title: Keeping track of multiple actions

text:
# Question
Title: Keeping track of multiple actions
I have a number of LED's connected to an Arduino which receives a JSON dict.

The JSON dict determines which action the LED's follow (either a fade, a pulse, on, or off), but I'm having trouble working out how to get one LED to flash whilst another fades etc.

The important parts of the code looks like this:

```
int led_choice;
int led_brightness;
String pattern_name;
int pattern_length;

// Timer Setup
unsigned long led1_current_time;
unsigned long led2_current_time;
unsigned long previousFadeMillis[2];
unsigned long previousPulseMillis[2];
unsigned long current_time;

// fade setup
int fadeInterval = 50;
int fadeIncrement = 5;
int fadeDirection = 1;
int fadeValue = 0;
int maxPWM = 255;
int minPWM = 0;
int translated_pin;

// Pulse setup
int pulse_state = 0;

void setup() {
  pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
  Serial.begin(115200);
}

void loop() {

  current_time = millis();

  // CODE HERE TO READ SERIAL/MQTT, DECIPHER JSON AND EXTRACT VARIABLES

  if ( pattern_name == "fade"){
    fade(current_time, pattern_length, led_brightness, led_choice);
  } else if ( pattern_name == "pulse"){
    pulse(current_time, pattern_length, led_brightness, led_choice);
  }
  else if (pattern_name == "on" )
  {
    solid_running(led_choice, led_brightness);
  }
  else {
    switch_off(led_choice);
  }
}

/********** LED CONTROL FUNCTIONS *********/
void fade(unsigned long thisMillis, int fadeInterval, int maxPWM, int led_pin) {
  if (thisMillis - previousFadeMillis[led_pin] >= fadeInterval) {
    // yup, it's time!
    if (fadeDirection == 1) {
      fadeValue = fadeValue + fadeIncrement;
      if (fadeValue >= maxPWM) {
        // At max, limit and change direction
        fadeValue = maxPWM;
        fadeDirection = 0;
      }
    } else {
      //if we aren't going up, we're going down
      fadeValue = fadeValue - fadeIncrement;
      if (fadeValue <= minPWM) {
        // At min, limit and change direction
        fadeValue = minPWM;
        fadeDirection = 1;
      }
    }
    // Only need to update when it changes
    analogWrite(led_pin, fadeValue);
    // reset millis for the next iteration (fade timer only)
    previousFadeMillis[led_pin] = thisMillis;
  }
}

void pulse(unsigned long thisMillis, int on_duration, int on_speed, int led_pin){
  if (thisMillis - previousPulseMillis[led_pin] >= on_duration) {
    // save the last time you blinked the LED
    previousPulseMillis[led_pin] = thisMillis;

    // if the led is off turn it on and vice-versa:
    if (pulse_state == 0) {
      pulse_state = 1;
      // set the led with the ledState of the variable:
      analogWrite(led_pin, 255);
    } else {
      analogWrite(led_pin, 0);
      }
      pulse_state = 0;
    }
  }
}

void switch_off(int led_pin){
    analogWrite(led_pin, 0);
}

void solid_running(int led_pin, int led_brightness){
    analogWrite(led_pin, led_brightness);
}

```

If I send the json data telling LED 1 to pulse, as soon as I send a second string telling LED2 to fade, LED 1 stops pulsing.

I'm sure this is something obvious, but it's been driving me mad for days!

*EDIT: Adding the second attempt at this*

```
// Declare the number of LED's
const int led_count = 2;

// Setup the ENUM for the various Modes
enum EMode { Off, On, Pulse, Fade };
// Create the struct and initialise it
struct MMode {
  EMode pin_mode;
  int action_pin;
  int action_delay;
  int action_max;
  int action_min;
  int fade_direction;
  int fade_value;
  int fade_increment;
  unsigned long m_current_time;
  unsigned long previous_millis;
} leds[led_count] {
  {Fade, D4, 20, 255, 0, 1, 0, 1, 0, 0},
  {Fade, BUILTIN_LED, 20, 255, 0, 1, 0, 1, 0, 0}
};

void setup() {
  Serial.begin(9600);
  // Setup the Built-in LED
  pinMode(BUILTIN_LED, OUTPUT);
  // Setup the Red LED
  pinMode(D4, OUTPUT);
}

void loop() {
    for (int n = 0; n < led_count; n++) {
      leds[n].m_current_time = millis();
      switch(leds[n].pin_mode){
        case Fade:
          fade(leds[n]);
          break;
      }
    }
}

/********** LED CONTROL FUNCTIONS *********/
void fade(struct MMode led) {
  if (led.m_current_time - led.previous_millis >= led.action_delay) {
    // yup, it's time!
    if (led.fade_direction == 1) {
      led.fade_value = led.fade_value + led.fade_increment;
      Serial.print("Fade Up Value: ");
      Serial.print(led.fade_value);
      Serial.println("    ");
      if (led.fade_value >= led.action_max) {
        // At max, limit and change direction
        led.fade_value = led.action_max;
        led.fade_direction = 0;
      }
    } else {
      //if we aren't going up, we're going down
      led.fade_value = led.fade_value - led.fade_increment;
    //  Serial.print("Fade Down Value");
    //  Serial.print(led.fade_value);
    //  Serial.print("    ");
      if (led.fade_value <= led.action_min) {
        // At min, limit and change direction
        led.fade_value = led.action_min;
        led.fade_direction = 1;
      }
    }
    //Serial.print(led.fade_value);
    //Serial.print("  ");
    // Only need to update when it changes
    analogWrite(led.action_pin, led.fade_value);
    // reset millis for the next iteration (fade timer only)
    led.previous_millis = led.m_current_time;
    //Serial.print(led.previous_millis);
    //Serial.print("  ");
  }
}

```

This second iteration of the code appears to define the led's using the struct correctly, however when I upload it to the arduino, motor.fade\_value gets set to 1, and never increments above this.

I get the feeling I'm missing something from the answers that I've had so far, but I'm not sure what that something is, and google isn't proving very helpful tonight...

# Answer
you need to call the fade/pulse function every time until the led state's change,

Start by creating full separate state for each LED,

```
struct LED_state{
    STATE state;

    unsigned long led1_current_time;
    unsigned long previousMillis;
    int pin;
    int fadeValue;
    int fadeDirection;
    int pulse_state = 0;
}

LED_state led[2];

```

`STATE` is an enum for each animation you do. Change the functions to take a pointer to this state. Initialize them in `init()`.

Then create an update function which looks like:

```
void updateLED(LED_state* state){
    switch(state->state){
    case FADE:  fade(state);break;
    case PULSE: pulse(state);break;
    case ON:    solid_running(state);break;
    case OFF:   switch_off(state);break;
    }
}

```

Every time through the loop you call this update function for each LED's state.

To change what the LED does you the only need to update the state member in the struct for the LED.

```
  if ( pattern_name == "fade"){
    led[chosen_led]->state = FADE;
  } else if ( pattern_name == "pulse"){
    led[chosen_led]->state = PULSE;
  } else if (pattern_name == "on" ){
    led[chosen_led]->state = ON;
  } else {
    led[chosen_led]->state = OFF;
  }

```
> 1 votes

# Answer
Without looking to the entire code, the best way is to use a 'mode' for each led. So for each led, keep track how it should behave (like Off, On, Blink, FadeOff, FadeOn etc) and some parameters (for the speed for fading for example). You can use a struct for this, like

```
enum EMode { Off, On, Pulse, FadeOff, FadeOn };
struct LedMode
{
   EMode mode;
   int fadeSpeed; // Only used when mode = fade off/on
};

LedMode ledModes[8]; // For e.g. 8 leds

```

When you get a JSon command, change the ledMode structure for that LED accordingly.

Than in the main loop use something like:

```
loop()
{
    for (int n = 0; n < 8; n++) // For each led
    {
       switch (ledModes[n].mode)
       {
       case Off:
         TurnOff(ledModes[n]);
         break;

       case On:
          TurnOn(ledModes[n]);
          break;

       case Pulse:
          Pulse(ledModes[n]);
          break;

       case FadeOn:
          FadeOn(ledModes[n]);
          break;

       ...
    }
}

```

To prevent going into each case all the time, add in the structure a 'Dirty' flag which is set to true by JSON and set to false after performed the change (e.g. you only have to switch a LED On or Off one time, not in every loop). For FadeOn/Off until it has reached 255 or 0. You also can use a PreviousMode and check if the mode has been changed since last time.

And for the Pulse/FadeOn/Off you need to add in the structure the last set value to be able to increase/decrease it, and the time it has changed last time.

Btw, you also can pass n and get LedModes\[n\] directly since it is global.
> 2 votes

---
Tags: led
---


# Question
Title: 'dynamic_cast' not permitted with -fno-rtti
```
class A {
    virtual ~A();
}

class B : public A {
    public:
      int foo;
}

void bar(A *foo_){
    B* b = dynamic_cast<B*>(foo_);

    if(b != nullptr){
         cout << (*foo_)->foo << endl;
    }
}

int main(){
    B b{};
    bar(b);
}

```

Compiling error:

```
error: 'dynamic_cast' not permitted with -fno-rtti

```

I thank sincerely for the help.

# Answer
It seems avr-gcc version 4.9.2 that is used by the Arduino IDE has been compiled without RTTI support. It defaults to `-fno-rtti`, and if you try turning it on with `-frtti` you just get other horrible linker error messages instead.

So it looks like you can't use `dynamic_cast` on AVR boards.

Googling around it looks like numerous people have tried to enable FTTI on Arduino, but they have either failed and given up, or they have succeeded and never bothered to tell anyone else how they did it (numerous forum posts of "how do you do this?", a bit of discussion, and then they tail off...)

The solution? Either don't use RTTI, or use a more capable microcontroller whose compiler has RTTI enabled.

One way to not use RTTI is to fake it yourself:

```
#define CLASS_A 1
#define CLASS_B 2

class A {
    public:
        virtual int classType() { return CLASS_A; }
};

class B : public A {
    public:
        virtual int classType() { return CLASS_B; }
        void bar() {
            Serial.println("Baaaah!");
        }
};

void foo(A *foo) {
    if (foo->classType() == CLASS_B) {
        B *foob = (B *)foo;
        foob->bar();
    } else {
        Serial.println("Sorry, I can't bar.");
    }
}

void setup() {
    Serial.begin(115200);
    A a;
    B b;
    foo(&a);
    foo(&b);
}

void loop() {
}

```

Output:

```
Sorry, I can't bar.
Baaaah!

```
> 2 votes

---
Tags: compile
---


# Question
Title: Occasional incorrect time returned by NTP
I have an Uno with CC3000 wifi shield and am trying to use the sntp.h library to get NTP time. I have been experimenting with a modified version of the ntpTest code from the library which fetches the time every minute. In the serial monitor I get the correct time MOST of the time. However at random intervals, the time will display 3 hours and 14 minutes ahead of the current MST time.

the SNTP client constructor looks like this:

```
sntp mysntp = sntp(NULL,"time.nist.gov", (short)(-7 * 60),(short)(-7 * 60), true);

```

The time will display correctly for two to ten minutes and then display one of the erroneous times once then revert to correct time.

**EDIT** Here is the pared down code from the Adafruit CC3000 WIFI shield ntpTest example. Note that the only reason I was getting the time so often was just teaching myself how it worked and I noticed this odd behavior. My intent was not to make an application that would, in the end, access NTP servers more than once per day.

