# Question
Title: 7-Segment Display with WS2312B and FastLED
I thought of the idea of using the WS2312B LED strip to drive a custom 7-Segment display. The project will require a large number of these displays, and driving them with a single Arduino (I'm thinking of an Arduino MEGA). For driving the LEDs I am using the FastLED library.

I wrote some code that drives a single display, It works, but I think It's possible to make it simpler, the code I wrote stores the digits in arrays, and uses these arrays in functions customized to each digit. here is an example:

```
//Digit Arrays:
byte digit0[]     = {0,1,2,3,4,5};
byte digit1[]     = {1,2};
byte digit2[]     = {0,1,3,4,6};
byte digit3[]     = {0,1,2,3,6};
byte digit4[]     = {1,2,5,6};
byte digit5[]     = {0,2,3,5,6};
byte digit6[]     = {0,2,3,4,5,6};
byte digit7[]     = {0,1,2};
byte digit8[]     = {0,1,2,3,4,5,6};
byte digit9[]     = {0,1,2,3,5,6};

```

The functions are something like this:

```
void AllOff(){
//Switch off All the LEDs in the segment. Should be off for 1 second
  for(int i=0; i<7; i++){
    leds[i] = CRGB::Black;
    FastLED.show();
  }
  //delay(1000);
}
void AllOn(CRGB myColor){
  //Switch on All the LEDs in the segment (should display 8)
  //The color of choice is #1E78A0
  for(int i=0; i<7; i++){
    leds[i] = CRGB (30,120,160);
    FastLED.show();
  }
  delay(1000);
}
void Print0(CRGB myColor){
  //Prints the digit 0:
  AllOff();
  ArraySize = sizeof(digit0);     //get the size of the array
  for(int i=0; i<ArraySize; i++){
    LED_Number  = digit0[i];      //get the LED number from the array
    leds[LED_Number]    = CRGB (myColor);  //Switch the LED on
    FastLED.show();
  }
}

```

When I call it in the code, I simply do something like this:

```
Print0(CRGB::Purple);
delay(500);

```

I have tried for the best part of the past two days to find a better way to go about this, but I couldn't. What I'm thinking is perhaps to create a function that would store all the digits instead of storing every one as an array, and then call it maybe within a for loop? something like

```
for(int i=0; i<10; i++){
    displaydigit[i];
    FastLED.show();
  }

```

Do you know of any library that has something similar, or perhaps any idea on how to achieve this?

Your assistance, as always, is greatly appreciated.

Thank You.

# Answer
First, for all the digits I'd use an 7 value array, indicating for every segment if it's ON or OFF. So for `0` your get `byte digit0[] = {1,1,1,1,1,1,0}`, where `1` indicates the segment is ON, and `0` indicates it's OFF. Your code then becomes:

```
void Print0(CRGB myColor){
  //Prints the digit 0:
  for(int i=0; i<7; i++){
    if( digit0[i] )
      leds[i] = CRGB (myColor);  //Switch the LED on
    else
      leds[i] = CRGB::Black; // Switch the LED off
  }
  FastLED.show();
}

```

The next step would be to create a two dimensional array containing which segments are on for which digits.

```
byte digits[10][7] = {
     {1,1,1,1,1,1,0} //0
    ,{0,1,1,0,0,0,0} //1
    ,{1,1,0,1,1,0,1} //2
    ,{1,1,1,1,0,0,1} //3
    ,{0,1,1,0,0,1,1} //4
    ,{1,0,1,1,0,1,1} //5
    ,{1,0,1,1,1,1,1} //6
    ,{1,1,1,0,0,0,0} //7
    ,{1,1,1,1,1,1,1} //8
    ,{1,1,1,1,0,1,1} //9
   }

```

Now you can generalize you Print0 function to accept any number:

```
void PrintNumber(byte number, CRGB myColor){
  if( number>9 )
    return;
  for(int i=0; i<7; i++){
    if( digit[number][i] )
      leds[i] = CRGB (myColor);  //Switch the LED on
    else
      leds[i] = CRGB::Black; // Switch the LED off
  }
  FastLED.show();
}

```

Call the new function in your `loop`; for example `PrintNumber(3, CRGB:White);`

If you want to put multiple 7-segment displays in series, you could add and `offset` argument to the PrintNumber function, and use `leds[i+offset]` instead. Then call the PrintNumber with offset 0 for the first digit/display, 7 for the second, 14 for the third, and so on.
> 1 votes

# Answer
In general, in many engineering efforts, a definition of the feature(s) and constraints need to be considered. The feature you are creating is a large-7-segment-display. Now decide what constraints you are working under. Normally, in embedded programming, this means limited memory, limited power and interacting with people.

Because of limited memory, consider storing 7-segment patterns in a condensed form. Also consider creating the simplest code possible. Usually the more data is compressed, the more complex the code needs to be. If there is a large amount of data (for example, an mp3 compressed sound track) the cost of high compression and complex code can be justified. But storing 7-segment patters is comparatively simple. So, consider expanding the array to include all 7 segments for each of the 10 digits. Store if each segment is on or off. Then, remove the "all on" and "all off" loops in your code leaving only one loop to read the array and turn off or on each segment.

Adapting the project to facilitate interacting with people can be confusing and difficult. Possibly the most common problem with displays are delays and flicker. For this project choosing the WS\* line of LEDs should mitigate flicker problems (at the very least it takes it out of your hands) as the PWM feature is the responsibility of each WS\* chip. People have been putting up with (expect) small delays when viewing large displays. And it is expected this approach could update perhaps 10 digits in less than hundreds of milliseconds.
> 0 votes

---
Tags: arduino-ide, led, rgb-led, led-strip, functions
---


# Question
Title: How to Set the Control Register on the DS3231 RTC module for Arduino UNO R3?
I am using the DS3231 RTC connected to an Arduino UNO R3 for a project. I won’t go into detail, but I need to save power, therefore I am using the DS3231 Alarm Interrupt to wake the Arduino from sleep. The Alarm Interrupt works fine when the Arduino is sleeping and connected to the 5V and GND pins of the Arduino, however it turns out that the DS3231 won’t fire a square wave interrupt when on battery power. **In order to turn it on, I need to set bit 7 of the Control Register (0Eh) to logic 1, and bit 6 to logic one.** I can’t find any documentation on how to do this, except for a few forums talking about it. What is the specific code to do this, and where would I place the code?

DS3231 Data Sheet (Control Register on p.13)

```
#include <Wire.h>
#include <RTClibExtended.h>
#include <LowPower.h>

#define wakePin 2    //use interrupt 0 (pin 2) and run function wakeUp when pin 2 gets LOW
#define ledPin 13    //use arduino on-board led for indicating sleep or wakeup status

RTC_DS3231 RTC;      //we are using the DS3231 RTC

byte AlarmFlag = 0;
byte ledStatus = 1;

//-------------------------------------------------

void wakeUp()        // here the interrupt is handled after wakeup
{
}

//------------------------------------------------------------

void setup() {
  //digitalWrite(wakePin,HIGH);
  //Set pin D2 as INPUT for accepting the interrupt signal from DS3231
  pinMode(wakePin, INPUT);

  //switch-on the on-board led for 1 second for indicating that the sketch is ok and running
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, HIGH);
  delay(1000);

  //Initialize communication with the clock
  Wire.begin();
  RTC.begin();
  RTC.adjust(DateTime(__DATE__, __TIME__));   //set RTC date and time to COMPILE time

  //clear any pending alarms
  RTC.armAlarm(1, false);
  RTC.clearAlarm(1);
  RTC.alarmInterrupt(1, false);
  RTC.armAlarm(2, false);
  RTC.clearAlarm(2);
  RTC.alarmInterrupt(2, false);

  //Set SQW pin to OFF (in my case it was set by default to 1Hz)
  //The output of the DS3231 INT pin is connected to this pin
  //It must be connected to Arduino D2 pin for wake-up
  RTC.writeSqwPinMode(DS3231_OFF);

  //Set alarm1 every day at 18:33
  RTC.setAlarm(ALM1_MATCH_HOURS, 16, 19, 0);   //set your wake-up time here
  RTC.alarmInterrupt(1, true);
}

//------------------------------------------------------------

void loop() {

  //On first loop we enter the sleep mode
  if (AlarmFlag == 0) {
    attachInterrupt(0, wakeUp, LOW);                       //use interrupt 0 (pin 2) and run function wakeUp when pin 2 gets LOW
    digitalWrite(ledPin, LOW);                             //switch-off the led for indicating that we enter the sleep mode
    ledStatus = 0;                                         //set the led status accordingly
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);   //arduino enters sleep mode here
    detachInterrupt(0);                                    //execution resumes from here after wake-up

    //When exiting the sleep mode we clear the alarm
    RTC.armAlarm(1, false);
    RTC.clearAlarm(1);
    RTC.alarmInterrupt(1, false);
    AlarmFlag++;
  }

  //cycles the led to indicate that we are no more in sleep mode
  if (ledStatus == 0) {
    ledStatus = 1;
    digitalWrite(ledPin, HIGH);
  }
  else {
    ledStatus = 0;
    digitalWrite(ledPin, LOW);
  }

  delay(500);
}

```

Also, how would I set it to go to sleep after the alarm?

Thanks!

P.s sorry about that Thomas, I'm a bit new here.

# Answer
> 0 votes
I took a look at the FabioCuomo-DS3231 library, as I guess that is what you are using, and I saw nothing related to setting those two bits. However, you can take inspiration from the code in the library to implement the functionality yourself.

I would try this:

```
void enableAlarmInLowPower(void) {
    // Read the control register.
    Wire.beginTransmission(DS3231_ADDRESS);
    Wire.write(DS3231_CONTROL);
    Wire.endTransmission();
    Wire.requestFrom((uint8_t)DS3231_ADDRESS, (uint8_t)1);
    uint8_t value = Wire.read();
    Wire.endTransmission();

    // Update it.
    value |= bit(6) | bit(7);  // set bits 6 and 7

    // Write it back.
    Wire.beginTransmission(DS3231_ADDRESS);
    Wire.write(DS3231_CONTROL);
    Wire.write(value);
    Wire.endTransmission();
}

```

Warning: not tested.

---
Tags: arduino-uno, power, code-review, rtc
---


# Question
Title: Can't create a RTC_DATA_ATTR var inside a class
I'm trying to create a deepSleep class for my ESP32 project, but I get this error : `section attribute not allowed for 'clock_beforeSleep'` The only place it compiles, is outside the class.

How should I declare it ?

**EDIT1**: Add Code

```
#include "EEPROM.h"
#include "time.h"
#include "WiFi.h"

RTC_DATA_ATTR long clock_expectedWake = 0;
RTC_DATA_ATTR int bootCounter = 0;
RTC_DATA_ATTR int driftRTC = 0;
RTC_DATA_ATTR long clock_beforeSleep = 0;

class esp32Sleep
{
#define EEPROM_SIZE 16
#define DEV_NAME "ESP32lite"
#define uS_TO_S_FACTOR 1000000ULL /* Conversion micro seconds to seconds */

private:
  char sleepstr[250];
  // RTC_DATA_ATTR long clock_expectedWake = 0;
.
.
.

```

# Answer
You can't put an `RTC_DATA_ATTR` qualified variable inside a class because the class is stored in normal RAM. The `RTC_DATA_ATTR` qualified variable is, by definition, stored in RTC RAM.

The definition of `RTC_DATA_ATTR` includes a `section` attribute (`__attribute__((section(".rtc.data")))`) that tells the compiler where abouts in memory the variable should be stored (in this case the 8kiB of "slow" RTC memory). That is mutually exclusive with where the compiler decides to store the class.

It's like you have a diamond necklace which the has to be kept in a safe at all times, but you want to wear it around your neck *whilst at the same time storing it in the safe*. You can't do it.
> 3 votes

# Answer
I think some explanation about the different allocation schemes could be useful:

* Global variables, as well as static locals and static class members, are allocated at build time, by the linker, typically in the .data or .bss section of the program.
* Local variables are allocated at run time in the stack. Typically the compiler issues some instructions to adjust the stack pointer in order to make room for the variable. As an optimization, the most used locals can be stored directly in CPU registers, but this optimization is disabled if you use the address of the variable.
* Variables created with `new` and `malloc()` are allocated at run time in the heap. This allocation is handled by a support library.

Note that objects are variables and are allocated in one piece, just like a C `struct`. Static class members are not part of the class instances.

Now, some build chains have extensions that allow you to store statically allocated variables elsewhere than the RAM. One example is the `PROGMEM` storage on AVR. `RTC_DATA_ATTR` sounds like a similar extension. You may be able to store a regular class member this way if:

1. The object is global and stored as `RTC_DATA_ATTR` as a whole.
2. It doesn't need a constructor.
> 1 votes

---
Tags: esp32, sleep
---


# Question
Title: Using millis() to create a timed sequence of events
I was hoping anyone could help me with my problem.

I am trying to play a sequence of tones without using delay. So I am relying on millis(). However I have not been successful yet and after reading multiple tutorials about using millis(), I could not find one that covers sequencies of events. What I am trying to do is the following:

* Play a tone1 for 1 s
* After 1 second (duration which tone 1 is played) play tone 2
* After 1 second (duration which tone 2 is played) play tone 3
* After 1 second (duration which tone 3 is played) play tone 4

With the current code I have, everything seems to be played at the same time and not really considering my IF statements.

Code:

```
#include "pitches.h"

int notes[]={
NOTE_B1,
NOTE_C2,
NOTE_CS2,
NOTE_D2,
NOTE_DS2,
NOTE_E2,
NOTE_F2,
NOTE_FS2,
NOTE_G2,
NOTE_GS2,
NOTE_A2,
NOTE_AS2,
NOTE_B2,
NOTE_C3,
NOTE_CS3,
NOTE_D3,
NOTE_DS3,
NOTE_E3,
NOTE_F3,
NOTE_FS3,
NOTE_G3,
NOTE_GS3,
NOTE_A3,
NOTE_AS3,
NOTE_B3,
NOTE_C4,
NOTE_CS4,
NOTE_D4,
NOTE_DS4,
NOTE_E4,
NOTE_F4,
NOTE_FS4,
NOTE_G4,
NOTE_GS4,
NOTE_A4,
NOTE_AS4,
NOTE_B4,
NOTE_C5,
NOTE_CS5,
NOTE_D5,
NOTE_DS5,
NOTE_E5,
NOTE_F5,
NOTE_FS5,
NOTE_G5,
NOTE_GS5,
NOTE_A5,
NOTE_AS5,
NOTE_B5,
NOTE_C6,
NOTE_CS6,
NOTE_D6,
NOTE_DS6,
NOTE_E6,
NOTE_F6,
NOTE_FS6,
NOTE_G6,
NOTE_GS6,
NOTE_A6,
NOTE_AS6,
NOTE_B6,
NOTE_C7,
NOTE_CS7,
NOTE_D7,
NOTE_DS7,
NOTE_E7,
NOTE_F7,
NOTE_FS7,
NOTE_G7,
NOTE_GS7,
NOTE_A7,
NOTE_AS7,
NOTE_B7,
NOTE_C8,
NOTE_CS8,
NOTE_D8,
NOTE_DS8
};

int speakerPin = 3;

 #define N_BUTTONS 8

int button_pins[N_BUTTONS] = {6, 7, 8, 9, 10, 11, 12, 13}; // Putting button_pins into an array

int Pitches[N_BUTTONS] = {0}; // Define array to hold the pitch. Setting it to 0.

long Durations[N_BUTTONS]; // Define array to hold the duration of the note. Setting it to 500.

unsigned long startMillis;
unsigned long startMillis_2;
unsigned long startMillis_3;
unsigned long startMillis_4;
unsigned long currentMillis;
unsigned long period = 1000;

void setup() {

Serial.begin(9600);

for(int pin : button_pins) pinMode(pin, INPUT); // Define the input pins for button_pins

startMillis = millis();

}

void loop() {

for (int button=0; button<N_BUTTONS ; button++){
  if(digitalRead(button_pins[button])){
    Pitches[button] = analogRead(A0)/13;   // As we have 77 pitches we divide the max Potentiometer value by 77. This equals 13.
    Durations[button] = analogRead(A1)*4;
   }
  }
////////////////////OUTPUT CODE////////////////////Sound generation code /////////////////////////////////

unsigned long currentMillis = millis(); // Gets the current time

if (currentMillis - startMillis >= period)  // Start event after 1 second
  {
  tone(speakerPin, notes[Pitches[0]], period);
  Serial.print("pitch1= ");
  Serial.println(Pitches[0]);
  Serial.print("duration1= ");
  Serial.println(period);
  Serial.print("millis = ");
  Serial.println(currentMillis);
  startMillis_2 = currentMillis;   // Saves the current time into the variable
  Serial.print("startMillis_2 = ");
  Serial.println(startMillis_2);
  }

if (currentMillis - startMillis_2 >= period)
  {
  tone(speakerPin, notes[Pitches[1]], period);
  Serial.print("pitch2= ");
  Serial.println(Pitches[1]);
  Serial.print("duration2= ");
  Serial.println(period);
  startMillis_3 = currentMillis;
  Serial.print("millis = ");
  Serial.println(currentMillis);
  Serial.print("startMillis_3 = ");
  Serial.println(startMillis_3);
  }

if (currentMillis - startMillis_3>= period)
  {
  tone(speakerPin, notes[Pitches[2]], period);
  Serial.print("pitch3= ");
  Serial.println(Pitches[2]);
  Serial.print("duration3= ");
  Serial.println(period);
  startMillis_4 = currentMillis;
  Serial.print("millis = ");
  Serial.println(currentMillis);
  Serial.print("startMillis_4 = ");
  Serial.println(startMillis_4);
  }

unsigned long startMillis_4;

if (currentMillis - startMillis_4 >= period)
  {
  tone(speakerPin, notes[Pitches[3]], period);
  Serial.print("pitch4= ");
  Serial.println(Pitches[3]);
  Serial.print("duration4= ");
  Serial.println(period);
  startMillis = currentMillis;
  Serial.print("millis = ");
  Serial.println(currentMillis);
  Serial.print("startMillis = ");
  Serial.println(startMillis);
  }

}

```

---

I have managed to get my code running on delay. It is working but I am very limited on what I can accomplish if I want more. I have read through all answers and comments but was still unable to get a millis() solution since my main problem was how to get tone 2 started and so on. I can get the first tone to play on a loop and correct intervals, but I am not understanding how to trigger the start of tone 2. Here is my code with delay. If anyone has can guide me to use millis() specially to trigger the start the tone 2, it would be very helpful.

EDIT. New Code:

```
#include "pitches.h"

int notes[]={
0,
NOTE_B1,
NOTE_C2,
NOTE_CS2,
NOTE_D2,
NOTE_DS2,
NOTE_E2,
NOTE_F2,
NOTE_FS2,
NOTE_G2,
NOTE_GS2,
NOTE_A2,
NOTE_AS2,
NOTE_B2,
NOTE_C3,
NOTE_CS3,
NOTE_D3,
NOTE_DS3,
NOTE_E3,
NOTE_F3,
NOTE_FS3,
NOTE_G3,
NOTE_GS3,
NOTE_A3,
NOTE_AS3,
NOTE_B3,
NOTE_C4,
NOTE_CS4,
NOTE_D4,
NOTE_DS4,
NOTE_E4,
NOTE_F4,
NOTE_FS4,
NOTE_G4,
NOTE_GS4,
NOTE_A4,
NOTE_AS4,
NOTE_B4,
NOTE_C5,
NOTE_CS5,
NOTE_D5,
NOTE_DS5,
NOTE_E5,
NOTE_F5,
NOTE_FS5,
NOTE_G5,
NOTE_GS5,
NOTE_A5,
NOTE_AS5,
NOTE_B5,
NOTE_C6,
NOTE_CS6,
NOTE_D6,
NOTE_DS6,
NOTE_E6,
NOTE_F6,
NOTE_FS6,
NOTE_G6,
NOTE_GS6,
NOTE_A6,
NOTE_AS6,
NOTE_B6,
NOTE_C7,
NOTE_CS7,
NOTE_D7,
NOTE_DS7,
NOTE_E7,
NOTE_F7,
NOTE_FS7,
NOTE_G7,
NOTE_GS7,
NOTE_A7,
NOTE_AS7,
NOTE_B7,
NOTE_C8,
NOTE_CS8,
NOTE_D8,
NOTE_DS8
};

int speakerPin = 3;

#define N_BUTTONS 8

// Input variables definitions

int button_pins[N_BUTTONS] = {6, 7, 8, 9, 10, 11, 12, 13}; // Putting button_pins into an array

int Pitches[N_BUTTONS] = {0}; // Define array to hold the pitch. Setting it to 0.

long Durations[N_BUTTONS]; // Define array to hold the duration of the note. Setting it to 500.

void setup() {

Serial.begin(9600);

for(int pin : button_pins) pinMode(pin, INPUT); // Define the input pins for button_pins

}

void loop() {
int tempo = analogRead(A2);
for (int button=0; button<N_BUTTONS ; button++){
  if(digitalRead(button_pins[button])){
    Pitches[button] = analogRead(A0)/13;   // As we have 78 pitches we divide the max Potentiometer value by 77. This equals 13.
    Durations[button] = (analogRead(A1)*4) + tempo;
   }
  }
////////////////////OUTPUT CODE////////////////////Sound generation code /////////////////////////////////
  for (int button=0; button <N_BUTTONS ; button++){
  tone(speakerPin, notes[Pitches[button]], Durations[button]);
  delay(tempo);
  Serial.print("Pitch");
  Serial.print(button);
  Serial.print(" = ");
  Serial.println(Pitches[button]);
  Serial.print("Duration");
  Serial.print(button);
  Serial.print(" = ");
  Serial.println(Durations[button]);
  Serial.println(tempo);
  }
}

```

# Answer
You are overcomplicating the program. There is no point in remembering when each of the notes started. You just have to remember:

* what note is currently playing
* when you started playing this note

Then the logic of `loop()` becomes simply: “if we are done with the current note, then start playing the next one.” In code:

**Edit**: Changed the code to include your button-scanning loop.

```
int current_button;
uint32_t note_started;

void loop() {
    // Adjust the notes on button presses.
    for (int button = 0; button < N_BUTTONS; button++) {
        if (digitalRead(button_pins[button])) {
            // As we have 78 pitches we divide the max Potentiometer
            // value by 77. This equals 13.
            Pitches[button] = analogRead(A0)/13;
            Durations[button] = analogRead(A1)*4;
        }
    }

    // Are we done with the current note?
    uint32_t now = millis();
    int tempo = analogRead(A2);
    if (now - note_started >= Durations[current_button] + tempo) {

        // Then move to the next note.
        ++current_button;

        // Finished the tune?
        if (current_button == N_BUTTONS) {
            current_button = 0;  // then restart from the beginning
        }

        // Play the note.
        tone(speakerPin,
                Pitches[current_button], Durations[current_button]);

        // Take note of when this started.
        note_started = now;
    }
}

```
> 1 votes

# Answer
Your code falls through (skips over) the first “if” statement in the output code because its time period has not yet passed.

It then starts to use startMillis\_2, which is not yet initialized (and may be any value), in the next “if”.

Initialization of startMillis\_2 only happens inside the first “if” statement but that code has not yet been executed.

The same goes for startMillis\_3 and 4.

But I think there’s something more fundamentally wrong with your code. You execute all “if” statements inside of a loop that is continuously repeated. There is no sequence. You have to make sure that tone 2 can only be started after tone 1, etcetera.
> 0 votes

---
Tags: millis, programming-sequence
---


# Question
Title: Managing configurations via EEPROM by writing it with the hex file
I've been looking into I2C bootloaders for an ATTINY coprocessor on a board I'm developing, and I ran into a bit of a snag. I have the need to detect what board the main processor's code is running on, since there are a number of write-only peripherals I can't probe for presence or configuration (WS2812-series LEDs and a SSD1306 screen, among a few others), and I was going to manage that via a configuration blob stored on the ATTINY.

Unfortunately, this was coded into the firmware, and pushing out any sort of update for the coprocessor would then require that I build, label, and provide each version, and then have the user choose the correct one.

So, the solution would seemingly be EEPROM, since that can be set to persist over programming attempts (there's even a fuse setting to keep it, although in the other case how the AVR knows if it's been programmed \[in the era of bootloaders\] I'm not sure).

The issue is now that I need a way to set the EEPROM configuration when I create the original program, and then have future updates not touch it. The existing way is that I add a stub to my code that checks if there's a config and sets it (unfortunately per-unique-board-design, so I'd need lots of different copies again) and then never touches it again. Future firmwares could then just not include any stub at all.

However, this annoys me, especially since if something goes wrong it could mess up the EEPROM.

Does anyone know of a way to use a ICSP programmer to set EEPROM, ideally as part of the firmware upload?

I am using a usbasp with PlatformIO to do the chip programming, so I should have enough access on the first burning to change the EEPROM. Does anyone know how I could add in an EEPROM configuration to go with the flash one?

Some thoughts I have had:

1. Somehow modify/append the hex file to include data that goes to EEPROM and then burn it
2. Add a script to PlatformIO that lets me edit/compile/upload/whatever to EEPROM (I do not speak Python, so I'd need help)
3. Use an existing feature of PlatformIO/the build process/the AVR toolchain to set an EEPROM configuration (I have to suspect there is one, but Googling does not seem to have pointed one out)
4. Somehow do this with AVRDude

# Answer
`AVRDUDE` can program EEPROM. I usually do this as part of the firmware burn - the operator can pick which config block should go into the board while running the programming cycle. In some cases the EEPROM info is even generated programmatically during the cycle to contain dynamic info like unit serial number and commision date.

Here is an example command line that will program the file `filename.hex` into EEPROM...

```
avrdude -c stk500v2 -P COM6 -p atmega328p -U eeprom:w:filename.hex:i

```

The `AVRDUDE` write command (`U`) has many options to do almost anything you want...

```
-U memtype:op:filename[:format]
Perform a memory operation. Multiple ‘-U’ options can be specified in order to operate on multiple memories on the same command-line invocation. The memtype field specifies the memory type to operate on. Use the ‘-v’ option on the command line or the part command from terminal mode to display all the memory types supported by a particular device. Typically, a device’s memory configuration at least contains the memory types flash and eeprom. All memory types currently known are:
(...)
MEMTYPE:
eeprom
The EEPROM of the device.
(...)

OP:
w
read the specified file and write it to the specified device memory

(...)

FILENAME:
The filename field indicates the name of the file to read or write. The format field is optional and contains the format of the file to read or write. Possible values are:

i
Intel Hex

s
Motorola S-record

r
raw binary; little-endian byte order, in the case of the flash ROM data

e
ELF (Executable and Linkable Format), the final output file from the linker; currently only accepted as an input file

m
immediate mode; actual byte values specified on the command line, separated by commas or spaces in place of the filename field of the ‘-U’ option. This is useful for programming fuse bytes without having to create a single-byte file or enter terminal mode. If the number specified begins with 0x, it is treated as a hex value. If the number otherwise begins with a leading zero (0) it is treated as octal. Otherwise, the value is treated as decimal.

a
auto detect; valid for input only, and only if the input is not provided at stdin.

d
decimal; this and the following formats are only valid on output. They generate one line of output for the respective memory section, forming a comma-separated list of the values. This can be particularly useful for subsequent processing, like for fuse bit settings.

h
hexadecimal; each value will get the string 0x prepended.

o
octal; each value will get a 0 prepended unless it is less than 8 in which case it gets no prefix.

b
binary; each value will get the string 0b prepended.

The default is to use auto detection for input files, and raw binary format for output files.

Note that if filename contains a colon, the format field is no longer optional since the filename part following the colon would otherwise be misinterpreted as format.

As an abbreviation, the form -U filename is equivalent to specifying -U flash:w:filename:a. This will only work if filename does not have a colon in it.

```

Any of these files types can be used depending on what kind of data you are writing to the EEPROM and how it is being generated.

More info here... https://www.pololu.com/docs/0J67/5.8
> 2 votes

---
Tags: attiny, avrdude, eeprom, ide, programmer
---


# Question
Title: Does using multiple HX711 amplifiers change the supply voltage of an Arduino?
I’m creating essentially a load cell using an Arduino Nano and an HX711 amplifier. However, I want to have two HX711 amplifiers running off the same Arduino. Will that change the supply voltage since I’m using two (ex. Does it change from 5V to 2.5V)? I need an accurate supply voltage for the Wheatstone bridge equations to determine strain from the strain gauge readings, but I’m unsure what adding another amplifier will do to the supply voltage.

# Answer
> Will that change the supply voltage

No. Components and circuits connected in parallel add together their current requirements, but the voltage stays the same.
> 0 votes

---
Tags: sensors, arduino-nano, voltage, op-amp
---


title: HLK-RM04 wifi shield factory reset?

text:
# Question
Title: HLK-RM04 wifi shield factory reset?
I have this HLK-RM04:

It came with no catalogue or manual all threads about it are in Chinese after when I found the configuration webpage and changing it to client it wont connect and it stopped board casting hlink wifi how could i reset to factory settings?

After very long search I found an English manual.

What does Trst means ? I don’t understand what I must do to reset it!

# Answer
> 2 votes
Since no one has posted an answer, and I finally found one myself. Ground pin 10 for 6 seconds.

---
Tags: arduino-uno, shields, wifi
---


title: Designing RGB leds

text:
# Question
Title: Designing RGB leds
I am interested in creating a string of ~80 RGB LEDs run on an Arduino Uno. Each LED is to have its own on/off timing and color and the distance from one LED to the next about 4-5 feet.

Since I want to program each LED separately can I do that with strings like the Adafruit Pixels (https://www.adafruit.com/product/322) or do I have to set it up with separate RGB LEDs and daisy chain them?

Thanks for your help with this.

# Answer
> do I have to set it up with separate RGB LEDs and daisy chain them?

That's exactly, what the string of Neopixels, that you linked, is: Separate WS2801 RGB LED chips, which are daisy chained together. Since the distance of the LEDs on the string is not 4-5 feet, you cannot use the string directly.

You can either cut the string and extent the cables, as you need to. Or you can buy single LEDs and use completely your own cables. That's up to you; technically it is completely the same.

But since 80 LEDs, each 4 feet apart, will give you about 100m/330feet, you get a problem with the resistance of the wire. First about power supply:

You whole strip would need up to 4.8A of power, with every pixel at full white. You need to transport that current from your source, down to the very last LED. Make sure, that the used wire has very low resistance and is rated for such a current. If the resistance is to high, you will loose voltage over every meter of the cable and the last LEDs might be off color or not working.

I think the signal lines will be fine despite the distance, since every LED outputs them again to the next LED, so the signal should be kind of refined on every LED (though I don't know, how the WS2801 chips work internally).
> 1 votes

---
Tags: led, rgb-led
---


title: Arduino Nano clone doesn't upload Linux

text:
# Question
Title: Arduino Nano clone doesn't upload Linux
I've been trying to upload sketch to Arduino Nano clone (CH340G RS232 to USB converter). I have ArchLinux. My port is detected as /dev/ttyUSB0 (Official Arduino Uno is /dev/ttyACM0). After trying to upload a sketch avrdude responds with

```
avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x44

```

or

```
avrdude: stk500_getsync(): can't communicate with device: resp=0x88

```

After using verbose output it seems like it does not read from the arduino back to PC. I have all my permissions correct and everything was working to this date. I also used many arduinos which I also burned bootloader on using my Arduino Uno. Everything also works on seconds PC with Windows. Any ideas?

Linux log:

```
/usr/share/arduino/arduino-builder -dump-prefs -logger=machine -hardware /usr/share/arduino/hardware -hardware /home/jakub/.arduino15/packages -tools /usr/share/arduino/tools-builder -tools /home/jakub/.arduino15/packages -libraries /home/jakub/Arduino/libraries -fqbn=arduino:avr:nano:cpu=atmega328 -vid-pid=1A86_7523 -ide-version=10809 -build-path /tmp/arduino_build_539099 -warnings=all -build-cache /tmp/arduino_cache_182117 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=/home/jakub/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino5 -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino5.path=/home/jakub/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino5 -prefs=runtime.tools.arduinoOTA.path=/home/jakub/.arduino15/packages/arduino/tools/arduinoOTA/1.3.0 -prefs=runtime.tools.arduinoOTA-1.3.0.path=/home/jakub/.arduino15/packages/arduino/tools/arduinoOTA/1.3.0 -prefs=runtime.tools.avrdude.path=/home/jakub/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17 -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=/home/jakub/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17 -verbose /usr/share/arduino/examples/01.Basics/Blink/Blink.ino
/usr/share/arduino/arduino-builder -compile -logger=machine -hardware /usr/share/arduino/hardware -hardware /home/jakub/.arduino15/packages -tools /usr/share/arduino/tools-builder -tools /home/jakub/.arduino15/packages -libraries /home/jakub/Arduino/libraries -fqbn=arduino:avr:nano:cpu=atmega328 -vid-pid=1A86_7523 -ide-version=10809 -build-path /tmp/arduino_build_539099 -warnings=all -build-cache /tmp/arduino_cache_182117 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=/home/jakub/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino5 -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino5.path=/home/jakub/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino5 -prefs=runtime.tools.arduinoOTA.path=/home/jakub/.arduino15/packages/arduino/tools/arduinoOTA/1.3.0 -prefs=runtime.tools.arduinoOTA-1.3.0.path=/home/jakub/.arduino15/packages/arduino/tools/arduinoOTA/1.3.0 -prefs=runtime.tools.avrdude.path=/home/jakub/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17 -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=/home/jakub/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17 -verbose /usr/share/arduino/examples/01.Basics/Blink/Blink.ino
Using board 'nano' from platform in folder: /home/jakub/.arduino15/packages/arduino/hardware/avr/1.8.2
Using core 'arduino' from platform in folder: /home/jakub/.arduino15/packages/arduino/hardware/avr/1.8.2
Detecting libraries used...
/home/jakub/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino5/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR -I/home/jakub/.arduino15/packages/arduino/hardware/avr/1.8.2/cores/arduino -I/home/jakub/.arduino15/packages/arduino/hardware/avr/1.8.2/variants/eightanaloginputs /tmp/arduino_build_539099/sketch/Blink.ino.cpp -o /dev/null
Generating function prototypes...
/home/jakub/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino5/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR -I/home/jakub/.arduino15/packages/arduino/hardware/avr/1.8.2/cores/arduino -I/home/jakub/.arduino15/packages/arduino/hardware/avr/1.8.2/variants/eightanaloginputs /tmp/arduino_build_539099/sketch/Blink.ino.cpp -o /tmp/arduino_build_539099/preproc/ctags_target_for_gcc_minus_e.cpp
/usr/bin/arduino-ctags -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives /tmp/arduino_build_539099/preproc/ctags_target_for_gcc_minus_e.cpp
Kompilujem projekt...
/home/jakub/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino5/bin/avr-g++ -c -g -Os -Wall -Wextra -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR -I/home/jakub/.arduino15/packages/arduino/hardware/avr/1.8.2/cores/arduino -I/home/jakub/.arduino15/packages/arduino/hardware/avr/1.8.2/variants/eightanaloginputs /tmp/arduino_build_539099/sketch/Blink.ino.cpp -o /tmp/arduino_build_539099/sketch/Blink.ino.cpp.o
Compiling libraries...
Compiling core...
Using precompiled core: /tmp/arduino_cache_182117/core/core_arduino_avr_nano_cpu_atmega328_6ffe6e1951fbeab8145453327f70df2d.a
Linking everything together...
/home/jakub/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino5/bin/avr-gcc -Wall -Wextra -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -mmcu=atmega328p -o /tmp/arduino_build_539099/Blink.ino.elf /tmp/arduino_build_539099/sketch/Blink.ino.cpp.o /tmp/arduino_build_539099/../arduino_cache_182117/core/core_arduino_avr_nano_cpu_atmega328_6ffe6e1951fbeab8145453327f70df2d.a -L/tmp/arduino_build_539099 -lm
/home/jakub/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino5/bin/avr-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 /tmp/arduino_build_539099/Blink.ino.elf /tmp/arduino_build_539099/Blink.ino.eep
/home/jakub/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino5/bin/avr-objcopy -O ihex -R .eeprom /tmp/arduino_build_539099/Blink.ino.elf /tmp/arduino_build_539099/Blink.ino.hex
/home/jakub/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino5/bin/avr-size -A /tmp/arduino_build_539099/Blink.ino.elf
Projekt zaberá 924 bytov (3%) pamäte pre program. Maximum je 30720 bytov.
Globálne premenné zaberajú 9 bytov (0%)  dynamickej pamäti, 2039 bytov zostáva pre lokálne premenné. Maximum je 2048 bytov.
/home/jakub/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude -C/home/jakub/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf -v -patmega328p -carduino -P/dev/ttyUSB0 -b115200 -D -Uflash:w:/tmp/arduino_build_539099/Blink.ino.hex:i

avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

     System wide configuration file is "/home/jakub/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf"
     User configuration file is "/home/jakub/.avrduderc"
     User configuration file does not exist or is not a regular file, skipping

     Using Port                    : /dev/ttyUSB0
     Using Programmer              : arduino
     Overriding Baud Rate          : 115200
     AVR Part                      : ATmega328P
     Chip Erase delay              : 9000 us
     PAGEL                         : PD7
     BS2                           : PC2
     RESET disposition             : dedicated
     RETRY pulse                   : SCK
     serial program mode           : yes
     parallel program mode         : yes
     Timeout                       : 200
     StabDelay                     : 100
     CmdexeDelay                   : 25
     SyncLoops                     : 32
     ByteDelay                     : 0
     PollIndex                     : 3
     PollValue                     : 0x53
     Memory Detail                 :

                              Block Poll               Page                       Polled
       Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
       ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
       eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
       flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
       lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
       hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
       efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
       lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
       calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
       signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

     Programmer Type : Arduino
     Description     : Arduino

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0xfc

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0xfc

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0xfc
         Hardware Version: 4238814
         Firmware Version: 21984432.4
         Topcard         : Unknown

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0xfc

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0xfc

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0xfc

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0xfc
         Vtarget         : 0.0 V
         Varef           : 1992555.2 V
         Oscillator      : Off
         SCK period      : 0.1 us

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x88

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0xfc
avrdude: AVR device initialized and ready to accept instructions

Reading |
avrdude: arduino_read_sig_bytes(): (a) protocol error, expect=0x10, resp=0xfc
avrdude: error reading signature data for part "ATmega328P", rc=-3
avrdude: error reading signature data, rc=-3

avrdude done.  Thank you.

```

Windows log:

```
C:\Program Files (x86)\Arduino\arduino-builder -dump-prefs -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\Adamko\Documents\Arduino\libraries -fqbn=arduino:avr:nano:cpu=atmega328 -ide-version=10807 -build-path C:\Users\Adamko\AppData\Local\Temp\arduino_build_858804 -warnings=all -build-cache C:\Users\Adamko\AppData\Local\Temp\arduino_cache_611368 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -prefs=runtime.tools.avr-gcc-5.4.0-atmel3.6.1-arduino2.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -prefs=runtime.tools.arduinoOTA.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -prefs=runtime.tools.arduinoOTA-1.2.1.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -prefs=runtime.tools.avrdude.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -prefs=runtime.tools.avrdude-6.3.0-arduino14.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -verbose C:\Program Files (x86)\Arduino\examples\01.Basics\Blink\Blink.ino
C:\Program Files (x86)\Arduino\arduino-builder -compile -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\Adamko\Documents\Arduino\libraries -fqbn=arduino:avr:nano:cpu=atmega328 -ide-version=10807 -build-path C:\Users\Adamko\AppData\Local\Temp\arduino_build_858804 -warnings=all -build-cache C:\Users\Adamko\AppData\Local\Temp\arduino_cache_611368 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -prefs=runtime.tools.avr-gcc-5.4.0-atmel3.6.1-arduino2.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -prefs=runtime.tools.arduinoOTA.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -prefs=runtime.tools.arduinoOTA-1.2.1.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -prefs=runtime.tools.avrdude.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -prefs=runtime.tools.avrdude-6.3.0-arduino14.path=C:\Program Files (x86)\Arduino\hardware\tools\avr -verbose C:\Program Files (x86)\Arduino\examples\01.Basics\Blink\Blink.ino
Using board 'nano' from platform in folder: C:\Program Files (x86)\Arduino\hardware\arduino\avr
Using core 'arduino' from platform in folder: C:\Program Files (x86)\Arduino\hardware\arduino\avr
Detecting libraries used...
"C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10807 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\variants\\eightanaloginputs" "C:\\Users\\Adamko\\AppData\\Local\\Temp\\arduino_build_858804\\sketch\\Blink.ino.cpp" -o nul
Generating function prototypes...
"C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10807 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\variants\\eightanaloginputs" "C:\\Users\\Adamko\\AppData\\Local\\Temp\\arduino_build_858804\\sketch\\Blink.ino.cpp" -o "C:\\Users\\Adamko\\AppData\\Local\\Temp\\arduino_build_858804\\preproc\\ctags_target_for_gcc_minus_e.cpp"
"C:\\Program Files (x86)\\Arduino\\tools-builder\\ctags\\5.8-arduino11/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "C:\\Users\\Adamko\\AppData\\Local\\Temp\\arduino_build_858804\\preproc\\ctags_target_for_gcc_minus_e.cpp"
Kompilujem projekt...
"C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr/bin/avr-g++" -c -g -Os -Wall -Wextra -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10807 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\variants\\eightanaloginputs" "C:\\Users\\Adamko\\AppData\\Local\\Temp\\arduino_build_858804\\sketch\\Blink.ino.cpp" -o "C:\\Users\\Adamko\\AppData\\Local\\Temp\\arduino_build_858804\\sketch\\Blink.ino.cpp.o"
Compiling libraries...
Compiling core...
Using precompiled core: C:\Users\Adamko\AppData\Local\Temp\arduino_cache_611368\core\core_arduino_avr_nano_cpu_atmega328_0c812875ac70eb4a9b385d8fb077f54c.a
Linking everything together...
"C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr/bin/avr-gcc" -Wall -Wextra -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -mmcu=atmega328p -o "C:\\Users\\Adamko\\AppData\\Local\\Temp\\arduino_build_858804/Blink.ino.elf" "C:\\Users\\Adamko\\AppData\\Local\\Temp\\arduino_build_858804\\sketch\\Blink.ino.cpp.o" "C:\\Users\\Adamko\\AppData\\Local\\Temp\\arduino_build_858804/..\\arduino_cache_611368\\core\\core_arduino_avr_nano_cpu_atmega328_0c812875ac70eb4a9b385d8fb077f54c.a" "-LC:\\Users\\Adamko\\AppData\\Local\\Temp\\arduino_build_858804" -lm
"C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr/bin/avr-objcopy" -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 "C:\\Users\\Adamko\\AppData\\Local\\Temp\\arduino_build_858804/Blink.ino.elf" "C:\\Users\\Adamko\\AppData\\Local\\Temp\\arduino_build_858804/Blink.ino.eep"
"C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr/bin/avr-objcopy" -O ihex -R .eeprom "C:\\Users\\Adamko\\AppData\\Local\\Temp\\arduino_build_858804/Blink.ino.elf" "C:\\Users\\Adamko\\AppData\\Local\\Temp\\arduino_build_858804/Blink.ino.hex"
"C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr/bin/avr-size" -A "C:\\Users\\Adamko\\AppData\\Local\\Temp\\arduino_build_858804/Blink.ino.elf"
Projekt zaberá 930 bytov (3%) pamäte pre program. Maximum je 30720 bytov.
Globálne premenné zaberajú 9 bytov (0%)  dynamickej pamäti, 2039 bytov zostáva pre lokálne premenné. Maximum je 2048 bytov.
C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avrdude -CC:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -carduino -PCOM3 -b115200 -D -Uflash:w:C:\Users\Adamko\AppData\Local\Temp\arduino_build_858804/Blink.ino.hex:i

avrdude: Version 6.3-20171130
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf"

         Using Port                    : COM3
         Using Programmer              : arduino
         Overriding Baud Rate          : 115200
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

         Programmer Type : Arduino
         Description     : Arduino
         Hardware Version: 3
         Firmware Version: 4.4
         Vtarget         : 0.3 V
         Varef           : 0.3 V
         Oscillator      : 28.800 kHz
         SCK period      : 3.3 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading input file "C:\Users\Adamko\AppData\Local\Temp\arduino_build_858804/Blink.ino.hex"
avrdude: writing flash (930 bytes):

Writing | ################################################## | 100% 0.16s

avrdude: 930 bytes of flash written
avrdude: verifying flash memory against C:\Users\Adamko\AppData\Local\Temp\arduino_build_858804/Blink.ino.hex:
avrdude: load data flash data from input file C:\Users\Adamko\AppData\Local\Temp\arduino_build_858804/Blink.ino.hex:
avrdude: input file C:\Users\Adamko\AppData\Local\Temp\arduino_build_858804/Blink.ino.hex contains 930 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.12s

avrdude: verifying ...
avrdude: 930 bytes of flash verified

avrdude done.  Thank you.

```

**UPDATE** Added the avrdude logs and command line.

# Answer
The problem is in kernel ch341 driver. Using 5.3.3 on Archlinux and 5.6 rc1.

https://github.com/torvalds/linux/blob/e33eab9ded328ccc14308afa51b5be7cbe78d30b/drivers/usb/serial/ch341.c

This driver version compiled using this Makefile

```
obj-m += ch341-m.o

all:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

reload: all
        sudo rmmod ch341-m ||true
        sudo insmod ./ch341-m.ko

```

Made it upload again. Hope it will be solved in kernel soon. I think the problem is addressed here

https://github.com/torvalds/linux/commit/35714565089e5e8b091c1155517b67e29118f09d#commitcomment-37154772

But the guy said it was solved in 5.6 rc1 which was not in my case.
> 3 votes

# Answer
I think you should try disconnecting any VCC port you have and see if it uploads if it does, after uploading the code reconnect the VCC ports again.
> 0 votes

---
Tags: uploading, clones, ch340, upload
---


# Question
Title: WindowsError(31, 'A device attached to the system is not functioning.') in arduino
Having board esp32 devkit v1, to get started with arduino ide (installed recommended boards for esp32) I marked board as`DOIT ESP32 DEVKIT V1` (as no other options as like `ESP32 DEVKIT V1` ) so upload gets this error

```
    esptool.py v2.6
Serial port COM3
Traceback (most recent call last):
File "esptool.py", line 2959, in <module>
File "esptool.py", line 2952, in _main
File "esptool.py", line 2652, in main
File "esptool.py", line 222, in __init__
File "site-packages\serial\__init__.py", line 88, in serial_for_url
File "site-packages\serial\serialwin32.py", line 62, in open
serial.serialutil.SerialException: could not open port 'COM3': WindowsError(31, 'A device attached to the system is not functioning.')
Failed to execute script esptool
the selected serial port Failed to execute script esptool
 does not exist or your board is not connected

```

so how do I upload my programs? I would be highly obliged if you could please help me solve this problem. Thank you.

# Answer
I got this error. Then switching USB ports fixed the problem. Showed up on COM3 in either place. I just switched from a built-in USB port to on off a hub, and it started working.
> 1 votes

---
Tags: arduino-ide, esp32, espressif
---


title: ESP8266-01 Resetting when DC motor runs

text:
# Question
Title: ESP8266-01 Resetting when DC motor runs
```
DC motor: 3-6v
Servo sg90: 3-7.2v
Esp 8266 01: 3.3v

```

I have 2 Arduino Uno both has their own ac-dc power adapter. Lets say, 1st Arduino is `Ard1` and 2nd is `Ard2`.

The `Ard1` communicates to a web server (BLYNK) with Esp 01.

Using I2C, `Ard1` sends command to `Ard2` to power/move the DC motor/Servo.

So far, **it has no problem operating with Servo**. But,

Whenever the `Ard1` commands the `Ard2` to power the DC motor.

Right when the DC motor runs(using `digitalWrite(motor,HIGH)`) the Esp 01 resets.

---

* Tried using `analogWrite(motor, 102)` though it won't reset instantly, prolong usage randomly resets it anytime.
* I also tried to test operating Servo and DC motor simultaneously in `Ard2` using Serial commands, without I2C/Esp01. There was no problem at all, both works flawlessly.

Below is the diagram of the wiring.

# Answer
Can you clear one thing that you are giving power to dc motor from 5v pin given on Arduino board or from your ac to dc power supply. If you are giving power to the motor from 5v pin of Arduino Uno then there is a high possibility that the motor is not getting sufficient current because 5v supply on Arduino comes from onboard lm1117 5v voltage regulator and cheap clon Arduino has a cheap regulator with less than 1amp capacity.
> 1 votes

---
Tags: esp8266, motor, reset
---


# Question
Title: WizNet W5100 not connecting to modern switches and routers
I have an Arduino data collector with a W5100 module (see bottom of picture). Simple fixed IP connection:

```
 byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
 byte ip[] = { 192, 168, 1, 242 };
 Ethernet.begin(mac,ip);

```

This works with my old routers (Asus WL500, TP-Link MR3420), but fails to connect when plugged in a gigabit switch or my new router (D-Link DWR-116). The connection LED on the new devices does not lit up or blinks slowly, showing repeated connection attempts. So the W5100 fails to make the physical connection.

I made it work by adding my 10-year old Surecom switch to the mix, but wonder what the problem could be. Is there some cable configuration that is used by the W5100 but have been removed from these new network devices? (Not sure if the cable is cross or straight, trying another cable is messy, the whole thing is built in the wall.)

# Answer
> 7 votes
I think your problem is due to the MAC address that is being loading into the W5100. Try setting the 2 low order bits of the first byte to 0.

These bits define whether the MAC address is unicast or multicast and whether it is private or universal. Some switches appear to block ARP requests if these bits are set incorrectly.

I changed the first byte of the MAC address from x'47' to x'44' and things started working.

# Answer
> 0 votes
I just made a setup on my Dell PowerConnect and it starts to accept the W5100. I had to change the port speed to 10M and it starts working. The 100M and 1000M was not accepting the w5100. Before, I had a CISCO wifi 10/100M wired connection between it and w5100 and it connects fine, but this isn't the main network on my company.

# Answer
> 0 votes
sounds like a mac address issue. I googled for Tp-Link MAC address bytes and it worked perfectly. (it is first 4 bytes)

---
Tags: ethernet
---


# Question
Title: ESP8266 compilation error: "previous declaration of 'HTTPMethod HTTP_HEAD'"
I have an ESP8266 program that used to work but is now failing to compile with this error:

```
C:\...\Arduino\libraries\WiFiManager/WiFiManager.h:25:24: note: in expansion of macro 'PROGMEM'

 const char HTTP_HEAD[] PROGMEM            = "<!DOCTYPE html><html lang=\"en\"><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\"/><title>{v}</title>";

                        ^

In file included from C:\...\MyEsp.ino:14:0:

C:\...AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.6.3\libraries\ESP8266WebServer\src/ESP8266WebServer.h:33:39: error: previous declaration of 'HTTPMethod HTTP_HEAD'

 enum HTTPMethod { HTTP_ANY, HTTP_GET, HTTP_HEAD, HTTP_POST, HTTP_PUT, HTTP_PATCH, HTTP_DELETE, HTTP_OPTIONS };
                                   ^

```

I don't recall changing anything, except maybe updating some libraries. Any ideas what could be causing this? Here are my includes from the ESP8266 program:

```
#include <Arduino.h>

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>

#include <DNSServer.h>            //Local DNS Server used for redirecting all requests to the configuration portal
#include <ESP8266WebServer.h>     //Local WebServer used to serve the configuration portal
#include <WiFiManager.h>          //https://github.com/tzapu/WiFiManager WiFi Configuration Magic

#define SERIAL_BUFFER_SIZE 256

```

# Answer
You need a newer version of the WiFiManager.h library. This issue was fixed August last year.
> 0 votes

---
Tags: esp8266, library, compilation-errors, progmem
---


# Question
Title: How to stop program while Servo is rotating
If I code like this:

```
motor.write(0);
Serial.println("Before");
motor.write(180);
Serial.println("After");

```

Both "Before" and "After" is instantly printed, while the motor is still rotating.
I want "After" or whatever statement to be executed AFTER the motor reaches 180 degree.
How can I implement this? Is it possible to read Servo's statement?

Btw, I don't want to put delay after write(), so other than that strategy.

# Answer
> How can I implement this? Is it possible to read Servo's statement?

No, it is not possible. When you do a `servo.write()` it just changes the PWM duty cycle. It's then up to the servo to use that to set its position. The Arduino has no concept at all of the *current* position of the servo.

> Btw, I don't want to put delay after write(), so other than that strategy.

The only other way, besides delaying or otherwise using `millis()` to wait for a predefined period after your `write` would be to implement some form of feedback between the shaft of the servo and the Arduino. Maybe a potentiometer, or rotary encoder would do the job.
> 1 votes

# Answer
It's not possible with the servo alone, but you could add feedback. Some options:

* An encoder (may be expensive or not available for your servo) will tell you the position.
* You could also make your own encoder by connecting a potentiometer to the axis. The resistance of the pot will be related to the position of the servo.
* if you don't need to be exact something simple like a switch at the limit you want to reach.
* If it doesn't have to be exactly when the position is reached, you could measure the average time it takes (under load) to move from the minimum angle to the maximum angle. This will be the longest it ever takes to move. Then in your code wait 150% of that time before proceeding (to give a bit of a buffer "just in case").

As Majenko said, if you don't want to use a delay, use millis() or micros() to track the current and previous times a line in the loop executed; if the difference is larger than the required delay, the time has elapsed and you can proceed with the rest of the loop. This way you can track time without having to "block" the rest of the loop while you wait.
> 1 votes

---
Tags: arduino-uno, motor, servo
---


# Question
Title: Is it possible to run a monochrome LCD without driver circuit with an Arduino Uno?
I have an old monochrome LCD panel that I removed from a calculator. The LCD panel has no standard input pins, because it's directly connected to a driver on which the calculator software runs.

Is it possible to run the LCD without the calculator software? All pins of the LCD would be available (marked in blue). The pins marked in red were connected to the keyboard of the calculator.

# Answer
> 1 votes
In theory, maybe yes, in practice it will be hard job.

Some things you need to find out:

* Find the exact model of the LCD
* Find its datasheet
* I see an enormous amount of pins (especially the blue ones), so you need (a lot of) multiplexers or shift registers.
* Speed of the Arduino, is it enough to drive this LCD?
* You have to solder this to test.

# Answer
> 1 votes
Normally such LCDs are custom designed, mass produced displays especially for this calculator product. Thus it is very unlikely to find a datasheet or even a meaningful part number for it.

Most likely the pins on the LCD are directly connected to the corresponding fields on the LCD. In an LCD you have liquid crystals between two electrodes, which change their orientation, when a voltage is applied to the electrodes, which changes the light absorption of the layer. You need to apply the correct voltage to a pair of pins to activate their field. Most likely all of the fields or a few groups of them have a common electrode (which would be 1 pin). Without any documentation you are bound to experiment with the display, until you have found the correct voltages and pin arrangements. You might break the display in the process (for example through excess voltage).

I haven't done this myself, but googling gives an interesting result:

* This project, where they hacked the LCD of a cheap calculator for a waveform generator (though the display seems to be way less complex than yours) They seem to use 1.5V as voltage, so this might be a good starting point.

Your display has many pins. Depending on the Arduino model, that you use, you will fast run out of pins to use. You can try arranging the pins into a matrix, which would mean multiplexing the fields (turning them on and off fast one after another). Or you can buy additional parts to extent your pin count, for example shift registers.

---

As jsotola wrote in the comments (and as several forum threads on web web state), you should not put a constant voltage onto the display, since this will damage it. (I guess the liquid crystals will degrade fast because of their polarity, which make the work in the first place). Instead you have to place an alternating voltage at the pins, which changes it's polarity. The net voltage (The integrated voltage over time) must be zero. Thus you need to alternate the applied voltage. If you provide a span of 1.5V, you need to change between +0.75V and -0.75V.

As the display shouldn't need too much current and the voltage requirement is relative to the LCD ground, you might get way by setting the LCDs ground with a voltage divider to 2.5V and then operating around that. Though I'm not sure about that.

Otherwise you might need to actually change the polarity. This would also just need 1 extra digital output pin as the ground pin. One polarity would be the LCDs ground pin to Arduino's ground (outputting LOW at the digital pin) and the other pins to the needed positive voltage (HIGH divided down over a voltage divider or similar). The other polarity would be LCDs ground pin to the needed positive voltage (HIGH divided down over voltage divider) and the other pins to ground (outputting LOW).

---

As described above, hooking this bare LCD to the Arduino is not done fast and easy. You can try it, if you like to do it. But if you want to get your project (whatever it is) done fast, you should instead buy a LCD with integrated controller, which are mostly ready to use, and for which there are already libraries.

---
Tags: lcd
---


# Question
Title: Arduino SD Card open file modes append / overwrite
Running Arduine IDE `SD DataLogger Example`, my data gets appended to a txt file.

```
File dataFile = SD.open("datalog.txt", FILE_WRITE);
if (dataFile) {
  dataFile.println(dataString);
  dataFile.close();
}

```

Is there an explicit option to open the file in overwrite / append modes?

# Answer
If you look in this library, you see:

```
File SDClass::open(const char *filepath, uint8_t mode) {

    ...

    if ((mode & (O_APPEND | O_WRITE)) == (O_APPEND | O_WRITE)) {

```

So you can use all these mode combinations (e.g. O\_CREATE, O\_APPEND, O\_WRITE).
> 2 votes

# Answer
The Arduino SD library is an Arduino wrapper of old version of SdFat library (put into utility subfolder of the SD library). This SdFat library has constants like O\_READ, O\_WRITE, O\_APPEND.

Arduino wrapper has constants

```
#define FILE_READ O_READ
#define FILE_WRITE (O_READ | O_WRITE | O_CREAT | O_APPEND)

```

You can use the SdFa library constants in the wrapper calls.

```
File dataFile = SD.open("datalog.txt", O_READ | O_WRITE | O_CREAT);

```

**Warning**: not all versions of SD library bundled in different board packages have O\_APPEND in `#define FILE_WRITE`. Even in the Arduino SD library the O\_APPEND was removed some time ago and then the change was reverted, because all dataloger examples used FILE\_WRITE.
> 4 votes

# Answer
You only need to open the file with `FILE_WRITE` and use `file.seek(EOF)` to go to de end of the file. After that you can write whatever you want that will be appended to the end of the file.

```
File outputFile = SD.open(LOG_FILE, FILE_WRITE);
outputFile.seek(EOF);
outputFile.println("Appended to the EOF");

```
> 4 votes

---
Tags: c++, sd-card, sd
---


# Question
Title: cannot connect ESP8266 web server after some time
I am new to ESP8266 and found an example about turning a LED ON/OFF using web interface. It works well but after some time (few minutes) i cannot open the web page (in my case it is http://192.168.100.23 and i made it static IP). It keeps 'waiting for 192.168.100.23'. I can ping the IP. Can someone please help to find what the problem is? Thank you very much!

Below is the code:

```
#include <ESP8266WiFi.h>
#define LED D2
const char* ssid = "myAP";
const char* password = "32133213";
unsigned char status_led=0;
WiFiServer server(80);

void setup() {
  Serial.begin(115200);
  pinMode(LED, OUTPUT);
  /*WiFi.persistent( false );
  WiFi.setAutoConnect(true);
  WiFi.mode(WIFI_STA);*/
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  server.begin();
  Serial.println("Server started");
  Serial.println(WiFi.localIP());
}

void loop() {
  WiFiClient client = server.available();
  if (!client) {
    return;
  }

  Serial.println("new client");
  while(!client.available())
  {
    delay(1);
  }
  String req = client.readStringUntil('\r');
  Serial.println(req);
  client.flush();
  if (req.indexOf("/ledoff") != -1)
  {
    status_led=0;
    digitalWrite(LED,LOW);
    Serial.println("LED OFF");
  }
  else if(req.indexOf("/ledon") != -1)
  {
    status_led=1;
    digitalWrite(LED,HIGH);
    Serial.println("LED ON");
  }
  String web = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";
  web += "<html>\r\n";
  web += "<body>\r\n";
  web += "<h1>LED Status</h1>\r\n";
  web += "<p>\r\n";
  if(status_led==1)
      web += "LED On\r\n";
  else
      web += "LED Off\r\n";
  web += "</p>\r\n";
  web += "</p>\r\n";
  web += "<a href=\"/ledon\">\r\n";
  web += "<button>LED On</button >\r\n";
  web += "</a>\r\n";
  web += "</p>\r\n";

  web += "<a href=\"/ledoff\">\r\n";
  web += "<button>LED Off</button >\r\n";
  web += "</a>\r\n";

  web += "</body>\r\n";
  web += "</html>\r\n";

  client.print(web);
}

```

# Answer
I added WiFi.setSleepMode(WIFI\_NONE\_SLEEP); but it does not help. I found another script that is working well so far (after 1 day). I am new so i do not know what problem is but i think it needs to free memory and close connection. Below is the new code for those who get the same problem!

```
// Load Wi-Fi library
#include <ESP8266WiFi.h>
#define LED D2
// Replace with your network credentials
const char* ssid     = "myAP";
const char* password = "32133213";
// Set web server port number to 80
WiFiServer server(80);
// Variable to store the HTTP request
String header;
// Auxiliar variables to store the current output state
String outputState = "off";
// Assign output variables to GPIO pins

// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0;
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;
void setup() {
  Serial.begin(115200);
  // Initialize the output variables as outputs
  pinMode(LED, OUTPUT);
  // Set outputs to LOW
  digitalWrite(LED, LOW);

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
}
void loop(){
  WiFiClient client = server.available();   // Listen for incoming clients
  if (client) {                             // If a new client connects,
    Serial.println("New Client.");          // print a message out in the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    currentTime = millis();
    previousTime = currentTime;
    while (client.connected() && currentTime - previousTime <= timeoutTime) { // loop while the client's connected
      currentTime = millis();
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        header += c;
        if (c == '\n') {                    // if the byte is a newline character
          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println("Connection: close");
            client.println();

            // turns the GPIOs on and off
            if (header.indexOf("GET /on") >= 0) {
              Serial.println("light on");
              outputState = "on";
              digitalWrite(LED, HIGH);
            } else if (header.indexOf("GET /off") >= 0) {
              Serial.println("light off");
              outputState = "off";
              digitalWrite(LED, LOW);
            }

            // Display the HTML web page
            client.println("<!DOCTYPE html><html>");
            client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
            client.println("<link rel=\"icon\" href=\"data:,\">");
            // CSS to style the on/off buttons
            // Feel free to change the background-color and font-size attributes to fit your preferences
            client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
            client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
            client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
            client.println(".button2 {background-color: #77878A;}</style></head>");

            // Web Page Heading
            client.println("<body><h1>ESP8266 Web Server</h1>");

            // Display current state, and ON/OFF buttons for GPIO 5
            client.println("<p>State " + outputState + "</p>");
            // If the output5State is off, it displays the ON button
            if (outputState=="off") {
              client.println("<p><a href=\"/on\"><button class=\"button button2\">TURN ON</button></a></p>");
            } else {
              client.println("<p><a href=\"/off\"><button class=\"button\">TURN OFF</button></a></p>");
            }

            client.println("</body></html>");

            // The HTTP response ends with another blank line
            client.println();
            // Break out of the while loop
            break;
          } else { // if you got a newline, then clear currentLine
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }
      }
    }
    // Clear the header variable
    header = "";
    // Close the connection
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

```
> 1 votes

# Answer
The esp8266 enters modem sleep in STA mode without WiFi traffic. You can turn off the sleep mode with WiFi.setSleepMode. The possible parameters are WIFI\_NONE\_SLEEP, WIFI\_LIGHT\_SLEEP or WIFI\_MODEM\_SLEEP.

After some longer time the servers on esp8266 with arduino core usually get inaccessible even it the esp8266 connects as client to other servers or still sends UDP messages. It is a known issue with some possible workaround documented.
> 1 votes

---
Tags: esp8266
---


# Question
Title: Fixing serial communication , condition for serial data available checks out even after reading all the data sent
I have been working on monitoring an aquaculture , where I log the environment variables (temp. , humidity, gas sensor data) to firebase and control feeding mechanism via an app(where data can also be viewed)

The setup has all sensors connected to Uno Board, which transmits data serially to esp8266.

Pin 2 of Uno is connected to Pin 2 of esp8266

Pin 3 of Uno is connected to Pin 3 of esp8266

Right now the boards are being powered by USB ports in the computer.

My understanding is that, once all the data are read, the `Serial.available()` becomes 0 and the `while()` loop will not execute again, but it worked again and reads data.. to avoid sending same data over and over again(to FireBase), I used Boolean values to take care of.

The data should be available only once per 30 seconds, so after a string is fully read, I was able to see that pgm entered into `while()` loop and reads one/two values

```

// uploaded to esp8266 Lolin(wemos) d1 r2 and mini

#include<ESP8266WiFi.h>
#include<FirebaseArduino.h>
#include<SoftwareSerial.h>

// Set these to run example.
#define FIREBASE_HOST "@#$%^.firebaseio.com"
#define FIREBASE_AUTH "********"

#define WIFI_SSID "###########"
#define WIFI_PASSWORD "&^*^*%$#"

SoftwareSerial esp(D2,D3);

float temp_fb;
float gas_fb;
float hum_fb;

unsigned long last_chk = 0 ;
unsigned long time_elapsed;

bool t_ar , h_ar , g_ar = false ; //chk arrival of all data b4 sending

char r;
String cu_st = "c";

int found = 1;

void setup() {
  Serial.begin(9600);
  esp.begin(4800);

  // connect to wifi.
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("connecting");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

  Serial.println("connected: ");
  Serial.println(WiFi.localIP());

  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
}

void loop()
{
  time_elapsed = millis();
  if(time_elapsed - last_chk > 5000){
    Serial.print("checking for data from arduino...\tfeeder state\t");
    Serial.println(cu_st);
    last_chk = time_elapsed;
    time_elapsed = millis();
  }
   while(esp.available()>0)
  {
     if(found == 1)
     {
      Serial.println("................found data...............") ;
      found = 0;
     }
     r = esp.read();
     //Serial.print("first char\t"); just for debugging purposes
     //Serial.println(r);
     switch(r)
     {

      case 't':
      {
        Serial.println("got t...") ;
        t_ar = true;
        temp_fb = esp.readStringUntil(',').toFloat();
        break ;
      }

      case 'g':
      {
          Serial.println("got g...") ;
          g_ar = true;

          gas_fb = esp.readStringUntil(',').toFloat();;
          break ;
      }

      case 'h':
      {
        Serial.println("got h...") ;
        h_ar = true;

        hum_fb = esp.readStringUntil(',').toFloat();
        break ;
      }

      case 'c':
      {
        cu_st = "c" ;
        Firebase.setString("feeder" ,"c");
      }
      default: break;

     }

  }

  found = 1 ;

  if(g_ar and t_ar and h_ar)
  {
     //writing to firebase
     Serial.println("got the set.. to fb now");
     Firebase.setFloat("GAS SENSORinst" ,gas_fb);
     Firebase.setFloat("HUMIDITY SENSORinst" ,hum_fb);
     Firebase.setFloat("TEMP SENSORinst" ,temp_fb);
     Firebase.pushFloat("GAS SENSOR" ,gas_fb);
     Firebase.pushFloat("HUMIDITY SENSOR" ,hum_fb);
     Firebase.pushFloat("TEMP SENSOR" ,temp_fb);
  }

  t_ar , h_ar , g_ar = false ;

  cu_st = Firebase.getString("feeder");

   if (cu_st == "o")
   {
    Serial.println("\t\trecd req to feed");
    esp.print('o');
   }

}

```

The arduino sends data every 30 Sec. The servo connected to Arduino was having jitters every time the data was being sent(apparently due to not enough power to supply for all devices connected and both Softwareserial and servo having same timer) so I have added a LED just for trial
For some reason, `if` block in `close_feed()` is always executed.

```
//uploaded to arduino Uno
#include <SoftwareSerial.h>
#include<TimerOne.h>

SoftwareSerial ArduinoUno(3,2);
#include<Servo.h>
#include "DHT.h"

//Servo feeder;

int send_rate = 30000; //every 30 secs send data
unsigned long last_time_stamp = 0;
unsigned long cur_time = 0;

String sen_vals = "";
#define led 13
int feeding = 0 ;
const int gas = 0;//gas sensor o/p
#define DHTPIN 8
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(9600);
  ArduinoUno.begin(4800);
  pinMode(led,OUTPUT);
  //feeder.attach(11);
  //feeder.write(85);
  Timer1.initialize(10000); //every 10 millisecond check for arrival of feed command
  Timer1.attachInterrupt(feed_cmd); //chk feed_cmd for every 10 mS
   dht.begin();

  pinMode (3,INPUT); //recieve from esp
  pinMode (2,OUTPUT); //transmit to esp

}

void feed_cmd()
{
  while(ArduinoUno.available())
  {
    char valve = ArduinoUno.read();

    if(valve=='o')
    {
       digitalWrite(led, HIGH);
       //feeder.write(0);
       feeding = 1;
       ArduinoUno.print("c");
       valve = "";
    }
  }
}

void close_feed()
{
  if(feeding == 1)
  {

    feeding = 0;
    delay(5000);
    //feeder.write(85);
    digitalWrite(led,LOW);
    Serial.println("I am closing feeder");

   }
}

void send_data()
{
  float h = dht.readHumidity();
  float t = dht.readTemperature();
  String ht = String('h')+String(h)+String(',')+String('t')+String(t)+String(',');

  float raw_v = analogRead(gas);
  String g = String('g')+String(raw_v)+String(',');

  sen_vals = ht + g ;

  Serial.println(sen_vals);
  ArduinoUno.print(sen_vals);
}

void loop()
{
  // put your main code here, to run repeatedly:

  close_feed();
  cur_time = millis();
  if(cur_time > last_time_stamp + send_rate)
  {

    last_time_stamp = cur_time;
    send_data();

  }

}

```

Some how some blocks are executed even when they shouldn't be.. I wrote the code, but I cant figure out where the code fails, used a lot of serial prints to see how the flow of the code, but it only confused me further!

If somebody can take a look at this code and point out the flaws..I'll greatly appreciate it.

EDIT: I have changed he code as suggested below, but now the Arduino is receiving random things as input(pic attached) I have added the changed code too(I know this post is getting bigger and bigger, but i thought making changes to already existing code here won't be good for readability )

```
void setup() {
  Serial.begin(9600);
  esp.begin(4800);

  // connect to wifi.
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("connecting");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }

  Serial.println("connected: ");
  Serial.println(WiFi.localIP());

  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
}

void loop()
{
  time_elapsed = millis();
  if(time_elapsed - last_chk > 5000){
    Serial.print("checking for data from arduino...\tfeeder state\t");
    Serial.println(cu_st);
    last_chk = time_elapsed;
    time_elapsed = millis();
  }
   while(esp.available()>0)
  {
     if(found == 1)
     {
      Serial.println("................found data...............") ;
      found = 0;
     }
     r = esp.read();
     //Serial.print("first char\t");
     //Serial.println(r);
     switch(r)
     {

      case 't':
      {
        Serial.println("got t...") ;
        t_ar = true;
        temp_fb = esp.parseFloat();
        break ;
      }

      case 'g':
      {
          Serial.println("got g...") ;
          g_ar = true;

          gas_fb = esp.parseFloat();;
          break ;
      }

      case 'h':
      {
        Serial.println("got h...") ;
        h_ar = true;
        hum_fb = esp.parseFloat();
        break ;
      }
      default: break;

     }

  }

  found = 1 ;

  if(g_ar and t_ar and h_ar)
  {
     //writing to firebase
     Serial.println("got the set.. to fb now");
     Firebase.setFloat("GAS SENSORinst" ,gas_fb);
     Firebase.setFloat("HUMIDITY SENSORinst" ,hum_fb);
     Firebase.setFloat("TEMP SENSORinst" ,temp_fb);
     Firebase.pushFloat("GAS SENSOR" ,gas_fb);
     Firebase.pushFloat("HUMIDITY SENSOR" ,hum_fb);
     Firebase.pushFloat("TEMP SENSOR" ,temp_fb);
  }

  t_ar , h_ar , g_ar = false ;
  if (cu_st == "c")
  {
    sent = 0;
  }
  cu_st = Firebase.getString("feeder");
   if (cu_st == "o")
   {
    Serial.println("\t\trecd req to feed");
    if(sent == 0)
    {
      esp.print('o');
      sent =1;
      cu_st = "c";
      Serial.println("setting feeder to close in firebase");
      Firebase.setString("feeder" ,"c");

   }

  }
}

```

```
#include <SoftwareSerial.h>

SoftwareSerial ArduinoUno(3,2);
#include<Servo.h>
#include "DHT.h"

//Servo feeder;

int send_rate = 30000; //every 30 secs send data
unsigned long last_time_stamp = 0;
unsigned long cur_time = 0;
unsigned long close_time = 0;
unsigned long open_time = 0;
#define led 13
int feeder = 0 ;
const int gas = 0;//gas sensor o/p
#define DHTPIN 8
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

void setup()
{
  // put your setup code here, to run once:
  Serial.begin(9600);
  ArduinoUno.begin(4800);
  pinMode(led,OUTPUT);
  //feeder.attach(11);
  //feeder.write(85); //closing position
   dht.begin();

  pinMode (3,INPUT); //recieve from esp
  pinMode (2,OUTPUT); //transmit to esp

}

void feed_cmd()
{
  while(ArduinoUno.available())
  {
    char valve = ArduinoUno.read();
    Serial.print("feeder cmd recd ");
    Serial.println(valve);
    if(valve=='o')
    {
       digitalWrite(led, HIGH);
       //feeder.write(0); //open position
       open_time = millis();
       feeder = 1 ;
       Serial.println("I am opening feeder");
    }
  }
}

void close_feed()
{

  if(feeder == 1)
  {
   close_time = millis();
   if(close_time - open_time > 5000)
  {
    feeder = 0;
    digitalWrite(led , LOW);
    Serial.println("I am closing feeder") ;
  }
  }
}

void send_data()
{
  float h = dht.readHumidity();

  float t = dht.readTemperature();

  float raw_v = analogRead(gas);

  ArduinoUno.print("h");
  ArduinoUno.print(h);
  ArduinoUno.print(",t");
  ArduinoUno.print(t);
  ArduinoUno.print(",g");
  ArduinoUno.print(raw_v);
  ArduinoUno.print(",\n");
}

void loop()
{
  // put your main code here, to run repeatedly:

  feed_cmd();
  close_feed();
  cur_time = millis();
  if(cur_time - last_time_stamp > send_rate)
  {

    last_time_stamp = cur_time;
    send_data();

  }

}

```

Thanks for your time!!!

# Answer
I cannot really narrow down the source of your observed problems, since the problem descriptions are not clear enough. But there are some obvious problems/potential for making it better in your code.

In the Uno Code:

* It is totally unnecessary to use a timer interrupt for reading the SoftwareSerial interface. Instead you should write your `loop()` function non-blocking, meaning, that it does not wait for something to happen, but it will execute other code in the meantime (so no delay in `close_feed()`). Then you can just read the serial data in the loop function. You are saving a timer this way.
* In `send_data()` you are using the `String` class to concat a string of human readable data together and then send it. Using the `String` class in that way is evil, since on every concat operation it will allocate a new buffer for the string, deleting the old one. That makes Swiss cheese out of your heap memory (called heap fragmentation). That can lead to instability. Look at Majenko's blog entry about the Evils of Arduino Strings for more information. Instead of concatting you should simply print the information one after another:

```
Serial.print("h");
Serial.print(h);
Serial.print(",t");
Serial.print(t);

```

and so forth.
* Your handling of the `millis()` function should be different. It will roll over after 52 days. To prevent, that your code misfunctions at that time, you need to always take the time difference:

```
if(cur_time - last_time_stamp > send_rate)

```

instead of

```
if(cur_time > last_time_stamp + send_rate)

```

In the ESP Code:

* Your SoftwareSerial read code seems weird to me, but I think it should work. I would introduce a message protocol to the data stream, meaning to mark the end of a full message (a message containing one frame with all relevant data) with a special delimiter character, for example a newline character `\n`. Then you can read the message until this character into a buffer and then process the message as a whole.

---

That's about what I can say to this point. If you need a more focused answer, you have you describe further and more detailed the symptoms (what behavior you are seeing and what you expected).
> 1 votes

---
Tags: arduino-uno, serial, esp8266, softwareserial, iot
---


# Question
Title: displaying a 3 digit clock time on a 4 digit 7 segment display
I purchased one of these 4 digit 7 segment displays using a TM1637.

I installed the TM1637 display library from the libraries manager and included it:

`(#include <TM1637Display.h>)`.

I am trying to display the time, and I would like, preferably, to display 3 digit times with a colon, but without the leading zero.

I found this great reference online for using the library., and saw the usage for numbers with colons:

`showNumberDecEx(number, dots, leading_zeros, length, position)`

according to the guide, to have the colon in the center, you would pass `0b01000000` as the `dots` parameter.

And I figured that if I then want to display, for example, the time `1:36`, then my `number` parameter would be 136, my `leading_zeros` parameter would be `0` (false), my length would be `3` for a 3 digit number, and my position would by `1` to start the number in the zero-indexed second position:

`display.showNumberDecEx(136, 0b01000000, false, 3, 1); //displays 5136`

But this displayed `5136` with no colon.

I tried a number of other things, including:

`display.showNumberDecEx(136, 0b01000000, true, 3, 0); //displays 13:66` `display.showNumberDecEx(136, 0b01000000, false, 3, 0); //displays 13:6A`

I finally found code from this site, which works to display the time (albeit with a leading zero), but I don't fully understand it:

`display.showNumberDecEx(1*100+36, 0x80 >> 1, 1, 4, 0);`

I get that 1\*100+36 represents number of hours plus minutes, but I don't get the 0x80 \>\> 1 bit. I'm assuming the rest of it is just saying make it a 4 digit number and add a leading zero.

Can anyone possibly: * help me understand the above working code * tell me an easier way to construct a time so that I can ideally just pass a 3 or 4 digit number and have it automatically render out a clock time with separating colon * tell me why my previous attempts were incorrect

# Answer
I tested your first code line and it outputs a right aligned 136 without colon at my display. (Said I have only a colon at the middle and no decimal points)

The 5 at the fist digit (and also the A at your third code line) must have been set somewhere beforehand. The function does not change the unused digit, so it will stay whatever you set it to beforehand (Even from before the last reset of the Arduino. The display doesn't reset with the Arduino). You can set the segments for that digit to zero (or set all segments to zero, to clear the complete display) before you show the decimal number.

About the colon: Here it is important on which position you start the printing of the number. The colon/decimal point bitmask, that you provide the function with, is seen from the starting position, that you provide. The middle colon of a 4 digit display is wired to the second digit. When providing `1` as the starting position, you start with the second digit. Thus the colon bitmask must set the most significant ("first") bit, to enable the middle colon, since it belongs to the first digit, that is processed by the function. Meaning:

```
position = 0 and bitmask = 0b10000000 --> colon/decimal point at first digit on
position = 0 and bitmask = 0b01000000 --> colon/decimal point at second digit on
position = 0 and bitmask = 0b00100000 --> colon/decimal point at third digit on
position = 1 and bitmask = 0b10000000 --> colon/decimal point at second digit on
position = 1 and bitmask = 0b01000000 --> colon/decimal point at third digit on
position = 2 and bitmask = 0b10000000 --> colon/decimal point at third digit on
position = 2 and bitmask = 0b01000000 --> colon/decimal point at fourth digit on

```

The `0x80 >> 1` is just a different representation of your binary number. `0x80` is the hexadecimal form of the binary `0b10000000`. The `>>` operator shifts the byte to the right, here by one digit. Thus:

```
0x80 >> 1 = 0b10000000 >> 1 = 0x40 = 0b01000000

```

So the code, that you found, enables the colon/decimal point at the second digit.

> tell me an easier way to construct a time

Easier it relative. I used such a display in a project to display a time and used two `showNumberDecEx()` calls; one for the minutes and one for the seconds:

```
display.showNumberDecEx(seconds, 0x00, true, 2, 2);
display.showNumberDecEx(minutes, 0x40, true, 2, 0);

```

Having directly minutes and seconds may make it easier for you. About the no-leading-zeros: Since the library always prints left to right, you need to handle that by yourself. But that is rather easy. One if statement to check, if the minutes are greater than 9 or not. Depending on that you set the position to 0 or 1.

```
display.showNumberDecEx(seconds, 0x00, true, 2, 2);
if(minutes > 9){
    display.showNumberDecEx(minutes, 0x40, false, 2, 0);
} else {
    display.showNumberDecEx(minutes, 0x80, false, 1, 1);
}

```

You could put that into a function, so that you don't have to write this code multiple times.

Note: For my last code snippet to work, you should first clear the display (or optionally only the first digit), so that no number from before will be displayed there.
> 3 votes

# Answer
Always start by reading the docs. The README of the TM1637 display library gives a short summary of the available functions, then states “Please refer to TM1637Display.h for more information.” It would thus seem the authoritative documentation is the header file itself, which is indeed rich ins structured comments. According to it, the signature of `showNumberDecEx()` is

```
void showNumberDecEx(int num,
                     uint8_t dots = 0,
                     bool leading_zero = false,
                     uint8_t length = 4,
                     uint8_t pos = 0);

```

where the parameters have the following meanings (emphasis mine):

* `num`: the number to be shown
* `dots`: dot/colon enable \[...\]
* `leading_zero`: when true, leading zeros are displayed, otherwise **unnecessary digits are blank**
* `length`: **the number of digits to set**
* `pos`: the position of the most significant digit (0 - leftmost, 3 - rightmost)

The `length` and `pos` parameters control which digits are set. It is important to note that any digits that are not set *are left as is*. Note also that, if you are setting more digits than needed to display the number, the leftmost digits are either zeros *or blank*, depending on the value of `leading_zero`. And that is exactly what you want: you want the leftmost digit to be blank.

Here are some examples of what various calls display:

```
display.showNumberDecEx(136, 0x40, true,  3, 1)  →  "X1:36"
display.showNumberDecEx(136, 0x40, false, 3, 1)  →  "X1:36"
display.showNumberDecEx(136, 0x40, true,  3, 0)  →  "13:6X"
display.showNumberDecEx(136, 0x40, false, 3, 0)  →  "13:6X"
display.showNumberDecEx(136, 0x40, true,  4, 0)  →  "01:36"
display.showNumberDecEx(136, 0x40, false, 4, 0)  →  " 1:36"

```

In the examples above, “X” means “whatever was previously left there”, as the corresponding digit is not updated by the call. The last example is the one you want. Incidentally, the last three parameters of this example have their default values. You can thus achieve this simply with:

```
display.showNumberDecEx(136, 0x40);

```

You can also follow chrisl's advice and display the hours and minutes separately:

```
int hours = 1;
int minutes = 36;
display.showNumberDecEx(hours, 0x40, false, 2, 0);
display.showNumberDecEx(minutes,  0, true,  2, 2);

```

No need to separately handle the case where `hours` is larger than 9.
> 1 votes

---
Tags: library, rtc, 7-segment
---


# Question
Title: Can we burn Arduino bootloader into any microcontroller chip?
I am new to this Arduino community I noticed on youtube that while the prototype is complete people purchase new ATmega328p chips and flash bootloaders into them using in-system-programmers so that the chip could actually understand and interpret the instructions that are written in the high-level language if I am right(No I was wrong, it's actually the compiler that sits on Arduino). so I thought what if we could burn the atmega328p bootloader into any other microcontroller. So that we could program it in Arduino programming language(C/C++). Is this possible? sorry if I am dumb, but I wanted to know. And can anyone tell me whether could we use ATmega328p for production purposes(consumer electronics)? Thanks in advance.

# Answer
The answer needs to have multiple parts:

**Yes, in principle you can create a bootloader for any microcontroller, which acts like the Arduino's.**

Please be aware that there are different bootloaders, not just the common STK500 compatible one. Each of these bootloaders implements a certain protocol to transfer the binary code to the target system.

Additionally, some protocols also include commands to restart the microcontroller, to set configuration registers, and maybe more.

You need to read the bootloader's documentation to become familiar with its capabilities.

But it is your decision whether such a bootloader on a non-AVR system or an non-Arduino-AVR system is good for you.

**No, the bootloader does *not* enable the microcontroller to "understand" the high-level language.**

The standard Arduino IDE uses the specific compiler for the target microcontroller to translate the C++ source code to machine language. The resulting binary commonly runs on this target microcontroller only.

The bootloader just implements the protocol. In general, it is completely unaware of the meaning of the transferred data.

Microcontrollers in general use different processors with possibly different machine languages, contain different kinds of memory of different sizes, include different sets of different peripherals. But you know this for sure. You need to write and compile your source code for the specific part you're targeting.

**Yes, you can use ATmega328P for a consumer product, as Michel already said.**

You need to take the common measures that you take with *any* part of your product, though.
> 11 votes

# Answer
You cannot just load a sketch into any microcontroller, because every microcontroller has different memory layout, peripherals, ways of uploading, FLASH size etc.

You can use the atMega (or any microcontroller) for production purposes though. Of course each MCU type has operation conditions (like min/max temperature), so in e.g. automotive or military environments not all MCUs are allowed to be used, but for consumer electronics, afaik all MCUs can be used (meaning they will pass by themselves the needed certifications, which may not be true for components added and the circuit/enclosure resulting out of it).
> 3 votes

---
Tags: programming, atmega328, bootloader, avrdude, icsp
---