/* When selecting the ATtiny 25/45/85 in the board, Ensure that in the tools menu, the processor is set to ATtiny 85, with an 8 MHz clock. otherwise you will run out of resources as it will consider the slected board to be a ATtiny 25.
See https://wokwi.com/projects/290883003139228169 and https://docs.wokwi.com/guides/serial-monitor
https://blog.jloh02.dev/projects/connecting-attiny85-serial-monitor/
https://www.instructables.com/How-to-Program-an-Attiny85-From-an-Arduino-Uno/
https://www.best-microcontroller-projects.com/attiny85.html
*/
#include <Arduino.h>
#include "ArduinoUniqueID.h"
#include "Adler16.h"
#include <SoftwareSerial.h>
#define PWM_PIN PB2
#define STATUS_PIN PB4
#define SERIAL_TX PB0
#define SERIAL_RX PB3
#define SERIAL_DIR PB1
#define SERIAL_PORT_SPEED 115200
#define CompileDate __DATE__
#define CompileTime __TIME__
#define LED_DELAY 1000
bool switchLED = false;
unsigned long timerLED = 0;
String Serial_Number;
String serialResponse;
String MQTTtopic;
String MQTTmessage;
int8_t delimiterLocation;
uint8_t PWM_Value = 255;
const char delimiter = ':'; // use '' NOT ""
const uint8_t PROGMEM gamma8[] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
90, 92, 93, 95, 96, 98, 99, 101, 102, 104, 105, 107, 109, 110, 112, 114,
115, 117, 119, 120, 122, 124, 126, 127, 129, 131, 133, 135, 137, 138, 140, 142,
144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 167, 169, 171, 173, 175,
177, 180, 182, 184, 186, 189, 191, 193, 196, 198, 200, 203, 205, 208, 210, 213,
215, 218, 220, 223, 225, 228, 231, 233, 236, 239, 241, 244, 247, 249, 252, 255
};
SoftwareSerial mySerial(SERIAL_RX, SERIAL_TX);
Adler16 adler16;
void setup()
{
pinMode(PWM_PIN, OUTPUT);
pinMode(STATUS_PIN, OUTPUT);
pinMode(SERIAL_DIR, OUTPUT);
pinMode(SERIAL_TX, OUTPUT);
pinMode(SERIAL_RX, INPUT);
for (size_t i = 0; i < UniqueIDsize; i++)
{
Serial_Number += String(UniqueID[i], HEX);
}
Serial_Number.toUpperCase();
adler16.begin();
for (int j = 0; Serial_Number[j] != 0; j++)
{
adler16.add(Serial_Number[j]);
}
String adler16_serial = String(adler16.getAdler(), HEX);
adler16_serial.toUpperCase();
Serial_Number = adler16_serial;
mySerial.begin(SERIAL_PORT_SPEED);
mySerial.println(Serial_Number);
}
void loop()
{
if (millis() - timerLED >= LED_DELAY) {
timerLED = millis();
switchLED = !switchLED;
digitalWrite(STATUS_PIN, switchLED ? HIGH : LOW);
}
if (mySerial.available() != 0)
{
serialResponse = mySerial.readStringUntil('\n'); // read the incoming data as string until newline character
delimiterLocation = serialResponse.indexOf(delimiter); // find the location of the delimiter character
mySerial.print(F("response: "));
mySerial.println(serialResponse);
mySerial.print(F("delim loc: "));
mySerial.println(delimiterLocation);
if (delimiterLocation != -1) // make sure the delimiter was found
{
MQTTtopic = serialResponse.substring(0, delimiterLocation); // extract the topic
if (MQTTtopic == Serial_Number)
{
MQTTmessage = serialResponse.substring(delimiterLocation + 1); // extract the message
uint8_t value = MQTTmessage.toInt() ;
if (value >= 0 && value <= 255) // Is the message an int between 0 and 255?
{
PWM_Value = pgm_read_byte(&gamma8[value]); // Do the gamma conversion and save the PWM_Value as the light level
}
}
}
mySerial.print(MQTTtopic);
mySerial.print(MQTTmessage);
mySerial.println(F("..."));
}
analogWrite(PWM_PIN, PWM_Value);
}Status
PWM
Serial DIR