```
    /***************************************************
  This is an example for the Adafruit CC3000 Wifi Breakout & Shield

  Designed specifically to work with the Adafruit WiFi products:
  ----> https://www.adafruit.com/products/1469

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Kevin Townsend & Limor Fried & Rick Lesniak for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

/*

This example does a test of the SNTP (Simple Network Time Protocol) client:
* Initialization
* SSID Scan
* AP connection
* DHCP printout
* SNTP time synchronization
* Extract and print current time and date information

*/

#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
//#include "utility/NetTime.h"
#include <string.h>
#include "utility/debug.h"
#include "sntp.h"

// These are the interrupt and control pins
#define ADAFRUIT_CC3000_IRQ   3  // MUST be an interrupt pin!
// These can be any two pins
#define ADAFRUIT_CC3000_VBAT  5
#define ADAFRUIT_CC3000_CS    10
// Use hardware SPI for the remaining pins
// On an UNO, SCK = 13, MISO = 12, and MOSI = 11
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
                                         SPI_CLOCK_DIVIDER); // you can change this clock speed but DI

#define WLAN_SSID       "CompsciWifi"   // cannot be longer than 32 characters!
#define WLAN_PASS       "005276DA"
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define WLAN_SECURITY   WLAN_SEC_WPA2

//Arguments to SNTP client constructor:
//  1 - Primary Network Time Server URL (can be NULL)
//  2 - Secondary Network Time Server URL (also can be NULL)
//  3 - Local UTC offset in minutes (US Eastern Time is UTC - 5:00
//  4 - Local UTC offset in minutes for Daylight Savings Time (US Eastern DST is UTC - 4:00
//  5 - Enable Daylight Savings Time adjustment (not implemented yet)
//
//sntp mysntp = sntp(NULL, "time.nist.gov", (short)(-7 * 60), (short)(-7 * 60), true);
sntp mysntp = sntp(NULL, "time-a.timefreq.bldrdoc.gov", (short)(-7 * 60), (short)(-7 * 60), true);

// Type SNTP_Timestamp is 64-bit NTP time. High-order 32-bits is seconds since 1/1/1900
//   Low order 32-bits is fractional seconds
SNTP_Timestamp_t now;

// Type NetTime_t contains NTP time broken out to human-oriented values:
//  uint16_t millis; ///< Milliseconds after the second (0..999)
//  uint8_t  sec;    ///< Seconds after the minute (0..59)
//  uint8_t  min;    ///< Minutes after the hour (0..59)
//  uint8_t  hour;   ///< Hours since midnight (0..23)
//  uint8_t  mday;   ///< Day of the month (1..31)
//  uint8_t  mon;    ///< Months since January (0..11)
//  uint16_t year;   ///< Year.
//  uint8_t  wday;   ///< Days since Sunday (0..6)
//  uint8_t  yday;   ///< Days since January 1 (0..365)
//  bool     isdst;  ///< Daylight savings time flag, currently not supported
NetTime_t timeExtract;

#define pF(string_pointer) (reinterpret_cast<const __FlashStringHelper *>(pgm_read_word(string_pointer)))

const prog_char   janStr[] PROGMEM = "January";
const prog_char   febStr[] PROGMEM = "February";
const prog_char   marStr[] PROGMEM = "March";
const prog_char   aprStr[] PROGMEM = "April";
const prog_char   mayStr[] PROGMEM = "May";
const prog_char   junStr[] PROGMEM = "June";
const prog_char   julStr[] PROGMEM = "July";
const prog_char   augStr[] PROGMEM = "August";
const prog_char   sepStr[] PROGMEM = "September";
const prog_char   octStr[] PROGMEM = "October";
const prog_char   novStr[] PROGMEM = "November";
const prog_char   decStr[] PROGMEM = "December";

PROGMEM const char* const monthStrs[] = { janStr, febStr, marStr, aprStr, mayStr, junStr,
                                          julStr, augStr, sepStr, octStr, novStr, decStr};

const prog_char   sunStr[] PROGMEM = "Sunday";
const prog_char   monStr[] PROGMEM = "Monday";
const prog_char   tueStr[] PROGMEM = "Tuesday";
const prog_char   wedStr[] PROGMEM = "Wednesday";
const prog_char   thuStr[] PROGMEM = "Thursday";
const prog_char   friStr[] PROGMEM = "Friday";
const prog_char   satStr[] PROGMEM = "Saturday";

PROGMEM const char* const dayStrs[] = { sunStr, monStr, tueStr,  wedStr,
                                        thuStr, friStr, satStr};

/**************************************************************************/
/*!
    @brief  Sets up the HW and the CC3000 module (called automatically
            on startup)
*/
/**************************************************************************/
void setup(void)
{
  Serial.begin(115200);
  Serial.println(F("Hello, CC3000!\n"));

  //Serial.print("Free RAM: "); Serial.println(getFreeRam(), DEC);

  /* Initialise the module */
  Serial.println(F("\nInitialising the CC3000 ..."));
  if (!cc3000.begin())
  {
    Serial.println(F("Unable to initialise the CC3000! Check your wiring?"));
    while(1);
  }

  /* Optional: Update the Mac Address to a known value */
/*
  uint8_t macAddress[6] = { 0x08, 0x00, 0x28, 0x01, 0x79, 0xB7 };
   if (!cc3000.setMacAddress(macAddress))
   {
     Serial.println(F("Failed trying to update the MAC address"));
     while(1);
   }
*/

  /* Delete any old connection data on the module */
  Serial.println(F("\nDeleting old connection profiles"));
  if (!cc3000.deleteProfiles()) {
    Serial.println(F("Failed!"));
    while(1);
  }

  /* Attempt to connect to an access point */
  char *ssid = WLAN_SSID;             /* Max 32 chars */
  Serial.print(F("\nAttempting to connect to ")); Serial.println(ssid);

  /* NOTE: Secure connections are not available in 'Tiny' mode! */
  if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
    Serial.println(F("Failed!"));
    while(1);
  }

  Serial.println(F("Connected!"));

  /* Wait for DHCP to complete */
  Serial.println(F("Request DHCP"));
  while (!cc3000.checkDHCP())
  {
    delay(100); // ToDo: Insert a DHCP timeout!
  }

  /*Serial.println(F("UpdateNTPTime"));
  if (mysntp.UpdateNTPTime())
  {
    Serial.println(F("Current local time is:"));
    mysntp.ExtractNTPTime(mysntp.NTPGetTime(&now, true), &timeExtract);*/

    /*Serial.print(timeExtract.hour); Serial.print(F(":")); Serial.print(timeExtract.min); Serial.print(F(":"));Serial.print(timeExtract.sec); Serial.print(F("."));Serial.println(timeExtract.millis);
    Serial.print(pF(&dayStrs[timeExtract.wday])); Serial.print(F(", ")); Serial.print(pF(&monthStrs[timeExtract.mon])); Serial.print(F(" ")); Serial.print(timeExtract.mday); Serial.print(F(", "));Serial.println(timeExtract.year);
    Serial.println(timeExtract.yday + 1);
  }

  /* You need to make sure to clean up after yourself or the CC3000 can freak out */
  /* the next time you try to connect ... */
  /*Serial.println(F("\n\nClosing the connection"));
  cc3000.disconnect(); */

    mysntp.UpdateNTPTime();
    mysntp.ExtractNTPTime(mysntp.NTPGetTime(&now, true), &timeExtract);
    Serial.print(pF(&dayStrs[timeExtract.wday])); Serial.print(F(", ")); Serial.print(pF(&monthStrs[timeExtract.mon])); Serial.print(F(" ")); Serial.print(timeExtract.mday); Serial.print(F(", "));Serial.println(timeExtract.year);
}

void loop(void)
{
    mysntp.UpdateNTPTime();
    mysntp.ExtractNTPTime(mysntp.NTPGetTime(&now, true), &timeExtract);
    Serial.print(timeExtract.hour); Serial.print(F(":")); Serial.print(timeExtract.min);

    delay(60000);
    Serial.println();
}

```

# Answer
> 1 votes
The updated NTP test sketch assumes that the communication with the NTP server will not fail but as the NTP protocol is based on UDP the reply package can be lost. A possible correction to the updated sketch is to check the return value from `UpdateNTPTime()`.

```
void loop(void)
{
    if (mysntp.UpdateNTPTime()) {
        mysntp.ExtractNTPTime(mysntp.NTPGetTime(&now, true), &timeExtract);
        Serial.print(timeExtract.hour);
        Serial.print(F(":"));
        Serial.println(timeExtract.min);
        delay(60000);
        Serial.println();
    }
}

```

Cheers!

---
Tags: wifi, time
---


# Question
Title: How to interface USB to custom Arduino Uno Schematic and programming atmega?
I'm fairly new to designing schematics and working with the atmega on its own and I'm designing an arduino schematic on eagle. Ive gotten to the stage where I need to incorporate a TTL USB interface in order to program the chip. I've just became aware that the arduino uses another avr chip to do so but it appears similar to the microcontroller and just need some clarification.

Since I want it all on one board like the arduino uno, my question is how is the USB-B connected to the microcontroller and how would I Incorporate it into my schematic?

Another question (out of curiosity) if I was to mass produce said PCB with one program on the atmega chip and leave out a USB module so people wouldnt be able to reprogram it (without taking the board apart obviously) How would that be done?

Heres a photo of my current schematic:

# Answer
> 1 votes
> Since I want it all on one board like the arduino uno my question is how is the USB-B connected to the microcontroller and how would i Incorporate in my schematic?

The USB interface forms a bridge between the USB connector and the UART of the "master" MCU. You don't have to use a microcontroller, but almost any UART to USB bridge chip will do the job. Common ones are the CH340G (cheap and unstable), CP2102, FT232, etc. The DTR signal from the USB chip is used to reset the main MCU.

You should look at the existing Uno schematics to see how the two chips are wired together.

> Another question (out of curiosity) if I was to mass produce said PCB with one program on the atmega chip and leave out a USB module so people wouldnt be able to reprogram it (without taking the board apart obviously) How would that be done?

You would program the board through the ICSP pins - in the same way that you put the bootloader on. Normally you'd invest in a proper programmer to connect up to the chip, but you can do it with an Arduino acting as the programmer.

---
Tags: programming, usb, atmega328
---


# Question
Title: Can you use a RF remote with nRF24L01 and Arduino?
I recently bought a 10 pack of RF transceivers (nRF24L01). I wanted to know if its possible to pair one with an RC drone controller. I can't seem to find any ways to do this through google.

If this helps:

My drone and its controller is called "Sky Viper v2400" and a link to where you buy it is: https://www.amazon.com/Sky-Viper-01601-Streaming-Video/dp/B01D1HRXSK.

Thanks

# Answer
The nRF24 operates in the 2.4GHz frequency and implements a proprietary protocol so, even if I don't have much information on your particular drone/controller, I strongly doubt there's a chance you can use the nRF24 module to talk to your drone.
> 1 votes

---
Tags: nrf24l01+, rf
---


# Question
Title: exit status 1 'Time' does not name a type
```
#include <DS3231.h>
#include <Wire.h>  // i2C Conection Library

// Init DS3231
DS3231  rtc;
// Init a Time-data structure
Time  t;
uint32_t targetTime = 0;

uint8_t hh = 0, mm = 0, ss = 0, dd = 0, bb = 0; //variable Unsignet int 0-255
int yy = 0; //variable integer
String Day = "  "; //variable string

void setup() {
  Serial.begin(115200);
}

void loop() {
  t = rtc.getTime(); // gate all data time & date from RTC
  Day = rtc.getDOWStr(); //get name of day
  hh = t.hour,DEC; //pengambilan data jam
  mm = t.min,DEC; //pengambilan data menit
  ss = t.sec,DEC; //pengambilan data detik
  dd = t.date,DEC; //pengambilan data hari
  bb = t.mon,DEC; //pengambilan data bulan (dalam desimal)
  yy = t.year,DEC; //pengambilan data tahun
  //Buka Serial Monitor Arduino untuk melihat hasilnya
  Serial.print (Day);
  Serial.print (F(" Time = "));
  Serial.print (hh); Serial.print (F(" : "));
  Serial.print (mm); Serial.print (F(" : "));
  Serial.print (ss); Serial.print (F("  Date = "));
  Serial.print (dd); Serial.print (F(" . "));
  Serial.print (bb); Serial.print (F(" . "));
  Serial.println (yy);
  delay (1000);
}

```

When I verify the code, this error appears:

> exit status 1
> 'Time' does not name a type

What does it mean?

# Answer
You don't mention which library you are using (which library does `#include <DS3231.h>` refer to?)

The DS3231 library here https://github.com/NorthernWidget/DS3231 defines a `DateTime` object which appears to have similar elements to what you are trying to access in 't' (hour, min, sec etc).

I would try defining 't' as a `DateTime` object.
> 1 votes

---
Tags: rtc
---


