last updated: 2023-10-29
First I thought I could make a library with my custom functions, an this library would solve all my problems :).
But then I noticed it made programs often less clear. For most programs that are not too big I like to use the Arduino IDE because simplicity is important for beginners and students (and me :)). So I decided to document here code snippet that I use quite often.
I think these are quite self-explaining. It is possible to change the logic, as some BUILTIN LED's use negative logic.
// cs_led_helper_functions.ino
// weigu.lu
const byte LED_PIN = LED_BUILTIN; // LED_BUILTIN or other pin
bool LED_LOGIC = 1; // positive logic: 1, negative logic: 0
const unsigned long DELAY_MS = 3000;
const unsigned long LED_BLINK_DELAY_MS = 100;
void setup() {
init_led();
}
void loop() {
blink_led_x_times(3,LED_BLINK_DELAY_MS);
delay(DELAY_MS);
}
/****** LED HELPER functions *************************************************/
// initialise the build in LED and switch it on
void init_led() {
pinMode(LED_PIN,OUTPUT);
led_on();
}
// LED on
void led_on() {
LED_LOGIC ? digitalWrite(LED_PIN,HIGH) : digitalWrite(LED_PIN,LOW);
}
// LED off
void led_off() {
LED_LOGIC ? digitalWrite(LED_PIN,LOW) : digitalWrite(LED_PIN,HIGH);
}
// blink LED x times (LED was on) with delay_time_ms
void blink_led_x_times(byte x, word delay_time_ms) {
for(byte i = 0; i < x; i++) { // Blink x times
led_off();
delay(delay_time_ms);
led_on();
delay(delay_time_ms);
}
}
// toggle LED
void toggle_led(byte pin) {
digitalRead(pin) ? digitalWrite(pin, LOW) : digitalWrite(pin, HIGH);
}
With the millis()
-function we can create a non blocking delay. With the following function it gets simpler by using a static variable in the function:
// cs_non_blocking_delay.ino
// weigu.lu
const byte LED_PIN = LED_BUILTIN; // LED_BUILTIN or other pin
bool LED_LOGIC = 1; // positive logic: 1, negative logic: 0
const unsigned long NON_BLOCKING_DELAY_MS = 3000;
const unsigned long LED_BLINK_DELAY_MS = 100;
void setup() {
init_led();
}
void loop() {
if (non_blocking_delay(NON_BLOCKING_DELAY_MS)) {
blink_led_x_times(3,LED_BLINK_DELAY_MS);
}
// do here whatever you want :)
}
// non blocking delay using millis(), returns true if time is up
bool non_blocking_delay(unsigned long milliseconds) {
static unsigned long nb_delay_prev_time = 0;
if(millis() >= nb_delay_prev_time + milliseconds) {
nb_delay_prev_time += milliseconds;
return true;
}
return false;
}
/****** LED HELPER functions *************************************************/
...
Sometimes we need more delays. So we quit the returning bool variable and return the case within a byte:
// cs_non_blocking_delay_x3.ino
// weigu.lu
const byte PIN_LED2 = 2;// non blocking delay using millis(), returns true if time is up
const byte PIN_LED3 = 3;
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
pinMode(PIN_LED2, OUTPUT);
pinMode(PIN_LED3, OUTPUT);
}
void loop() {
switch (non_blocking_delay_x3(100, 200, 400)) {
case 1:
toggle_led(LED_BUILTIN);
break;
case 2:
toggle_led(PIN_LED2);
break;
case 3:
toggle_led(PIN_LED3);
break;
case 0:
break;
}
// do whatever you want here
}
byte non_blocking_delay_x3(unsigned long ms_1, unsigned long ms_2,
unsigned long ms_3) {
static unsigned long nb_delay_prev_time_1 = 0;
static unsigned long nb_delay_prev_time_2 = 0;
static unsigned long nb_delay_prev_time_3 = 0;
unsigned long millis_now = millis();
if(millis_now >= nb_delay_prev_time_1 + ms_1) {
nb_delay_prev_time_1 += ms_1;
return 1;
}
if(millis_now >= nb_delay_prev_time_2 + ms_2) {
nb_delay_prev_time_2 += ms_2;
return 2;
}
if(millis_now >= nb_delay_prev_time_3 + ms_3) {
nb_delay_prev_time_3 += ms_3;
return 3;
}
return 0;
}
// toggle LED
void toggle_led(byte pin) {
digitalRead(pin) ? digitalWrite(pin, LOW) : digitalWrite(pin, HIGH);
}
// cs_convert_cstring_w_bytes_2_bytes.ino
// convert a C-string with hex bytes to real bytes
// weigu.lu
char c_string[] = "53414767700067C800000782"; // the c_string
void setup() {
Serial.begin(115200);
delay(2500);
Serial.println("Serial ok");
Serial.print("The c_string: \"");
Serial.print(c_string);
byte byte_array_size = strlen(c_string)/2;
byte byte_array[byte_array_size]; // the byte array with half the size
c_string_hexbytes_2_bytes(c_string, byte_array); // array passed by ref
Serial.print("\"\nThe byte array in hex: ");
for (int i=0; i<12; i++) {
Serial.print(byte_array[i],HEX);
Serial.print(" ");
}
}
void loop() {
}
// convert a C-string with hex bytes to real bytes
void c_string_hexbytes_2_bytes(char c_string[], byte byte_array[]) {
byte tmp_array_size = strlen(c_string);
byte tmp_array[tmp_array_size];
for (byte i=0; i<tmp_array_size; i++) {
if ((c_string[i]>='A') && (c_string[i]<='F')) tmp_array[i] = byte(c_string[i]-55);
else if ((c_string[i]>='a') && (c_string[i]<='f')) tmp_array[i] = byte(c_string[i]-87);
else if ((c_string[i]>='0') && (c_string[i]<='9')) tmp_array[i] = byte(c_string[i]-48);
else {
Serial.println("error init IV");
return -1;
}
if (i%2==1) { // i odd (every second character)
byte_array[(i-1)/2] = byte((tmp_array[i-1]*16)+tmp_array[i]);
}
}
}
// cs_convert_cstring_2_hex_cstring.ino
// convert a C-string to C-string with hex values
// weigu.lu
char mytext[] = "BTS-IoT2";
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("Monitor alive\n");
char hex_text[strlen(mytext)*2]; // C-string with double length
cstring_2_hex_cstring(mytext, hex_text);
Serial.print("\"");
Serial.print(mytext);
Serial.print("\" gives us the following Hex C-string: \"");
Serial.print(hex_text);
Serial.println("\"");
}
void loop() {
}
// convert a C-string to C-string with hex values
void cstring_2_hex_cstring(char text[], char hextext[]) {
for (byte i=0; i<strlen(text); i++) {
hextext[i*2] = (text[i] >> 4) & 0x0F; // high nibble
hextext[i*2] <= 9 ? hextext[i*2] += 0x30 : hextext[i*2] += 0x37;
hextext[i*2+1] = text[i] & 0x0F; // low nibble
hextext[i*2+1] <= 9 ? hextext[i*2+1] += 0x30 : hextext[i*2+1] += 0x37;
}
}
// cs_convert_unsigned_long_2_hex_cstring.ino
// convert an unsigned long number to C-string with hex values
// weigu.lu
unsigned long mynumber = 0x12345678; // 4 Byte
void setup() {
Serial.begin(115200);
delay(3000);
Serial.println("Monitor alive\n");
char mybuff[8];
ulong_2_hex_cstring(mynumber, mybuff);
Serial.print("The number ");
Serial.print(mynumber);
Serial.print(" (0x");
Serial.print(mynumber,HEX);
Serial.print(") gives us the following Hex C-string: \"");
Serial.print(mybuff);
Serial.println("\"");
}
void loop() {
}
// convert an unsigned long number to C-string with hex values
void ulong_2_hex_cstring(unsigned long number, char hextext[]) {
byte d;
for (short i=3; i>=0; i--) {
d = number%256;
number = number/256;
hextext[i*2] = (d >> 4) & 0x0F; // high nibble
hextext[i*2] <= 9 ? hextext[i*2] += 0x30 : hextext[i*2] += 0x37;
hextext[i*2+1] = d & 0x0F; // low nibble
hextext[i*2+1] <= 9 ? hextext[i*2+1] += 0x30 : hextext[i*2+1] += 0x37;
}
}
We can choose one of two functions. One function needs only the date. The other needs also the day of week, so a third function calculates the day of week from the date.
// cs_get_daylight_saving_time.ino
// weigu.lu
#include <TimeLib.h>
String dow_str[] = {"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"};
void setup() {
Serial.begin(115200);
setTime(10,0,10,28,10,23); // set UTC: hr,min,sec,day,month,year
Serial.println("UTC: " + String(year()) + '-' + str_02u(String(month())) + '-' +
str_02u(String(day())) + 'T' + str_02u(String(hour())) + ':' +
str_02u(String(minute())) + ':' + str_02u(String(second())));
int dow = day_of_week(day(),month(),year());
Serial.print("Day of week: " + dow_str[dow]);
Serial.print(" Daylight_saving: f1: " + String(is_daylight_saving_time_from_dow(day(),month(),dow)));
Serial.println(" f2: " + String(is_daylight_saving_time(day(),month(),year())));
time_t t = now();
if (is_daylight_saving_time(day(),month(),year())==1) {
t = t + 7200;
}
else {
t = t + 3600;
}
setTime(t);
Serial.println("Corrected time: " + String(year()) + '-' + str_02u(String(month())) + '-' +
str_02u(String(day())) + 'T' + str_02u(String(hour())) + ':' +
str_02u(String(minute())) + ':' + str_02u(String(second())));
}
void loop() {
}
// add leading zero to string with 1 digit
String str_02u(String s) {
if (s.length()==1) {
s = '0' + s;
}
return s;
}
// calculate day of week from date (Zeller’s Congruence method)
// 6 = Saturday, 0 = Sunday, 1 = Monday, …, 5 = Friday
int day_of_week(int d, int m, int y) {
int dow = ((d + int(2.6 * (((m + 12 - 3) % 12) + 1) - 0.2) - 40 +
(m < 3 ? y-1 : y) + int((m < 3 ? y-1 : y)/4) + 5)-1) % 7;
return dow;
}
// for europe needing day of week (1 = monday)
bool is_daylight_saving_time_from_dow(int d, int m, int dow) {
int previous_sunday = d - dow;
if (m < 3 || m > 10) return false;
if (m > 3 && m < 10) return true;
if (m == 3) return previous_sunday >= 25;
if (m == 10) return previous_sunday < 25;
}
// for europe
bool is_daylight_saving_time(int d, int m, int y) {
byte y2 = y % 100;
byte x1 = 31 - (y2 + y2 / 4 - 2) % 7; //last Sunday March
byte x2 = 31 - (y2 + y2 / 4 + 2) % 7; // last Sunday October
if ((m > 3 && m < 10) || (m == 3 && d >= x1) || (m == 10 && d < x2)) {
return 1;
}
else {
return 0;
}
}