Microcontroller projects

Arduino tips and tricks

last updated: 01/05/20

Introduction

Arduino means a lot of things.

There is the Arduino IDE, and the Arduino programming language (C++) and the Arduino boards. Here some links, if the page gets too long:



Arduino IDE

Install Arduino portable on a USB Stick

Download the latest Arduino software from Arduino.cc and extract the compressed folder. You can do this on a USB Stick. Now switch to the Arduino folder and create a folder with the name portable inside the Arduino folder. A portable installation allows to carry around your personal set of sketches, cores and libraries, to be used on any computer without affecting it with your files (see here).

Teensy

Download the newest Teensyduino version from pjrc.com and follow the instructions on this page to install it.

ESP32, ESP8266 and other cores

To be able to use Arduino with ESP32 we add the ESP32 framework simply by adding a text line to to File > Preferences > Additional Boards Manager URLs:.

ESP32

Enter the string

https://dl.espressif.com/dl/package_esp32_dev_index.json

into Additional Board Manager URLs: field. You can add multiple URLs, separating them with commas.

ESP8266

So we also add the string

http://arduino.esp8266.com/stable/package_esp8266com_index.json

for ESP8266.

ATmega chips by MCUdude

If you want to Arduinoize one of the following chips:

MightyCore MegaCore MiniCore
---------- ---------- ----------
ATmega1284 ATmega2561 ATmega8
ATmega644 ATmega2560 ATmega48
ATmega324 ATmega1281 ATmega88
ATmega164 ATmega1280 ATmega168
ATmega32 ATmega640 ATmega328
ATmega16 ATmega128
ATmega8535 ATmega64
AT90CAN128
AT90CAN64
AT90CAN32

add the Core needed by MCUdude (Hans). Thanks Hans for your work!!

https://mcudude.github.io/MightyCore/package_MCUdude_MightyCore_index.json
https://mcudude.github.io/MiniCore/package_MCUdude_MiniCore_index.json
https://mcudude.github.io/MegaCore/package_MCUdude_MegaCore_index.json

After adding the json strings, we need to install the files. For this open the Boards Manager from Tools > Board > Boards Manager.... Scroll down and click on install for the needed platform. After installation is complete, restart Arduino.

Now we can select our Board from Tools > Board.

UDEV rules

In Linux we need to set up the udev rules to access our devices without being root. The text file name begins with a number (01-99) defining the ranking and ends with .rules (e.g. 15-lolin_wemos.rules). It has to be copied to /etc/udev/rules.d. Reboot your computer after changing rules.

Here a udev file for several mc's: (14-my_mc_rules.rules)

    # Teensy by Paul https://www.pjrc.com/teensy/49-teensy.rules
    ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789]?", ENV{ID_MM_DEVICE_IGNORE}="1"
    ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789]?", ENV{MTP_NO_PROBE}="1"
    SUBSYSTEMS=="usb", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789]?", MODE:="0666"
    KERNEL=="ttyACM*", ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="04[789]?", MODE:="0666"
    # FTDI 232
    SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="0666"
    SUBSYSTEMS=="usb", ATTRS{idVendor}=="067b", ATTRS{idProduct}=="2303", MODE="0666"
    # LOLIN Wemos D1 mini, ESP32 (QinHeng Electronics HL-340 USB-Serial adapter)
    SUBSYSTEMS=="usb", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", GROUP="plugdev", MODE="0666"
    # LOLIN D1 mini pro
    SUBSYSTEMS=="usb", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", GROUP="plugdev", MODE="0666"
    # atmega32u4 DFU
    SUBSYSTEM=="usb", ATTR{idVendor}=="03eb", ATTR{idProduct}=="2ff4", GROUP="plugdev", MODE="0660"
    # at90usb1286/1287 AVR DFU
    SUBSYSTEM=="usb", ATTR{idVendor}=="03eb", ATTR{idProduct}=="2ffb", GROUP="plugdev", MODE="0660"
    # Atmel weigu_vendor (AT90usbkey Saleski)
    SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="0001", GROUP="plugdev", MODE="0666"
    SUBSYSTEMS=="usb", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="0002", GROUP="plugdev", MODE="0666"

If you have a board with a new chip, get the idVendor and the idProduct with the command:

     lsusb

and expand the file.

Arduino programming

Programming

In Arduino the C or C++ code files are named "sketch" have the extension .ino and must be contained in a folder with the same name (without .ino).

You find your sketches in the folder portable/sketchbook in your Arduino folder. If you open a new sketch (xxx.ino) without folder (File > Open), Arduino will create the folder for you.

After opening a sketch (File > Open, File > Sketchbook or File > Examples) we click on the Arduino Upload button arrow to the right to compile and upload the sketch.

Hex and list files

In Linux, the hex file can be found in the /tmp directory. If compiling for Teensy we find a .lst file containing the assembler code. For the other Arduino boards this file is missing. We can get it from the .elf file with the following command:

    avr-objdump -S Blink.ino.elf > list.txt

Libraries

We often need external libraries for our sensors. To install a library in Arduino is quite simple.

In newer Arduino versions click on : Tools > Manage Libraries... (older versions: sketch > Iclude Library > Manage Libraries...). In the search-field you type the name of your sensor or library. Often you can chose between more libraries. After installing the library look at the library examples in File > Examples.

To install a library that is not found with Arduino search, we download the library as .zip-file (e.g. github) and install it with Sketch > Include Library > Add .ZIP Library....

Non blocking delay

With the millis()-function we can create a non blocking delay. Here is a little example how to do it with a function to increase the reading of the program:

    // non blocking delay (weigu.lu)

    const unsigned long DELAY_MS = 200;

    void setup() {
      pinMode(LED_BUILTIN, OUTPUT);
    }

    void loop() {
      if (non_blocking_delay(DELAY_MS)) {
        toggle_led(LED_BUILTIN);
      }
      // do here whatever you want :)
    }

    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;
    }

    void toggle_led(byte pin) {
      if (digitalRead(pin)) {
        digitalWrite(pin, LOW);
      }
      else {
        digitalWrite(pin, HIGH);
      }
    }

Sometimes we need more delays. So we quit bool and return the case within a byte:

    // non blocking delay x3 (weigu.lu)

    const byte PIN_LED2 = 2;
    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 here whatever you want :)
    }

    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;
    }

    void toggle_led(byte pin) {
      if (digitalRead(pin)) {
        digitalWrite(pin, LOW);
      }
      else {
        digitalWrite(pin, HIGH);
      }
    }