# Question
Title: Where in datasheet is the warning about unreliability of reading PINxn?
I use atmega32u4 (but believe it applies to all models). Here is the datasheet.

Consider the following C program (I use AVR-GCC 5.4.0):

```
#include <avr/io.h>
int main(void)
{
  PORTB |= 1 << PB5; /* pullup */
  DDRB |= 1 << PB0; /* LED */
  if (!(PINB & 1 << PB5))
    PORTB |= 1 << PB0; /* turn on LED */
  while (1) ;
}

```

There are two situations:

* connect a 10cm wire to PB5 pin (the other end of the wire is in the air): the result is that sometimes after poweron the led is on, sometimes the led is not on.
* do not connect anything to PB5 pin: the result is that after poweron led is never on.

I have a standard setup. Nothing tricky. If it does not work reliably, this gotcha **MUST** be documented in datasheet. This setup is supposed to deal with a stupid button. But sometimes it detects a keypress while there is no keypress.

The question is: where in datasheet there is a warning about this gotcha? And did somebody come across such case, or I'm the first in the world?

**EDIT** See also this question.

# Answer
> did somebody come across such case, or I'm the first in the world?

You are not the first. I recently got bitten by the very same issue.

However, unless you are close to an unusually strong radio source, I do not think it has anything to do with electromagnetic interference. In my experience, the internal pullup is perfectly reliable for reading switches and push buttons, even on a breadboard with jumper wires acting as antennas. If you use `pinMode()` and `digitalRead()` instead of direct port access, you too will find the internal pullup is perfectly fine.

Before I give you the answer (suspense...), let's look closely at what your code does. The disassembly looks like this:

```
main:
    sbi  PORTB, PB5 ; turn on pullup on PB5
    sbi  DDRB,  PB0 ; set LED pin as output
    sbis PINB,  PB5 ; read PB5, if it is LOW then:
    sbi  PORTB, PB0 ;   turn on LED
0:  rjmp 0b         ; hang in an infinite loop

```

In the situation when the LED turns on, every instruction there executes in two CPU cycles, save for `sbis`, which takes a single cycle in this case. Now, let's look at the timings, and specifically at the states of the pullup and the input circuitry during each of the first seven CPU cycles:

```
cycle   instruction   pullup latch PINB5
----------------------------------------
   1   sbi PORTB, PB5   off    X     X
   2      cont.         off    X     X
   3   sbi DDRB,  PB0   on     X     X
   4      cont.         on    LOW    X
   5   sbis PINB, PB5   on     X    LOW
   6   sbi PORTB, PB0   on     X     X
   7      cont.         on     X     X

```

In the table above, “X” means “don't care”. Each instruction takes effect at the beginning of the *next* CPU cycle, when the clock's rising edge commits the result of the instruction to the affected flip-flops. That's why the pullup turns on only at the beginning of cycle 3. Now, since the pin did read LOW, that means the PB5 flip-flop was LOW while the CPU was reading it, during cycle 5. This in turn means that the synchronizing latch before that flip-flop was LOW during cycle 4.

Your expectation was for the pin to read HIGH. So let's see: how fast should the pin voltage have risen in order for the pin to indeed read HIGH? Since the input latch is transparent during the first half of each cycle, this means that the voltage should raise past the Schmitt trigger's threshold during cycle 3 and the first half cycle 4. So the rise time should be less than 1.5 cycles. Or rather 1.5 cycles minus the combined propagation delay of the PORTB5 flip-flop and the logic that controls the pullup from that flip-flop's output. Probably around 90 ns. That's short!

By now you have probably guessed: the culprit is not electromagnetic interference, it's stray capacitance. A simple calculation will show you that about *three picofarads* is enough to produce the effect you are seeing. This is the kind of stray capacitance you will find everywhere, even between the PCB traces of your Arduino board. Note that electromagnetic noise can add some unpredictability to what you see, as the pin is susceptible to it when it's completely floating, i.e. *before* you turn on the pullup, which makes the initial voltage (at the beginning of cycle 3) unpredictable. But once the pullup is on and the pin has settled, you won't care about noise anymore, unless it's unusually strong.

The solution to your problem is simply to wait for the pullup to charge the stray capacitance. A microsecond delay should be enough to fix the issue. Alternatively, use the Arduino functions instead of direct port access: they are so slow that you will not need any extra delay.

> where in datasheet there is a warning about this gotcha?

In section 18.2.4 – Reading the Pin Value: “\[The synchronizing latch\] is needed to avoid metastability if the physical pin changes value near the edge of the internal clock, **but it also introduces a delay**.” (emphasis mine).

**Edit**: In a previous version of this answer, I incorrectly stated that `sbi` is a single cycle instruction, which required the voltage to rise in half a cycle instead of 1.5 cycles. The corrected timing is still short enough for stray capacitance to be a valid explanation of the observed behavior.

---

**In summary**:

* The stray capacitance attached to the pin, together with the pullup resistor, for an RC circuit.
* As the pin is initially floating, it's initial voltage is unpredictable.
* When the pullup is turned on, the voltage starts to rise from whatever initial value it had to 5 V.
* After some time, which can be typically of the order of the RC time constant, the input Schmitt trigger turns HIGH.
* After some extra delay introduced by the synchronizer, the PINxn flip-flop turns HIGH.
* If the CPU reads the PINx register before that happens, it gets a LOW reading.
> 6 votes

# Answer
A test with an Arduino Uno.

I used the usb connector to power-on the arduino uno. The led is at PB5, so I have exchanged PB0 and PB5. My test is therefor not the same.

```
#define LED_PB  PB5   // pin 13, onboard led
#define INP_PB  PB0   // pin 8, antenna

void setup(void)
{
  noInterrupts();
  PORTB |= 1 << INP_PB; /* pullup */
  DDRB |= 1 << LED_PB; /* LED */
  if (!(PINB & 1 << INP_PB))
    PORTB |= 1 << LED_PB; /* turn on LED */
  while (1) ;
}

void loop()
{
}

```

Using it next to my computer and phone, sometimes the led stays on. I can even find a spot behind my computer monitor (with CCFL backlight) where the led always turns on.

Then I went outside, away from metals, wifi, and so on. The air humidity outside is 70% at the moment, which is high. I put it on a wooden table, so there is no charge by plastic. I used a battery to power the arduino uno. Then the led **never** turns on.

In such a clean environment, the internal pullup resistor was probably strong enough to pull the pin high during that very short time.

@IgorLiferenko, @sa\_leinad gave the right answer. What you noticed is normal. It is totally normal. That behaviour can be expected. It will be worse when your circuit is not well designed.
A oscilloscope will not help. As soon as you connect a oscilloscope, you have changed something. It will also be very hard to detect that very short time (less than a microsecond).

In my opinion the influence by radio waves is only half of the problem. I think the electrical charge of the air, and the capacitive coupling of the wire with the air might have a larger effect.
> 3 votes

# Answer
You have made an antenna with the 10cm wire and are receiving radio waves which is translating to voltages on your input pin. This is why you don't have the same trouble when the wire is not connected.

According to www.csgnetwork.com/freqwavelengthcalc.html your 10cm wire is picking up frequencies of 750 MHz based on a quarter wavelength calculation.

The datasheet states that the internal pull up resistance is roughly between 20K - 50K ohms. As mentioned in the comments, this is quite weak.

There are two things that you can do that I can see:

The reason that this is not in the datasheet is because this is a general electronics/physics knowledge, not a characteristic of the micro-controller itself.
> 2 votes

# Answer
This actually is documented in the datasheet and illustrated by the logic diagram of the typical GPIO, to see what is really going on behind your compiled code you need to look at the generated assembly code and which registers are being accessed:

When you change one bit of an IO port, you are either modifying the 8 bit register on which that bit is mapped using the WRx signal or just the 1 bit register for the pin alone using the WPx signal. When you use the WPx signal to set or clear the bit, you don't need to know the states of the other pins so the discussion ends here. However, when you use the WRx signal to MODIFY a single bit, you need to know the states of the other 7 bits which means that your need to read the 8 bit port. You can either read the port LATCH using the RRx signal or you can read the actual physical pins using the RPx signal. Now when using the RRx signal, no amount of loading or noise on the pins themselves will affect what is read from the output of the port latch but when using the RPx signal, if a previous write to the port is followed by a read of the port, any parasitics or noise on the OUTPUT pins may cause a pin that you think that you just set to a one suddenly becomes a zero.

The reason this happens is because of how opcodes are pipelined. Writes to ports happen at the end of the last instruction clock but reads happen at the beginning so that there is essentially zero time between when you set that bit to a 1 and when you change some other bit (Read-modify-write fashion) so that bit is still a zero when it is read and then immediately written as a zero.

As illustrated below, this can be rectified by inserting a delay between write and read-modify-write opcodes to let the pin states stabilize. The delay must take into account the capacitive loading and noise environment
> -1 votes

---
Tags: atmega328, arduino-leonardo, atmega32u4, avr-gcc
---


title: Interrupts Problem with Flow sensor

text:
# Question
Title: Interrupts Problem with Flow sensor
```
 #include <Wire.h> //I2C lib
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
 // LCD lib
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

const int pot_pin = A0;
const int pump_pwm= 3;

int press_pin =A1;

//flowmeter parameters
int flowPin = 2;  // input pin on arduino D2

double flowRate;   // value intented to calculate
double flowR; // flow value in lt
double totalFlow; // total output of flow from system

byte sensorInterrupt = 0; // interrupt 0 on D2 pin Arduino Nano

volatile int count; ////integer needs to be set as volatile to ensure it updates correctly during the interrupt process.

int pot_init= 0;
int pump_init= 0;
int percentValue =0;

void setup() {

  lcd.begin(20,4);  // A4 - A5 connection SDA - SCL
  lcd.backlight();
  Serial.begin(9600);

  pinMode( flowPin,INPUT); // Set D2 pin as an input

  attachInterrupt(sensorInterrupt,Flow,RISING); // Configures interrupt 0 ( pin D2 on Arduino Nano ) to run function "Flow"
}

void flow_control(void) {

  count = 0; // reset counter so it could start counting from 0

  interrupts(); // enables interrupts on arduino nano
  delay(1000); // wait 1000 msec
  noInterrupts(); // disable interrupts on arduino nano

  //calculation for flowmeter

  flowR = (count*8.93);   // 112 pulse/lt 423.84 pulse /gallon
  flowRate= flowR*60;     // convert seconds to minutes, new unit is ml/minutes
  flowRate= flowRate/1000; // convert ml to liters, new unit is lt/minutes

  totalFlow += flowR;

  // Print the flow rate for this second in litres / minute
    Serial.print("Flow rate: ");
    Serial.print(int(flowRate));  // Print the integer part of the variable
    Serial.print("L/min");
    Serial.print("\t");       // Print tab space

    // Print the cumulative total of litres flowed since starting
    Serial.print("Output Liquid Quantity: ");
    Serial.print(totalFlow/1000);
    Serial.println("L");

    lcd.setCursor(0,2);
  lcd.print("Flow: ");
    lcd.setCursor(8,2);
  lcd.print(flowRate);
  lcd.print("lt/min");

  lcd.setCursor(0,3);
  lcd.print("Total: ");
  lcd.setCursor(8,2);
  lcd.print(totalFlow/1000);
  lcd.print("lt");

}

void Flow(void)
{
  count++; // every time this function is called, increment  "count" by 1
}

void loop() {

  pressure_cal();
  pump_control();
  flow_control();
  lcd_control();
}

void pressure_cal(void) {

  float sensorVoltage = analogRead(press_pin);   // sensor voltage A0
  float psi = ((sensorVoltage-102)/204)*25;  // Offset    0 PSI= 0.5V=102 unit, 50 PSI= 2.5, 100 PSI= 4.5V, 1 PSI= 0.04V

  // calibration
  float bar = psi*(0.0689475729);           // Conversion PSI to BAR

  lcd.setCursor (0,1);
  lcd.print (psi);
  lcd.print (" PSI");

  lcd.setCursor ( 10,1);
  lcd.print(bar);
  lcd.print( " BAR");

  //lcd.setCursor(17,1);
  //lcd.print(sensorVoltage);

  Serial.println (sensorVoltage);
  Serial.println(bar);
  Serial.println (psi);

  delay (100);
}

void pump_control(void)

{

  // read the analog in value:
  pot_init = analogRead(pot_pin);
  // map it to the range of the analog out:
  pump_init = map(pot_init, 0, 1023, 50, 230);  //  duty cycle between %20 - %90: speed control , duty cycle between %0 - %20: turned off  , duty cycle between %90 - %100: full speed
  // map pump speed percent of full scale
  percentValue = map (pump_init, 50, 230,0,100);
  // change the analog out value:
  analogWrite(pump_pwm, pump_init);

  // print the results to the Serial Monitor:
  Serial.print("\t Speed Input = ");
  Serial.print(pot_init);
  Serial.print("\t Speed Output = ");
  Serial.print(pump_init);
  Serial.print("\t Pump Speed Percentage = ");
  Serial.println(percentValue);

  lcd.setCursor(2,0);
  lcd.print("Speed: ");
  lcd.setCursor(8,0);
  lcd.print("%");
  lcd.setCursor(9,0);
  lcd.print(percentValue);
  lcd.print("     ");

 //  delay after the last reading:
  delay(2);

}

```

I try to write code including flow sensor, pressure sensor and pump. I wrote the code. But When I use interrupt , code stop. I used functions in " void loop()" . I moved the interrupt code ( flow\_control) between void setup and void loop. But I can see outputs in serial monitor but I cannot see on lcd. Could you help me fix the problem ?

# Answer
> 3 votes
A lot of peripheral libraries requires interrupts to be enabled, especially when they use timing or the I2C/SPI pins. Instead of disabling interrupts for the majority of the sketch, what you want to do is isolate disabling the interrupts to *just reading and resetting* the count variable:

```
noInterrupts(); // disable interrupts on arduino nano
local_count = count;
count=0;
interrupts(); // enables interrupts on arduino nano

```

Also all that processing takes some time which will skew the timing so it's better to use timestamp and millis:

unsigned long previous\_read;

```
if(millis() -  previous_read > 1000){
    noInterrupts(); // disable interrupts on arduino nano
    int local_count = count;
    count=0;
    interrupts(); // enables interrupts on arduino nano
    previous_read += 1000;

    //process flowrate based on local_count

}

```

---
Tags: arduino-uno, sensors, arduino-nano, interrupt
---


title: Problems with NodeMCU and Relay

text:
# Question
Title: Problems with NodeMCU and Relay
I've connected the MCU to a cheap chinese 24/12v to 5v car phone charger and hooked some wires to a relay.When I try to program doesn't matter if the pin is set to high or low , as soon as I touch the "IN" wire from the relay into any of the selected pins, the relay auto actives.

here is the schematic The charger input is hooked to a 12V drill battery for tests and the output to arduino is an usb port that I soldered wires to it's respective poles.

```
USB from Chinese charger Positive pole ------- NodeMcu Vin
USB from Chinese charger Negative pole ------- NodeMcu GND
USB from Chinese charger Positive pole ------- Relay   VCC
Relay Ground --------------------------------- NodeMcu Gnd
Relay DataPin -------------------------------- NodeMcu D0 or D1

```

And here's the code:

```
int port = D0;
int portB = D1;

void setup() {
Serial.begin(115200);
pinMode(port,OUTPUT);
pinMode(portB,OUTPUT);

digitalWrite(port,HIGH);
digitalWrite(portB,LOW);

}

void loop() {

}

```

But the result is that the relay will always be on activated ( IN pin = Low ) even connected to D0 that is high... Any ideas ?

# Answer
Does your nodemcu directly feed the relay? If so, 3.3v (nodemcu output high level) is not enough to activate it. I would use a transistor like a s8050 to Power it (do not forget the freewheel diode on the relay coil)
> 1 votes

---
Tags: nodemcu, relay
---


# Question
Title: Rc car which returns to middle when left or right button is not pressed
Hi i am currently working on a school project , my only problem is that i want my RC car to return to middle direction (which i have set to 66 in the servo motor) when the left or right button is not pressed . i used if statements but it doesn't work. Are there any function that i can use ? Here is my code for the transmitter i used the RC-Switch Library (https://www.arduinolibraries.info/libraries/rc-switch)

```
#include <RCSwitch.h>
#include <Servo.h>

const int IN1 = 3;
const int IN2 = 4;
const int trigPin = 5;
const int echoPin = 6;
const int Buzzer = 8;
int distance = 0;
int value = 0;
long duration;
RCSwitch mySwitch = RCSwitch();
Servo myservo;

void setup () {
  mySwitch.enableReceive(0);
  myservo.attach(7);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
  pinMode(echoPin, INPUT); // Sets the echoPin as an Input
  pinMode(Buzzer,OUTPUT);
  Serial.begin (9600);    // Debugging only
  Serial.println ("Receiver Ready");
}

void loop () {

  delayMicroseconds(10);
  // Clears the trigPin
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  // Sets the trigPin on HIGH state for 10 micro seconds
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  // Reads the echoPin, returns the sound wave travel time in microseconds
  duration = pulseIn(echoPin, HIGH);
  // Calculating the distance
  distance= duration*0.034/2;
  // Prints the distance on the Serial Monitor
  //Serial.print("Distance: ");
  //Serial.println(distance); //distance is the returned integer,

 if (mySwitch.available()) {

    value = mySwitch.getReceivedValue();
    Serial.println (value);

      if(value == 1) {
        forward ();
        Serial.println (" = forward");
      }

      if(value == 2){
        backward ();
        Serial.println (" = backward");
      }

      if(value == 3) {
        left ();
        Serial.println (" = left");
      }

      if(value == 4) {
        right ();
        Serial.println (" = right");
      }
      Serial.print(" ");
    }
  mySwitch.resetAvailable();
  //myservo.write(45);
}

void forward () {
  digitalWrite (IN1, LOW);
  digitalWrite (IN2, HIGH);
}

//value = mySwitch.getReceivedValue();
void backward () {

  if ((distance < 50)&& (value == '2'))
  {
    digitalWrite (IN1, LOW);
    digitalWrite (IN2, LOW);
    digitalWrite (Buzzer, HIGH);
  }
  else if ((distance > 50)&& (value == '2'))
  {
    digitalWrite (IN1, HIGH);
    digitalWrite (IN2, LOW);
    digitalWrite (Buzzer, LOW);
  }
}
// 66 is middle

void right () {
  if (value == 4){
    myservo.write(110);
  } else
  myservo.write(66);
}

void left () {
  if (value == 3){
    myservo.write(50);
  }else
 myservo.write(66);
}

```

And Here is The transmitter code

```
// TRANSMITTER CODE

#include <RCSwitch.h>
RCSwitch mySwitch = RCSwitch();
// Assigning controller buttons to Digital Pins
 int forward = 11;
 int reverse = 10;
 int rightTurn = 9;
 int leftTurn = 8;

void setup () {
  pinMode (forward, INPUT_PULLUP);
  pinMode (reverse, INPUT_PULLUP);
  pinMode (rightTurn, INPUT_PULLUP);
  pinMode (leftTurn, INPUT_PULLUP);
  mySwitch.enableTransmit(7);
  Serial.begin (9600);         // Debugging only
  Serial.println ("Transmitting");
}

void loop () {
  if (digitalRead(forward) == LOW) {
    mySwitch.send(1, 24);
    Serial.println ("Forward");
  }

  if (digitalRead(reverse) == LOW) {
    mySwitch.send(2, 24);
    Serial.println ("Reverse");
  }

  if (digitalRead(leftTurn) == LOW) {
    mySwitch.send(3, 24);
    Serial.println ("Left Turn");
  }

  if (digitalRead(rightTurn) == LOW) {
    mySwitch.send(4, 24);
    Serial.println ("Right Turn");
  }
}

```

# Answer
You send values from your transmitter when you press a button but not when you release them. The simplest solution would be sending the state of all buttons in every iteration if the transmitter has enough capacity. (I think it has for just these four values)

Add an enum to make the code more readable:

```
enum {
    FORWARD_ON = 0,
    FORWARD_OFF, // It will be 1.
    BACKWARD_ON, // It will be 2 and so on...
    BACKWARD_OFF,
    RIGHT_ON,
    RIGHT_OFF,
    LEFT_ON,
    LEFT_OFF
};

```

So a sending function will be like this:

```
if (digitalRead(forward) == LOW)
    mySwitch.send(FORWARD_ON, 24);
else
    mySwitch.send(FORWARD_OFF, 24);
// And so on for every button...

```

Then by reception you should add some state variables and store the received values:

```
int steer_right = 0;
int steer_left = 0;

// ...

loop() {

// ...

value = mySwitch.getReceivedValue();

switch (value) {
    case RIGHT_ON:
        steer_right = 1;
        break;
    case RIGHT_OFF:
        steer_right = 0;
        break;
    case LEFT_ON:
        steer_left = 1;
        break;
    case LEFT_OFF:
        steer_left = 0;
        break;

    // ... (throttle)

    default:
        break;
}

// ...

}

```

Then you evaluate what you got:

```
if (steer_right && !steer_left)
    right();
else if (!steer_right && steer_left)
    left();
else
    straight();

// ... (throttle)

```
> 1 votes

---
Tags: arduino-nano, motor, servo
---


# Question
Title: Do You Put a Break after the Last case in a Switch?
The Arduino Switch Case Reference has a switch structure written two different ways:

First in the Syntax as:

```
switch (var) {
  case label1:
    // statements
    break;
  case label2:
    // statements
    break;
  default:
    // statements
}

```

and then in the Example code as:

```
  switch (var) {
    case 1:
      //do something when var equals 1
      break;
    case 2:
      //do something when var equals 2
      break;
    default:
      // if nothing else matches, do the default
      // default is optional
      break;
  }

```

Is there any reason to (or not to) add a `break;` in the `default:` case? Does the need for 'break;' change if the final case is not `default:`?

# Answer
> 2 votes
You can, but you don't have to.

Should you? That's up to you.

I do. That's because it's then simple to add another `case` at the end of the structure in the future if you want, and you don't have to remember to add the `break` to the existing last case.

---
Tags: coding-standards
---


# Question
Title: How can I loop my code? For example after 30 minutes?
So I have this code which records the temperature and humidity using a DHT22 sensor. After it get's the values it then sends it to a webpage using PHP $\_GET method, where that gets imported into a DB and emails (using PHP). But this only happens when I upload the code to my ESP8266; how can I know build in a loop function that it sends it every 30 mins or given time?

```
#include <ESP8266WiFi.h>
#include "DHT.h"

const char* ssid     = "bbox2";      // SSID of local network
const char* password = "azerty";   // Password on network

WiFiClient client;
char servername[]="lucasdebelder.be";  // remote server we will connect to
String result;

float temperature;
float humidity;

#define DHTPIN 14

#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);

void setup() {
  dht.begin();
  delay(2000);
  Serial.begin(115200);
  Serial.println("Connecting");
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(100);
  }
  Serial.println("Connected");
  delay(1000);
  readSensor();
  String temperatureString = String(temperature,1);
  String humidityString = String(humidity,1);
  sendDataToServer(temperatureString,humidityString);
}

void loop() {

}

void sendDataToServer(String temperature, String humidity)
{
  if (client.connect(servername, 80)) {  //starts client connection, checks for connection
    Serial.println("connected");
    client.println("GET /send_temperature.php?temperature="+temperature+"&humidity="+humidity+" HTTP/1.1"); //Send data
    client.println("Host: lucasdebelder.be");
    client.println("Connection: close");  //close 1.1 persistent connection
    client.println(); //end of get request
  }
  else {
    Serial.println("connection failed"); //error message if no client connect
    Serial.println();
  }

 while(client.connected() && !client.available()) delay(1); //waits for data
  while (client.connected() || client.available()) { //connected or data available
    char c = client.read(); //gets byte from ethernet buffer
      result = result+c;
    }

  client.stop(); //stop client
  Serial.println(result);

}

void readSensor()
{

  humidity = dht.readHumidity();
  temperature = dht.readTemperature();
  Serial.println("Temperature:");
  Serial.println(temperature);
  Serial.println("Humidity:");
  Serial.println(humidity);

}

```

# Answer
> 1 votes
As stated in the previous answer. Code that needs to run more than one time should be called in the loop. But in this case the following solution will work as well.

You can end your setup with a call to the `deepsleep(time_us)` function which can be found in the ESP library. This will shutdown everything except for the on board RTC(Real Time Clock). So the circuit only draws a very little current (20 uA). This can be very useful if the circuit is powered by a battery.

The RTC has a signal on GPIO 16 (D0 on NodeMcu) which will be held HIGH while the given time is not reached. If the given time is reached the signal will be LOW.

If you connect GPIO 16 to the RST(reset) pin, this will make the ESP8266 start-up again. And thus the `setup()` will be executed again.

# Answer
> 0 votes
You execute the corresponding function only in the `setup()` function, which is called once on startup of the ESP. After that the `loop()` function is called repeatedly. The `setup()` function is meant to "setup" your code for it's functionality, which is then executed in the `loop()` function. For example you are begin the Wifi connection and connect to a network in there, because you need the network for your main functionality.

So you have to put the code from `readSensor()` until (and including) `sendDataToServer()` into the `loop()` function. This will execute this code repeatedly.

Then you have to introduce some concept of time, else your code will be executed very fast, effectively flooding your webserver. The easiest way would be to add a call to `delay(30000)`, which would delay the code for 30s. But using delay is not considered good coding style, since it is basically busy waiting and you cannot do anything else during that time.

So to be able to add other functionalities in the future you can implement the time concept with non-blocking code. Take the `BlinkWithoutDelay` example from the Arduino IDE as reference. It uses the `millis()` function, which counts the milliseconds since the startup. You save a timestamp of the last execution of your code and wait until the difference between the current time (given by `millis()`) and your timestamp is greater than 30s. In this time the ESP can do other things, since it still goes through the `loop()` function undisrupted. Then after the timespan you execute the code and reset the timestamp to the current time.

---
Tags: esp8266, wifi, loop
---


title: Wake up a PC from an Uno

text:
# Question
Title: Wake up a PC from an Uno
I want to wake up a PC via a USB-connected Arduino. When using a Pro Micro (Leonardo) I can do it, as its HID interface can wake up a PC. That is, in the Device Manager, under "Keyboards", the relevant HID device under "Power Management" has an "Allow this device to wake-up the PC" checkbox.

However, I need to use an Uno for this project. There's a hack (see link below) which flashes the ATMega16U2 on an Uno to act as a HID keyboard. It works fine, but this HID keyboard on a flashed Uno does NOT have the "Allow this device to wake up the PC" checkbox, i.e. I can't wake up my PC. I tried, the PC doesn't wake up. I know I can use an Ethernet shield on an Arduino to send a Wake up on LAN packet, but I don't want to add any shields, if I don't have to. Any advice how to do this?

EDIT: I was pointed to 2 libraries, NicoHood and LUFA (links below) to code a HID keyboard for the ATMega16U2 on an Arduino Uno. The problem is that acquainting myself with the subject and (either) library, would take several days, which is why I'd prefer to find an already-compiled simple HID device that does what I want. If I can't find one, I have a "dumb" solution: since the Leonardo can wake up a PC, I can hook it up to the PC, power the Uno (with my code) off the Leonardo, link one digital pin between the Uno and the Leonardo, so that the Uno can trigger a USB keystroke on the Leonardo. This is kludgy, since it uses the Leonardo just to send one USB keystroke to wake up the PC, but it would work.

LUFA

NicoHook Keyboard API

HoodLoader

Relevant links:

Arduino Uno as a USB HID Interface

Wake a touchscreen using a Pro Micro

# Answer
> 1 votes
Got it working: my Uno can now wake up a PC. I followed the HoodLoader wiki and I used the HID-Bridge sketches (below). It took about 2-3 hrs.

HoodLoader

HID-Bridge

---
Tags: arduino-uno, usb, keyboard
---


# Question
Title: Why do my temperature sensor values become inconsistent when additional hardware is added to the board?
I have this strange problem. My TMP 36 sensor works fine when it is the only thing connected to my Arduino Uno board. The voltage measurements, and thus the temperature, are accurate and consistent. However, when I attach an LCD screen to the Uno and have a program print the TMP's measurements to the screen, the values become inconsistent, and can change up to 10 degrees F from one reading to another. (I have the sensor take a measurement every second.) This does not happen when the LCD screen is not plugged in. I decided to remove separate connectors from the screen and see when the measurements became consistent again. I tried this once and found that a ground wire that goes to connection 5 on the screen caused to value to change when I repeatedly inserted and removed it from a ground pin. The TPM values were changing even when there was nothing else connected to the LCD (it wasn't on) except for the ground wire. I don't understand how this is possible, and I don't know if this is a hardware or software issue.

I rewired the LCD screen starting with sensor wires, then ground wires, and then the two 5V connections, with one of them having a 220 ohm resistor. I did this while the circuit was powered, and watched the values for any large changes. The first change was a few seconds after I wired the last 5V wire. The sensor measured 80 degrees F and then 85 degrees F one second later. It then went to 81 for a few seconds, then 87. The values continued to change, but not by as much as previous times. By the way, the temperature in the area that the Arduino is in is about 82 degrees F.

TMP values do not change by more than 3 degrees F when the LCD is not connected to the screen. I don't understand what could be causing this. Has anyone else had this problem before, or know the cause?

Here is the layout.

```
#include <LiquidCrystal.h>

LiquidCrystal lcd(12,11,5,4,3,2);
const int sensorPin = A5;
const float baselineTemp = 20.0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  int sensorVal = analogRead(sensorPin);
  Serial.print("Sensor value: ");
  Serial.print(sensorVal);
  float voltage = (sensorVal / 1024.0) * 5.0;
  Serial.print(", volts: ");
  Serial.print(voltage);
  Serial.print(", degrees C: ");
  float temperature = (voltage - .5) * 100;
  Serial.print(temperature);
  Serial.print(", degrees F: ");
  float fahrenheit = (temperature * 1.8 + 32);
  Serial.println(fahrenheit);
  delay(1000);
  lcd.begin(16,2);
  lcd.print(fahrenheit);
  lcd.print(" degrees F");
  float averageTemp;
  if(temperature < baselineTemp) {
    lcd.setCursor(0,1);
    lcd.print("Below room temp");
  }
}

```

# Answer
Don't take power for LCD from Uno pins. Connect LCD power to separate power source.
> 3 votes

# Answer
For an analog sensor like the TMP36, the Arduino uses the 5V as reference. If the 5V changes (but the TMP36 voltage stays the same), the Arduino thinks that the temperature has changed. The value returned by analogRead() increases. That is why the temperature seems to raise if the 5V is lowered.

The TMP36 (with resistor) outputs a certain voltage. That is different from 'ratiometric' sensors, they output a voltage relative to the 5V, and changes to the 5V have no effect on the result. A 'ratiometric' sensor is for example a wheatstone bridge, or a LDR with resistor.

With the TMP36, you need a good voltage reference to read the actual voltage. The internal voltage reference can be used. Perhaps an extra voltage divider is needed. Or use a power supply to the power barrel jack and let the onboard voltage regulator create a fixed voltage of 5V which can be used as reference.

When using digital temperature sensors, like the DS18B20, all these problems are gone instantly.

The 5V should never be connected to AREF. It is already internally connected to VCC at default, and when the internal voltage reference is selected, the AREF pin changes the voltage. In that case, an internal shortcut is created when AREF is connected to 5V. There is no need to add 100nF to AREF, since the Arduino Uno has already 100nF to AREF and GND.

A breadboard can have bad contacts. Since the current of the LCD uses the same GND and +5V wires, it can have influence on the TMP36. It is better to use seperate wires as already mentioned by Chris Stratton. To reduce noise you could take a number of analogRead() values and use the average. For an analog temperature sensor it is common practice to average a number of samples.
> 1 votes

# Answer
Try powering your circuit using a 9V battery. I have also had this problem and it worked when I used a separate power supply. It seems to be an electrical noise caused by your computer USB. The answer posted by JRobert should be necessary if you want to power from the computer.
> 1 votes

# Answer
I had this issue and put a 0.1 µF capacitor across the sensor and got much reduced noise (to within half a degree which is really +- one tick).
> 1 votes

# Answer
I don't see +5v -\> Aref (and Aref -\> bypass capacitor -\> Gnd). Necessary, if you are using the power supply voltage as a reference, as you appear to be.
> 0 votes

---
Tags: arduino-uno, lcd, temperature-sensor
---


# Question
Title: How to upload program to custom arduino board without USB FTDI and making it read only?
If I was to mass produce a microcontroller board I have designed based around the atmega328 (very similar to an arduino uno) but for one embedded task where I want one program only to be stored on it. I want to make the program read only and impossible to access and impossible to overwrite. The board will not include a USB FTDI chip in order to prevent another program being uploaded via arduino IDE. How would I upload said program to the microcontroller?

Would I have to make use of ICSP pins (I dont know much about that) and if this is an impossible task and so a USB will have to be integrated to upload programs... How would i prevent other programs overwriting the main program and also prevent this program from being viewed? \[The main program is written in the arduino IDE\]

# Answer
I think you cannot prevent overwriting the firmware, neither prevent viewed by others.

However, you can detect that someone overwrites it (besides you), by reading some code from e.g. EEPROM based on the content of your firmware. If you read a different code, than you can act upon it.
> 0 votes

---
Tags: programming, usb, atmega328, communication, uploading
---


title: NOT realtime MP3 decoder

text:
# Question
Title: NOT realtime MP3 decoder
I know that MP3 is the most popular audio format out there, but I need to be able to convert them to wav files for bother project I'm working on. It can be done with a PC but I would like to know if there is a way of decoding a MP3 file and turning it into a pcm wav file on an Arduino. I don't want to use an extra chip, as I do not plan on playing the MP3s, just converting them.

# Answer
> 2 votes
The mp3 audio coding is not just one mathematical calculation. To decode every mp3 file you need a complete package and enough memory. That is not something for a simple arduino board.

There are libraries to decode for example a jpg file or a mp3 file. They have restrictions and you need a faster processor.
Adafruit has made a start: https://learn.adafruit.com/native-mp3-decoding-on-arduino/, but you need a powerful non-standaard arduino-compatible board. That library does not use I2S yet.

I suggest to use a Raspberry Pi.

---
Tags: arduino-mega, audio
---


title: String & Char concatenations

text:
# Question
Title: String & Char concatenations
A newbie in Arduino- and I'm trying to concatenate string and chars ( well in python it is quite different ).

I'm trying to post a MQTT message- constructed following format to the `client.publish(outTopic, "["+outTopic+"]"+ msg)`

while `outTopic` is a char\* variable, and `msg` is char- but I get an error for such concatenation.

please your help

```
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// GPIOs on SONOFF board
int LED_SONOFF = 13;
int REL_SONOFF = 12;
int PIN_SW = 14;

const char* ssid = "HomeNetwork_2.4G";
const char* password = "pswd";
const char* mqtt_server = "192.168.2.113";

WiFiClient espClient;
PubSubClient client(espClient);

char msg[50];
const char* outTopic = "HomePi/Dvir/Messages";
const char* inTopic = "HomePi/Dvir/Windows/SONOFF";
const char* inTopic2 = "HomePi/Dvir/Windows/All";
const char* clientID = "Sonoff#1";
String m1, m2;

void start_wifi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void setup() {
  start_wifi(); // start wifi service
  Serial.begin(115200); // start serial service
  delay(10);

  // define sonoff gpios
  pinMode(LED_SONOFF, OUTPUT);
  pinMode(REL_SONOFF, OUTPUT);
  pinMode(PIN_SW, INPUT_PULLUP); // GPIO14 has a pullup resistor
  digitalWrite(LED_SONOFF,HIGH); // LED high is OFF
  digitalWrite(REL_SONOFF,LOW);

  // start mqtt
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void switch_on() {
  digitalWrite(REL_SONOFF,HIGH);
  digitalWrite(LED_SONOFF, LOW); // LED ON
  pub_mqtt("Switch ON");
}

void switch_off() {
  digitalWrite(REL_SONOFF,LOW);
  digitalWrite(LED_SONOFF, HIGH); // LED OFF
  pub_mqtt("Switch OFF");
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  if ((char)payload[0] == '1') {
    switch_on();
  }
  if ((char)payload[0] == '0') {
    switch_off();
    Serial.print("payload: ");
    Serial.println(payload[0]);
  }

}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP8266Client")) {
      Serial.println("connected");
      client.publish(outTopic, "Connected");

      client.subscribe(inTopic);
      m1="Subscribed to: "+inTopic;
      client.publish(outTopic, m1);
      if (inTopic2 !=""){
        client.subscribe(inTopic2);
        m2="Subscribed to: ";//+ String(inTopic2);
        client.publish(outTopic, m2);
      }

    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void pub_mqtt(char* msg) {
  client.publish(outTopic, msg);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  if (digitalRead(PIN_SW)==1) {
    if (digitalRead(REL_SONOFF)!=LOW) {
      switch_off();
    }
  }
  else if (digitalRead(PIN_SW)==0) {
    if (digitalRead(REL_SONOFF)!=HIGH){
      switch_on();
    }
  }
   delay(100);
}

```

# Answer
> 2 votes
You can't simply concatenate C strings like that. Instead you have to build them up into a new string. For formatting like that the simplest way is with `sprintf`:

```
char outMessage[strlen(outTopic) + strlen(msg) + 3]; // Room for topic, message, [ and ] and terminating \0
sprintf(outMessage, "[%s]%s", outTopic, msg);
client.publish(outTopic, outMessage);

```

Another method is with strcpy and strcat:

```
char outMessage[strlen(outTopic) + strlen(msg) + 3]; // Room for topic, message, [ and ] and terminating \0
strcpy(outMessage, "[");
strcat(outMessage, outTopic);
strcat(outMessage, "]");
strcat(outMessage, msg);
client.publish(outTopic, outMessage);

```

You have to ensure that your "holding" string `outMessage` is big enough to hold everything you want to send, *plus a terminating NULL character*, otherwise your program will crash.

Another way of creating the "holding" variable is with `alloca()`. That allocates bytes on the stack for a variable - just like `malloc()` does on the heap, but doesn't require `free()`ing because it's on the stack and is reclaimed when the function exits:

```
char *outMessage = (char *)alloca(strlen(outTopic) + strlen(msg) + 3);

```

---
Tags: string, mqtt, constants, strlen
---


title: Difference in pinout (types?) Uno/Mega

text:
# Question
Title: Difference in pinout (types?) Uno/Mega
As a hands-on guy, I've started my first ever Arduino project 5 hours ago with no prior knowledge about Arduinos (I have coding experience tho. included this in case I am missing something obvious to the veterans around here). So far I have been able to hook-up 3 SSD1306 SPI OLED displays to my Uno, and created a script that allows me to control each display separately. Because my goal is to have 5 displays work off one Arduino, I figured to pin everything over to my Mega since it has more outputs (not sure yet about the differences between DIGITAL PWM on the Uno, and the 53 additional DIGITAL pins on the Mega).

First problem I encountered is that I couldn't find where the clock pulse was specified in the demo script. It's pinned on the Uno on pin 13, but this is not specified somewhere in that script, and I think once I understand the differences in pins from both boards, I might be able to help myself a few more steps into the future.

So to sum up my questions.

1. How or where is the ClockPulse being specified.
2. Can I use the 53 DIGITAL pins on the Mega, instead of the 13 DIGITAL PMW that I have on my Uno, and if yes, do I need to change some settings?

Here is my current script that works on my Uno, but not on my Mega, even if I use the same DIGITAL PMW pins on my Mega.

```
#include "HCuOLED.h"
#include "SPI.h"

//#define CS_DI 10
//#define DC_DI 9
//#define RST_DI 8

//HCuOLED HCuOLED_1(SSD1307, CS_DI, DC_DI, RST_DI); // For SSD1307 displays (HCMODU0050 & HCMODU0052)
HCuOLED HCuOLED_1(SSD1307, 10, 9, 8); // For SSD1307 displays (HCMODU0050 & HCMODU0052)
HCuOLED HCuOLED_2(SSD1307, 7, 6, 5); // For SSD1307 displays (HCMODU0050 & HCMODU0052)
HCuOLED HCuOLED_3(SSD1307, 4, 3, 2); // For SSD1307 displays (HCMODU0050 & HCMODU0052)

void setup()
{
  HCuOLED_1.Reset();
  HCuOLED_2.Reset();
  HCuOLED_3.Reset();
}

void loop()
{
  //display 1
  HCuOLED_1.SetFont(Terminal_8pt);
  HCuOLED_1.Cursor(44,0);
  HCuOLED_1.Print("Cpt");
  HCuOLED_1.Cursor(20,10);
  HCuOLED_1.Print("Fastlane");

  HCuOLED_1.Cursor(14,24);
  HCuOLED_1.SetFont(LCDLarge_24pt);
  HCuOLED_1.Print("KM/H");
  HCuOLED_1.Refresh();

  HCuOLED_1.ClearBuffer();

  //display 2
  HCuOLED_2.SetFont(Terminal_8pt);
  HCuOLED_2.Cursor(44,0);
  HCuOLED_2.Print("Cpt");
  HCuOLED_2.Cursor(20,10);
  HCuOLED_2.Print("Fastlane");

  HCuOLED_2.Cursor(14,24);
  HCuOLED_2.SetFont(LCDLarge_24pt);
  HCuOLED_2.Print("RPM");
  HCuOLED_2.Refresh();

  HCuOLED_2.ClearBuffer();

  //display 3
  HCuOLED_3.SetFont(Terminal_8pt);
  HCuOLED_3.Cursor(44,0);
  HCuOLED_3.Print("Cpt");
  HCuOLED_3.Cursor(20,10);
  HCuOLED_3.Print("Fastlane");

  HCuOLED_3.Cursor(14,24);
  HCuOLED_3.SetFont(LCDLarge_24pt);
  HCuOLED_3.Print("Info");
  HCuOLED_3.Refresh();

  HCuOLED_3.ClearBuffer();
}

```

And here is the original script:

```
#include "HCuOLED.h"
#include "SPI.h"

/* Example bitmap */
const PROGMEM byte Tiny_Logo_Resistor[] =
{
  0xC0, 0xE0, 0x30, 0x30, 0xF0, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x38, 0x0E, 0x07, 0x1E, 0x78, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x70, 0x1C, 0x07, 0x0F, 0x3C, 0xF0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0x3C, 0x0F, 0x07, 0x1C, 0x70, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x78, 0x1E, 0x07, 0x0E, 0x38, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xF0, 0x30, 0x30, 0xE0, 0xC0,
  0x00, 0x01, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x3C, 0x38, 0x0E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x1E, 0x38, 0x1C, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0E, 0x38, 0x38, 0x0E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x1C, 0x38, 0x1E, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0E, 0x38, 0x3C, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x01, 0x00,
};

/* Digital pin number for the displays chip select pin */
#define CS_DI 10
/* Digital pin number for the displays data/command pin */
#define DC_DI 9
/* Digital pin number for the displays reset pin */
#define RST_DI 8

/* Array indexes for the X and Y coordinates */
#define X1 0
#define Y1 1
#define X2 2
#define Y2 3

/* Arrays to store coordinates and direction for the line, rectangle and bitmap */
byte Box[4] = {1,1,20,20};
byte BoxDir[4] = {1,1,1,1};
byte Line[4] = {100,25,120,55};
byte LineDir[4] = {-1,-1,-1,-1};
byte Bitmap[2] = {40,40};
byte BitmapDir[2] = {-1,-1};

/* Create an instance of the library (uncomment one of the lines below) */
//HCuOLED HCuOLED(SSD1307, SS_DI, DC_DI, RST_DI); // For SSD1307 displays (HCMODU0050 & HCMODU0052)
HCuOLED HCuOLED(SH1106, CS_DI, DC_DI, RST_DI); // For SH1106 displays (HCMODU0058 & HCMODU0059)

void setup()
{

  /* Reset the display */
  HCuOLED.Reset();
}

void loop()
{
  /* Display some text using a small 8x8 fixed width font */
  HCuOLED.SetFont(Terminal_8pt);
  HCuOLED.Cursor(44,0);
  HCuOLED.Print("HOBBY");
  HCuOLED.Cursor(20,10);
  HCuOLED.Print("COMPONENTS");

  /* Display a number using a large 4 line LCD style font */
  HCuOLED.Cursor(20,24);
  HCuOLED.SetFont(LCDLarge_24pt);
  HCuOLED.Print("HCuOLED");

  /* Change the draw mode from NORMAL to INVERT */
  HCuOLED.DrawMode(INVERT);
  while(1)
  {
    /* Move the positions of the 3 objects */
    MoveRect();
    MoveLine();
    MoveBitmap();

    /* Draw the objects to the display buffer */
    HCuOLED.Rect(Box[X1],Box[Y1],Box[X2],Box[Y2], SOLID);
    HCuOLED.Line(Line[X1],Line[Y1],Line[X2],Line[Y2]);

    HCuOLED.Cursor(Bitmap[X1],Bitmap[Y1]);
    HCuOLED.Bitmap(84, 2, Tiny_Logo_Resistor);

    /* Write the display buffer to the screen */
    HCuOLED.Refresh();

    /* Draw the objects again. As we are in INVERT mode this will remove them */
    HCuOLED.Rect(Box[X1],Box[Y1],Box[X2],Box[Y2], SOLID);
    HCuOLED.Line(Line[X1],Line[Y1],Line[X2],Line[Y2]);

    HCuOLED.Cursor(Bitmap[X1],Bitmap[Y1]);
    HCuOLED.Bitmap(84, 2, Tiny_Logo_Resistor);
  }
}

/* Update the X and Y coordinates for the box */
void MoveRect(void)
{
  if(Box[X1] == 0 || Box[X1] == 127)
    BoxDir[X1] *= -1;
  Box[X1] += BoxDir[X1];

  if(Box[Y1] == 0 || Box[Y1] == 63)
    BoxDir[Y1] *= -1;
  Box[Y1] += BoxDir[Y1];

  if(Box[X2] == 0 || Box[X2] == 127)
    BoxDir[X2] *= -1;
  Box[X2] += BoxDir[X2];

  if(Box[Y2] == 0 || Box[Y2] == 63)
    BoxDir[Y2] *= -1;
  Box[Y2] += BoxDir[Y2];
}

/* Update the X and Y coordinates for the Line */
void MoveLine(void)
{
  if(Line[X1] == 0 || Line[X1] == 127)
    LineDir[X1] *= -1;
  Line[X1] += LineDir[X1];

  if(Line[Y1] == 0 || Line[Y1] == 63)
    LineDir[Y1] *= -1;
  Line[Y1] += LineDir[Y1];

  if(Line[X2] == 0 || Line[X2] == 127)
    LineDir[X2] *= -1;
  Line[X2] += LineDir[X2];

  if(Line[Y2] == 0 || Line[Y2] == 63)
    LineDir[Y2] *= -1;
  Line[Y2] += LineDir[Y2];
}

/* Update the X and Y coordinates for the bitmap */
void MoveBitmap(void)
{
  if(Bitmap[X1] == 0 || Bitmap[X1] == 43)
    BitmapDir[X1] *= -1;
  Bitmap[X1] += BitmapDir[X1];

  if(Bitmap[Y1] == 0 || Bitmap[Y1] == 47)
    BitmapDir[Y1] *= -1;
  Bitmap[Y1] += BitmapDir[Y1];
}

```

# Answer
You are communicating with your OLED displays using *SPI* \- Serial Peripheral Interface. This is a special hardware peripheral built in to the MCU, and the outputs of it are physically connected inside the MCU to what become pins 11-13 on the Arduino UNO.

This, and other things like the UART, PWM and the analog inputs, are known as *alternate functions* of the pins.

On small MCUs like the Arduino uses these functions are fixed in hardware (more advanced MCUs employ a system to allow you to map the functions to different pins).

When you use SPI on the UNO it always uses pins 11-13 (MOSI, MISO and SCK in that order). When you use SPI on the Mega it always uses pins 51, 50 and 52 (in that order for the same functions). You can't change it. Pin 10 on the UNO is the Slave Select pin, and that again is an *alternate function* which is hard wired. On the mega that function is pin 53.

For SPI to work as a master (which is what you want) then pin 10 on the UNO or pin 53 on the Mega must be set to OUTPUT. It doesn't matter if you actually use it, but it has to be set to OUTPUT as that defines the direction the SPI peripheral operates in.

So for the Mega you would wire your OLED displays to pins 51, 50 and 52 instead of pins 11, 12 and 13. You *could* use pin 53 as one of your chip select pins (though you don't *have* to, just as long as you set it to OUTPUT).

Incidentally, you can save pins on your setup by sharing some of them. The only pin that need to be unique for each OLED is the Chip Select pin. That is the pin that tells the OLED that it is being spoken to. Only when that pin is active will the OLED listen to any of the other pins.

The only other one you may need to connect separately is the reset pins, since you reset the displays in turn - resetting the second would reset the first and undo the configuration. TBH I'd connect the RESET pins of the OLEDs to a single pin, and specify another (unused, or non-existent) pin in the constructors for RESET - then manually reset all the OLEDs together through the one LOW pulse of the RESET pin, and then call the reset functions for each display, which should configure them all.

That way you are then using just (example UNO pins numbers shown):

* MOSI (11)
* MISO (12)
* SCK (13)
* DC (7)
* RESET (6)
* CS1 (10)
* CS2 (9)
* CS3 (8)
> 2 votes

---
Tags: arduino-uno, arduino-mega, spi, ssd1306
---


# Question
Title: Arduino sketch- How to add Time Stamp for outgoing MQTT
I'm writing a sketch in order to upload to a Sonoff device ( Remote relay, based ESP8266 ).

All is working great, but I wish my MQTT pubs to contain following format:

`[ DATE & TIME ] msg`

ESP8266 is connected to the internet. I;m looking for a way doing it (including periodic time updates ) without running all 1MB memory, meaning: a code that 1) get time from external source (LAN or WAN ) 2) update it every 24h 3) Lite code ?

Thanks

# Answer
Start with the ESP8266WiFi "NTPClient" example. That will teach you how you can get the "Unix Epoch" time from the internet.

That value can be fed directly into TimeLib to keep track of the time for you (indeed, TimeLib includes an NTP example for Arduino Ethernet that should help you get started). Do that periodically (daily, hourly, whatever), and you have your time. TimeLib can then give you the date and time as individual components (hours, minutes, etc), which you can then construct together (I'd use `snprintf`) to include in your MQTT message:

```
int len = strlen(message) + 25;
char mqttMessage[len];
snprintf(mqttMessage, len, "[%04d/%02d/%02d %02d:%02d:%02d] %s",
    year(), month(), day(), hour(), minute(), second(), message);

mqttMessage => "[2018/08/11 20:36:24] foo"

```
> 1 votes

---
Tags: esp8266, time
---


# Question
Title: Always 255-response in I2C between ATTiny85 (8MHz) and Arduino Uno
I tried to set up an I2C conversation between ab ATTiny85 (8MHz) and an Arduino Uno. However I always get a 255 response from my I2C slave. I am using Arduino 1.8.5.

What am I doing wrong?

**ATTiny85-Slave Code:**

```
#include "TinyWireS.h"  // wrapper class for I2C slave
routines
#define I2C_SLAVE_ADDR  0x26 // i2c slave address (38)

byte t=10;

void setup() {
  TinyWireS.begin(I2C_SLAVE_ADDR);  // init I2C Slave mode
  TinyWireS.onRequest(requestEvent);
}

void loop() {
}

void requestEvent() {
  TinyWireS.send(t);
}

```

**Arduino Uno-Master Code:**

```
 #include <Wire.h>
 #define I2C_SLAVE_ADDR  0x26 // i2c slave address (38)

void setup() {
  Wire.begin();
  Serial.begin(9600);
}

void loop() {
  byte num;
  // read 1 byte, from address 0x26
  Wire.requestFrom(I2C_SLAVE_ADDR, 1);
  while(Wire.available()) {
    num = Wire.read();
  }
  Serial.print("num = ");
  Serial.println(num,DEC);
}

```

# Answer
It may seem that the current commit of January 2018 from the TinyWire library is corrupt. Try using an older version from 2017, for example this one: https://github.com/rambo/TinyWire/tr...72a13504bbfc4e

This solves the problem for me as well.

Source: Teensy 3.5 - I2C - ATTiny85-20PU (TinyWireS.OnRequest not triggering!) - Post #11
> 1 votes

---
Tags: arduino-uno, i2c, attiny85
---


title: Using EEPROM Anything in loop()

text:
# Question
Title: Using EEPROM Anything in loop()
I'm trying to make a programm for Arduino Bluno Beetle, that saves a string in the loop. Here is my code:

```
#include <EEPROM.h>
#include <EEPROMAnything.h>
struct config_t{
   String lastThing;
    } savedValues;
void setup(){
   EEPROM_readAnything(ADDR, savedValues);
   Serial.println(lastThing);
}
String readString="asd";
void loop() {
 //...
 lastThing=readString;
 EEPROM_writeAnything(ADDR, savedValues);
}

```

(The EEPROMAnything.h can be found here: https://playground.arduino.cc/Code/EEPROMWriteAnything?action=sourceblock&num=1)

The code works until the 11th line. It gives there the following error:

```
'lastThing' was not declared in this scope

```

Does anybody know how to fix this problem?

# Answer
> 1 votes
The proper syntax for referring to a struct member is \[structName\].\[memberName\]. Changing `lastThing` in lines 8 & 13 to `savedValues.lastThing` fixes the "undeclared" error.

# Answer
> 0 votes
**Very huge disclaimer**: the code in this answer is untested, and moreover I never played with `String` objects (I don't like dynamic allocation on arduino). Consequently bugs are expected in this code. If you find any (for instance, the relocation does not work how I suppose, or the parameters should be passed in another way in the read function) please write in the comment so I can fix this

EDIT: Since there were complaints about this, I tested it and.. It works. The read and write functions work so, in the end, it appears that all the researches I did for this answer were complete and allowed me to correctly implement it

---

As pointed out, `lastThing` is not a variable, it is a field in the `savedValues` variable. So the correct syntax would be

```
lastThing=readString;

```

This said, your code won't work and has performance issues. First of all it uses the EEPROM.write method, which overwrites the value in eeprom thus lowering its life, and then you will save a pointer to a memory area (4 bytes), which is not the thing you want to save.

In my opinion, it is better to save it "manually":

```
// Write i in EEPROM, starting from address addr.
// Return the number of bytes written (2 if everything is ok)
uint16_t writeUInt16ToEeprom(uint16_t addr, uint16_t i)
{
    uint16_t currAddr = addr;

    // Only if there is enough space
    if ((currAddr + 2) <= E2END)
    {
        // Write the 2 bytes in eeprom
        EEPROM.update(currAddr++, i >> 8);
        EEPROM.update(currAddr++, i & 0xFF);
    }
    return (currAddr - addr);
}

// Write s in EEPROM, starting from address addr.
// Return the number of bytes written
uint16_t writeStringToEeprom(uint16_t addr, String s)
{
    uint16_t currAddr = addr;

    uint16_t len = s.length();

    // Only if there is enough space
    if ((currAddr + len + 2) <= E2END)
    {
        // Write the string length
        currAddr += writeUInt16ToEeprom(currAddr, len);

        // Write the string bytes
        for (uint16_t i = 0; i < len; i++)
            EEPROM.update(currAddr++, s.charAt(i));
    }

    return (currAddr - addr);
}

// Read i from EEPROM, starting from address addr.
// Return the number of bytes read (2 if everything is ok)
uint16_t readUInt16FromEeprom(uint16_t addr, uint16_t & i)
{
    uint16_t currAddr = addr;

    // Only if there is enough space
    if ((currAddr + 2) <= E2END)
    {
        i = EEPROM.read(currAddr++);
        i = i << 8 | EEPROM.read(currAddr++);
    }
    return (currAddr - addr);
}

// Read s from EEPROM, starting from address addr.
// Return the number of bytes read
// S should be already allocated when entering the function
uint16_t readStringFromEeprom(uint16_t addr, String & s)
{
    uint16_t currAddr = addr;

    uint16_t len = 0;
    s.remove(0);

    // Check if there is enough space for the length
    if ((currAddr + 2) <= E2END)
        currAddr += readUInt16FromEeprom(currAddr, len);

    // Check if there is enough space left for all the chars
    if ((currAddr + len) <= E2END)
    {
        s.reserve(len); // Should allocate only once, thus speeding up

        for (uint16_t i = 0; i < len; i++)
            s.concat((char)(EEPROM.read(currAddr++)));
    }
    else
        currAddr = addr;

    return (currAddr - addr);
}

String lastThing;

void setup(){
    readStringFromEeprom(ADDR, lastThing);
    Serial.println(lastThing);
}

String readString="asd";
void loop() {
    //...
    lastThing=readString;
    writeStringToEeprom(ADDR, lastThing);
}

```

Note: you should also check the values returned from the functions to check whether the writing or reading was successful.

In this case I did not use the struct, since in your example the struct is not used. If you really need it, because for instance you want to save also an int, you can do something like this:

```
struct config_t{
    String lastThing;
    uint16_t myIdx;
} savedValues;

uint16_t writeUInt16ToEeprom(uint16_t addr, uint16_t i)
...

uint16_t writeStringToEeprom(uint16_t addr, String s)
...

uint16_t readUInt16FromEeprom(uint16_t addr, uint16_t & i)
...

uint16_t readStringFromEeprom(uint16_t addr, String & s)
...

// Write s in EEPROM, starting from address addr.
// Return the number of bytes written
uint16_t writeStructToEeprom(uint16_t addr, struct config_t s)
{
    uint16_t currAddr = addr;
    currAddr += writeStringToEeprom(currAddr, s.lastThing);
    currAddr += writeUInt16ToEeprom(currAddr, s.myIdx);
    return (currAddr - addr);
}

// Read s from EEPROM, starting from address addr.
// Return the number of bytes read
// S should be already allocated when entering the function
uint16_t readStructFromEeprom(uint16_t addr, struct config_t s)
{
    uint16_t currAddr = addr;

    uint16_t readVal = readStringFromEeprom(currAddr, s.lastThing);
    if (readVal == 0)
        return 0;
    currAddr += readVal;

    uint16_t readVal = readUInt16FromEeprom(currAddr, s.myIdx);
    if (readVal == 0)
        return 0;
    currAddr += readVal;

    return (currAddr - addr);
}

void setup(){
    readStructFromEeprom(ADDR, savedValues);
    Serial.println(lastThing);
}

String readString="asd";
void loop() {
    //...
    savedValues.lastThing = readString;
    savedValues.myIdx = 22;
    writeStructToEeprom(ADDR, savedValues);
}

```

I think that the idea is pretty easy to understand. Basically you manually write a function for each type you want to write (e.g. `writeUInt16ToEeprom`), then use these "building blocks" to create complex functions (e.g. `writeStructToEeprom`). For items which do not have a fixed width (`Strings`) you first save the length, then the bytes. What I mean with "fixed width" is that you know at compile time the number of childs it has For instance, the struct has two "childs" (the string and the integer), while the string has an unknown number of childs (n characters).

You can write a template function for all the integers like this:

```
// Write i in EEPROM, starting from address addr.
// Return the number of bytes written
template <class T> uint16_t writeIntegerToEeprom(uint16_t addr, T i)
{
    uint16_t currAddr = addr;

    // Only if there is enough space
    if ((currAddr + sizeof(T)) <= E2END)
    {
        // Write the bytes in eeprom
        for (uint8_t idx = 0; idx < sizeof(T); idx++)
        {
            EEPROM.update(currAddr++, (8*(i >> (sizeof(T) - 1 - idx))) & 0xFF);
        }
    }
    return (currAddr - addr);
}

// Read i from EEPROM, starting from address addr.
// Return the number of bytes read
template <class T> uint16_t readUInt16FromEeprom(uint16_t addr, T & i)
{
    uint16_t currAddr = addr;

    // Only if there is enough space
    if ((currAddr + sizeof(T)) <= E2END)
    {
        i = 0;
        for (uint8_t idx = 0; idx < sizeof(T); idx++)
        {
            i = i << 8 | EEPROM.read(currAddr++);
        }
    }
    return (currAddr - addr);
}

```

You can use it for all the integer types, using it like the UInt16 variant above. Avoid using it for classes or structs, since in some cases (e.g. the struct with string example above) it may not save what you want

# Answer
> 0 votes
it is better not to use String type at all and it can't be saved to EEPROM. You can save a copy of the internal c-string of the String with `strcpy(savedValues.lastThing, readString.c_str());`

```
#include <EEPROM.h>

#define ADDR 512

struct config_t {
  char lastThing[32];
  int lastNum;
} savedValues;

void setup() {
  Serial.begin(115200);
  Serial.setTimeout(10);

  EEPROM.get(ADDR, savedValues);
  Serial.println(savedValues.lastThing);
  Serial.println(savedValues.lastNum);
}

void loop() {
  if (Serial.available()) {
    String readString = Serial.readStringUntil('|');
    int n = Serial.parseInt();

    strncpy(savedValues.lastThing, readString.c_str(), sizeof(savedValues.lastThing));
    savedValues.lastNum = n;
    EEPROM.put(ADDR, savedValues);

    //clean rest of the input (crlf)
    byte b;
    while (Serial.readBytes(&b, 1) > 0);
  }
}

```

---
Tags: arduino-uno, eeprom
---


# Question
Title: Some Arduino components seem ridiculously cheap
My project is an Arduino-based device, packed into a box.

It will need to use Speed, Latitude, Longitude and Altitude data to log hills it detects on to an SD. On the press of a button, it will need to upload the hill data to the server via Wi-Fi.

I need the following items:

* GPS Module + Antenna
* WiFi Module
* SD Module
* Altimeter
* microSD Card
* Inline switch for my battery pack

The cost? Well on the Pi Hut it was £120 or so:

> GPS = https://thepihut.com/products/sim808-gps-gprs-gsm-shield-for-arduino = £42
>
> WiFi = https://thepihut.com/products/wifi-shield-v3-for-arduino-rpsma-802-11b-g-n = £54
>
> SD = https://thepihut.com/products/microsd-card-module-for-arduino = £6
>
> microSD Card = https://thepihut.com/products/blank-micro-sd-cards (4GB) = £5
>
> Altimeter = https://thepihut.com/products/adafruit-bmp280-i2c-or-spi-barometric-pressure-altitude-sensor = £10
>
> Switch = https://thepihut.com/products/adafruit-in-line-power-switch-for-2-1mm-barrel-jack = £2.50

On Bang Good (a really cheap online shop I discovered) it was more like £30:

> GPS = https://www.banggood.com/GPS-UBLOX-NEO-7N-Satellite-Positioning-Module-For-Arduino-51MCU-STM32-p-1203610.html?rmmds=cart\_middle\_products&cur\_warehouse=CN = £10.54
>
> GPS Antenna = https://www.banggood.com/GPS-Active-Ceramic-Antenna-IPX-IPEX-Interface-For-GPS-Module-p-1203537.html?rmmds=cart\_middle\_products&cur\_warehouse=CN = £2.11
>
> WiFi = https://www.banggood.com/Upgraded-Version-1M-Flash-ESP8266-ESP-01-WIFI-Transceiver-Wireless-Module-p-979509.html?rmmds=cart\_middle\_products = £2.53
>
> SD = https://www.banggood.com/Micro-SD-TF-Card-Memory-Shield-Module-SPI-Mciro-SD-Adapter-For-Arduino-p-919914.html?rmmds=cart\_middle\_products&cur\_warehouse=CN = £1.02
>
> microSD Card = https://www.banggood.com/4GB-MicroSD-Card-with-Card-Reader-for-RC-FPV-Camera-Quadcopter-p-1050069.html?rmmds=cart\_middle\_products&cur\_warehouse=CN = £3.96
>
> Altimeter = https://www.banggood.com/MPL3115A2-IIC-I2C-Intelligent-Temperature-Pressure-Altitude-Sensor-V2\_0-For-Arduino-p-1198222.html?rmmds=cart\_middle\_products = £5.16
>
> Switch = https://thepihut.com/products/adafruit-in-line-power-switch-for-2-1mm-barrel-jack
>
> = £2.50 (From Pi Hut, though)

I'm suspicious. I might be inexperienced, and this may be a bad question, but is the cheaper option lower in quality? Is the expensive one over the top? The cheap version really seems to good to be true.

# Answer
> 15 votes
The cheaper option is not always lower in quality. You can find items for sale on Amazon, Ebay and Aliexpress that all have the same "seller name" and a identical picture of the item. The price is usually 5 to 10 times higher on Amazon than Ebay. Aliexpress is usually the cheapest.

During the past year, I've ordered over 100 Arduino related sensors/modules from Ebay and Aliexpress. Four from Ebay and one from Aliexpress were defective. I got a refund for all five items.

If you are going to buy the cheaper products, it's a good idea to order more than you need in case one is defective.

Some items should not be sold at any price. For example, I purchased a DHT11 temperature and humidity sensor when I first started with Arduinos. It's an inaccurate piece of garbage, and that's exactly where it went.

# Answer
> 3 votes
If something is too good to be true, it usually is.

In all seriousness, going with a reputable shop (Adafruit, Sparkfun, Pololu) can save you a bit of headaches later, especially if you are doing integration. You might ask (email) the Pi Hut folks why you should buy from their place, rather than the other place, I'm curious what they would say. I don't think this needs to be an accusatory sort of email (how dare you charge more!), but more of a "I see there is a price difference; obviously, something is going on which I don't know about, can you explain this?"

I've bought cheap stuff from Amazon (Arduino clones), and they'd work... after a fashion. Bad solder masks, badly soldered components; all would make getting things going a real pain. Sometimes, a component (like a voltage regulator) wouldn't work, and so an Arduino clone would work when plugged in to a USB port, but not in a standalone mode. Then again, this was a 4 for $10, vs 1 for $15, so it was a bit of a lark, but there was a build quality

If you are putting a lot of effort into the software for this, or paying someone for the software to be developed, or this experiment will be a costly one, the price difference wouldn't be as much of an issue. Is £90

How many of these are you building, BTW? If you are building many, cheaper components might be an issue.

Someone might have another take here; the other shop might be quite reputable, but you have to ask why there is a huge disparity in costs, yes.

If you are wanting to sell stuff online, people may ask for warranties, or expect something to work for N months/years; what would happen if these units fail?

# Answer
> 3 votes
I designed a battery backup power supply for a product at my work. I included the INA219 current/voltage measurement chip. For the prototype run I bought that part from two Aliexpress sellers since the cost was half of what it would cost through our normal distributors. (two orders of 50) Half of the chips we way out of spec. Some would read current okay but the voltage was off. Some the voltage was okay and the current was off. I suspect one order of the 50 was badly out of spec parts but since we didn't track which chips ended up in which boards we didn't know which was the bad batch.

In another case, we had been using a cheap buck converter (dc-dc power supply) normally called Mini360. It was a very good module and the chip was from a major IC manufacture. It was cheaper for us to buy the module than to buy the parts so I included it as a through hole component in some of my designs. A couple of months ago we had experienced some problems with a product and I then found that the Mini360 modules we were using was different. The pcb was different, a tiny bit smaller, and the switching regulator use was from a China manufacture. It was a knock-off of the original chip on the earlier Mini360. Because of what we were doing in our product, the new knock-off part caused problems for one of the designs. The part does the same job as the original part, but it wasn't the same. And how it worked for us, in one specific product, meant that I couldn't use it. On the next revision of the product I designed out the module and implemented the module onto our smd board. And we buy the original part from our normal distributors, not China. It costs us more but we need reliability.

For my hobby I use the Arduino framework as it was easier for coding. (I'm a hardware designer) I also use cheap available parts targetted for the Arduino user base. Most of the stuff is decent, good enough. But there always is a higher level of risk when we buy these cheap parts.

# Answer
> 1 votes
The main reason that some devices on eBay, or where ever, are markedly cheaper is that they are *clones* produced by a third party, using designs that have been copied/pirated or reverse engineered.

This reduces the third party's set up costs, quality assurance (QA) (i.e. testing) costs and research and development (R&D) costs to almost zero (compared to those of the original manufacturer).

So, *generally*, the board will, for all intents and purposes, be the same physically, just at a much lower cost, and, as dandavis states in his comment, probably with the same reliability and quality.

However, if you purchase these clones, then the research and development aren't being paid for and may inhibit further growth in the market.

In addition, sometimes the cost is reduced *even* further as the third party cloner will use inferior and cheaper, alternative, components which *may* cause the device to fail sooner than the original. They may even come from *the same factory* and be devices that are using the original components, but which have failed the QA process, for one reason or another... and then fail in extreme circumstances.

So, in summary, you are taking a gamble (albeit a small one), and whilst generally you will end up with a device of the same quality, you *may* sometimes end up with a bit of a lemon.

---
Tags: arduino-uno, gps
---


# Question
Title: Why isn't DigiSpark automatically recognized on other computers?
I bought a DigiSpark (it is a development board based on the ATtiny85 microcontroller) yesterday and I wrote my first script.

I have no problems to run it on my personal PC (which I am using to program my DigiSpark). The problem is when I try to plug my DigiSpark to another PC, which doesn't have DigiSpark drivers installed. I tried to run it on two different PCs (Windows 7) and Windows just can not find DigiSpark drivers so my script does not run.

Of course I tried to plug in to different USB ports - unfortunately it did not help.

Any ideas what can I do to make my DigiSpark run on other PC without installing drivers by myself?

Thank you.

# Answer
the digi spark make use of a bitbanged usb. (emulated usb). because of this a new pc wont see a HID keyboard but a digi spark. only when the driver is installed it will automaticly switch to the HID driver for the emulated usb stack. they pro micro has a hardware usb stack. this wil directly show a HID keyboard and work right away.
> 2 votes

# Answer
You will need to install the drivers before you can use it on other computers. The drivers tell a Windows PC how to talk to the device. The device is not a generic device so Windows can't use a fall back driver, like it could with a keyboard or monitor.
> 1 votes

# Answer
not true, https://www.reddit.com/r/arduino/comments/5ii5mv/why\_digispark\_is\_not\_automatically\_recognized\_on/
Yes, I try to get the DigiSpark to look like a keyboard to a host PC and execute a series of keystrokes. Here is my script: http://pastebin.com/dY05nbGY permalinkembedparent \[–\]cptskippy 3 points 5 months ago

Ok, you're using the DigiKeyboard library so that should make the Digispark show up as HID device. When you plug the DigiSpark into a PC where you haven't installed the drivers, does a "HID Keyboard Device" appear in the Device Manager under the Keyboards branch?

The Digispark powers up and executes the program immediately. My guess is that you probably need a delay in your code to allow the host PC to setup the interface.

```
#include "DigiKeyboard.h"

void setup() {
    DigiKeyboard.delay(5000);  // Wait 5 seconds before proceeding
}

int limit = 1;
int current = 0;

void loop() {
    DigiKeyboard.update();

    if (current < limit) {
        DigiKeyboard.sendKeyStroke(0);

        DigiKeyboard.sendKeyStroke(KEY_R, MOD_GUI_LEFT);
        DigiKeyboard.delay(100);
        DigiKeyboard.println("ipconfig");
        current++;
    }

    DigiKeyboard.delay(5000);
}

```

permalinkembedparent \[–\]readerpl\[S\] 2 points 5 months ago You are the best!!! IT WORKS!!!!!
> 1 votes

# Answer
I faced the same issue when I first time used DigiSpark. After searching on the internet I found the solid answer that worked for me.

Arduino IDE from 1.66 to onward have not driver for DigiSpark so you have to install the driver manually when you will use Arduino IDE 1.66 or latest. But Arduino IDE 1.65 and some lower versions have support for DigiSpark.

When you will use say Arduino 1.65 and connect DigiSpark to USB port, then your PC/Laptop will automatically install the driver for DigiSpart.
> -1 votes

---
Tags: digispark
---