# Question
Title: Adafruit RTC begin() not returning false
I am programming my arduino with the capability to keep time with the DS3231 from Adafruit. I do not have the module yet, but am trying to figure out the rest of the build without it.

However, it seems like the way to determine RTC is working does not work, as it returns true, even without the module.

Example code from the Adafruit RTC library for using this module:

```
// Date and time functions using a DS3231 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h"

RTC_DS3231 rtc;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

void setup () {

#ifndef ESP8266
  while (!Serial); // for Leonardo/Micro/Zero
#endif

  Serial.begin(9600);

  delay(3000); // wait for console opening

  if (! rtc.begin()) { // part that fails. begin() returns true when should return false
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
}
....

```

# Answer
If you look at the library source code it will be clear why `begin()` returns true.

From https://github.com/adafruit/RTClib/blob/1.2.0/RTClib.cpp#L434-L437:

```
boolean RTC_DS3231::begin(void) {
  Wire.begin();
  return true;
}

```

I suppose they plan to eventually make the return value of `begin()` mean something but for now it does not.
> 1 votes

# Answer
This should not happen anymore.

Actually, if you have a look at the last version of the source code on GitHub (1.13.0), you will see that now the developers implemented also a case in which the method returns false.

from https://github.com/adafruit/RTClib/blob/1.13.0/RTClib.cpp#L1537-L1543 :

```
boolean RTC_DS3231::begin(void) {
  Wire.begin();
  Wire.beginTransmission(DS3231_ADDRESS);
  if (Wire.endTransmission() == 0)
    return true;
  return false;
}

```
> 2 votes

---
Tags: arduino-uno, adafruit, rtc
---


title: Detailed analyse of memory usage

text:
# Question
Title: Detailed analyse of memory usage
When compiling a sketch, after linking, the build outputs a kind of forecast on RAM usage, e.g.:

> Minimum Memory Usage: 1456 bytes (71% of a 2048 byte maximum)

Is it possible to somehow get a breakdown or itemization of these 1456 bytes and details on exactly where in my code, or in included libraries, they are used?

# Answer
> 10 votes
Since you seem interested about RAM, rather than flash usage, I suggest you look at the symbol table of your compiled program, which will be more telling than the disassembly. On my Linux system, I usually do the following:

```
avr-nm -Crtd --size-sort the_program.elf | grep -i ' [dbv] '

```

`avr-nm` is the utility for displaying the symbol table. It is normally packaged with the Arduino IDE. It is invoked here with the following options:

* `--size-sort` is quite explicit
* `-C` means “demangle the C++ names”
* `-r` means “reverse sort”, i.e. sort from largest to smallest
* `-td` means “display numbers in decimal rather than hexadecimal”

This will output the list of all symbols that have a size, in three columns: size, type and name. You are only interested in the symbols that consume RAM, i.e. those of type `b` (BSS, or uninitialized data), `d` (initialized data) and `v` (vtable), either in upper or lower case. The `grep` command is a standard Unix utility which is used here to extract only the relevant lines from the output of `avr-nm`.

Example output for a small program:

```
00000068 B tx_buffer
00000068 B rx_buffer
00000034 B Serial
00000016 V vtable for HardwareSerial
00000004 B timer0_overflow_count
00000004 B timer0_millis
00000002 b loop::last_print
00000001 b timer0_fract

```

The first 4 entries come from the `Serial` object. The 3 entries starting with `timer0_` are used by the Arduino timekeeping functions (`millis()`, `micros()` and `delay()`). The entry named `loop::last_print` is a static local variable I declared in `loop()`.

# Answer
> 2 votes
Looking at an assembly listing of your code is the most direct method for finding out details of space allocation. On my Ubuntu Linux system, I use a shell script (that is, a file containing shell commands) like the following to produce an assembly listing of the most-recently-compiled `.ino` file, which must be in the working directory when the script executes:

```
#!/bin/sh
# Look for .ino in current directory, and find recent /tmp/build...
item=*.ino
[ -z "$item" ] && echo ino file not found && exit
BDIR=/tmp/$(ls -t /tmp | egrep -m1 build.*tmp)
BASE=$(basename $item .ino)
avr-objdump -S -I$PWD $BDIR/$BASE.cpp.elf > $BASE.ino.asm

```

All the stuff before the `avr-objdump` line allows the script to find out the name of the current `.ino` file and the name of the `/tmp/` subdirectory where the `.ino`'s `.elf` file is found.

You can also use `avr-objdump` to get a more concise size listing, as follows, where `$BDIR` and `$BASE` are as in the script above and represent the build directory in `/tmp/`, and the basename of the `.ino` file.

```
avr-objdump -C -d $BDIR/$BASE.cpp.o| egrep -C2 '^Disassembly' | egrep -v '^--|^$|^Disassembly' | less

```

This will produce a list with two-line entries like the following, in which each line beginning with 00000000 is a subroutine name, and the next line shows the last line of its compiled code. In this example output, the `setup_PowerDown()` routine has `0xA4` bytes of code, ISR `__vector_13` has `0xC6` bytes, `keepAlive()` has `0x10` bytes, etc.

```
00000000 <setup_PowerDown()>:
  a4:   08 95           ret
00000000 <__vector_13>:
  c6:   18 95           reti
00000000 <keepAlive()>:
  10:   08 95           ret
00000000 <eeWrite1(unsigned char, unsigned char)>:
  3a:   08 95           ret
00000000 <eeWrite2(unsigned char, unsigned char)>:
  18:   0c 94 00 00     jmp     0       ; 0x0 <eeWrite2(unsigned char, unsigned char)>
00000000 <parValidate(unsigned char, unsigned char, unsigned char)>:
  64:   08 95           ret
00000000 <loadSettings()>:
  e0:   08 95           ret
00000000 <applySettings()>:
  84:   08 95           ret

```

Some IDEs provide symbol table information that includes sizes of routines, stack frames, and data. I don't know if that's available via Arduino IDE, AVR-libc, or GNU Binutils. The symbol table provided by `avr-readelf -s` (as in following command) provides quite detailed symbol information that seems quite useless in its raw form.

```
avr-readelf  -s  $BDIR/$BASE.cpp.o

```

The methods described above are somewhat ad hoc, and depend on files left after `avr-gcc` or `avr-g++` run. I don't know of any “official” methods for getting the information you want to see.

# Answer
> 2 votes
You can automatically generate a "map" file every time you compile. This gives you a full breakdown of how everything is linked together by the linker, including the size of each section and other useful debugging information.

A simple modification to platforms.txt in `hardware/arduino/avr` is all that is needed. Find the line starting `compiler.c.elf.flags=` and add to the end of it:

```
 -Wl,-Map,"{build.path}/{build.project_name}.map"

```

If you like you can replace `{build.path}` with a hard-coded path, such as your desktop, and the `.map` with `.txt` to allow it to easily be opened by notepad or whatever you use (assuming Windows, of course).

# Answer
> 1 votes
This was a great question and helped me recently as I'm building quite an extensive Arduino app using a Nano (ATMega328 and 32K of program memory). At one point I was almost out of program memory and I was a bit shocked.
I didn't think the code was that large.

**My Tests and Results**

With the comments I read through the posts on this answer I decided to build a blank app and examine the results as I added libraries etc. Here are my results (*Using Arduino IDE 1.8.13*):

1. blank sketch takes up 444 bytes of program storage space (max is 30720 bytes).
2. Sketch which includes 6 libraries✔ uses up 6218 bytes

`<LiquidCrystal_I2C.h>, <Wire.h>,<ds3231.h>,<SD.h>,<EEPROM.h>,<SoftwareSerial.h>`
3. adding one line `Serial.begin(9600);` uses 6324 bytes **NOTE**: 6324 - 6218 = 106 bytes even though I only added 19 bytes (the characters for that line).
4. Adding on more line `Serial.print("a");` results in 6342 bytes used. That's 18 more bytes (6324 - 6342 = 18) which is the exact number of characters I added with that line (including semicolon).
5. Adding a 2nd line with `Serial.print("a");` results in 6358 (16 bytes)
6. Adding a 3rd line of `Serial.print("a");` results in 6374 (16 additional bytes).

I hope this helps a bit. I'm going back to my app now and removing all the Serial lines I used for debug output. They're just eating up program memory now. Actually, I'll probably even use the conditional compilation (shown in this SO answer) so I can still print when in debug.

Blank sketch means one with only the `void setup() {} void loop() {}` structures and nothing else.

✔ These are the libraries which I am using in my project.

I came back and added these additional lines with the amount of Program Memory used because there was a comment that lines of code do not impact memory at all. Of course they do. At some point all Program Memory is used up and your program will no longer fit into flash. This is what I was having a challenge with as my extensive program (which includes sensors, LCD, sd card, and bluetooth) continues to grow.

---
Tags: memory-usage
---


# Question
Title: 12V 28BYJ-40 motor is not generating enough torque
I am attempting to use a stepper motor to rotate one of my split-flap displays. However despite the thing the motor is rotating weighing probably half a pound, it struggles to do so. It really can rotate the module at all.

**Why is my motor struggling so much?**

My circuit is an Arduino powered by 5V from a wall outlet, connected to a ULN2003 driver that is powered by a 12V wall outlet. The driver is connected to the stepper motor.

This is my code, it uses the Accel stepper library:

```
#include <MultiStepper.h>
#include <AccelStepper.h>
#include <Stepper.h>

AccelStepper stepper2(AccelStepper::FULL4WIRE, 4, 5, 6, 7);

void setup()
{
    Serial.begin(9600);
    pinMode(0, OUTPUT);
    pinMode(1, OUTPUT);
    pinMode(A0, OUTPUT);
    pinMode(A1, OUTPUT);
    pinMode(A2, OUTPUT);
    pinMode(A3, OUTPUT);
    pinMode(A4, OUTPUT);
    pinMode(A5, OUTPUT);

    stepper2.setMaxSpeed(100);
    stepper2.setAcceleration(10);
    stepper2.moveTo(-24000000);

}
void loop()
{
    // Change direction at the limits
    //printletters();

    if (stepper2.distanceToGo() == 0)
        stepper2.moveTo(-stepper2.currentPosition());

    stepper2.run();
}

```

Edit: Here is the schematic, I'm sorry its terrible but I dont know how to make it better

simulate this circuit – Schematic created using CircuitLab

# Answer
The grounds needed to be shared. The driver board ground needed to be connected to the Arduino ground. Otherwise your putting 17V in and only taking 12V out. Thanks to DaveNewton for this answer. I made this change and the torque was immediately fixed!
> 0 votes

---
Tags: power, motor, stepper
---


# Question
Title: connecting a small motor to arduino using a transistor
I want to connect a small motor (water pump) to an arduino, and I am not sure about the circuit.

The pump is small, works with 3.3V, but consumes 0.1A so I decided to use a transistor. The one I have is BF547, an NPN type small transistor. It supports currents up to 100 mA.

I measured the hfe (beta) of the transistor, and it is 370. The Vcc is 3.3V, and the current through the motor is 0.1 A, therefore:

A. the Ib equals to Ic/hfe = 0.1A/370 giving Ib = 0,00027A

B. with the Vb at 3.3V(pin voltage) and Vbe at 0.7 (datasheet) the Rb = (Vb-Vbe)/Ib = 9558 Ohm (10kOhm)

My questions are:

1. Did I calculate the base resistance correctly?
2. Do I need any additional resistor for the collector, next to the pump? Is it possible that more current flows through the collector-emitter?
3. According to the datasheet of BF457 100mA is the max Ic it can take. Should I limit the pump by adding a small (10 Ohm) resistor to it (33 Ohm\[motors resitance\] + 10 Ohm for 3.3 V gives a current of 76 mA)

I am attaching the schematics (linear voltage regulator is there only to stabilise the Vcc provided by an old dc power source I found)

Thanks a lot for any suggestions!

# Answer
> 3 votes
I like your thought process (even though it might not be completely correct), I've seen how little thought were put in for such simple circuit design in the Arduino community, including from some Youtuber celebrity who teaching Arduino and claims to have an EE degree.

BF547 is an RF amplifier transistor, not for switching application, it would be better to use an NPN transistor such as 2N3904 which is designed for switching application and has a Ice of 200mA.

Your resistor value is too high. If your motor is designed to operate at 100mA 3.3v condition, you would want your driver to provide AT LEAST that current. Assuming your are driving the transistor with 5V out from an Arduino, a 1k bias resistor would limited the Ibe to (5 - 0.7Vbe)/1000=4.3mA, take a very conservative DC current gain of 30 (it typically in the range of 30 - 80 for switching transistor, and hfe could be in the range of 100 - 300 when frequency go up, but this will not be the case for Arduino even you drive the motor using PWM), which will capable to deliver Ice of 4.3 x 30 = 129mA. This should meet your Motor requirements.

You would need a protection diode connected between 3.3V and collector with its cathode connect to 3.3V and its anode connect to the collector of the transistor. An 1N4148 (max If=200mA) would be okay for this specific motor, or even better, use any Schottky diode with current and voltage limit higher than your application).

# Answer
> 1 votes
4.6V - 1.2V (2 diode drops of 0.7V) = 3.4V, close enough for the motor if you are using a MOSFET as a driver. You can use a UIS rated MOSFET with a Vgs of less than 4 and it will work perfectly. the transistor will give you an additional voltage drop of about 0.7 Volts and needs a base resistor. If you want to guarantee the motor will not start during reset and setup() add a 10K resistor from the port pin to ground.

---
Tags: motor, transistor
---


# Question
Title: How can i draw an electronic diagram of this?
I need help to draw a diagram of this picture the project include an Arduino nano, dht11 sensor, power module IRF520, 12V power supply and a fan

# Answer
See Rules and guidelines for drawing good schematics on electronics.stackexchange.com.

I'm no expert but perhaps some of what I have found will be of help.

To produce a clear easy-to-read useful schematic it doesn't really matter what tools you use. This website has a reasonable schematic editor so I suggest you could try that to start with.

Other tools I have tried include KiCAD, EasyEDA and Fritzing. KiCAD is maybe a bit hard to start with and Fritzing I find is very troublesome - It's good for the kind of breadboard layout diagram it was originally designed for. I have really enjoyed using EasyEDA. Other notable tools include Eagle. All these are free or have free versions for hobbyists. Beyond that are more capable and sophisticated professional tools.

Drawing a good schematic is an art and taking care of small details makes a big difference to how useful the diagram is.

The main features that I find make schematics for me to read are

* Ground connections at bottom edge of diagram.
* Positive voltage connections at top edge of diagram.
* Left to right flow for signals and power (e.g. battery at left, microprocessor in middle, LEDs, motors etc at right)
* Avoid having wires cross. Adjust the pin positions on an IC symbol to make this possible.
* Label everything clearly but don't let text overlap with anything else.

simulate this circuit – Schematic created using CircuitLab

The way you appear to be powering these modules seems a bit eccentric but this would be how I might draw that as a block-level schematic.
> 1 votes

---
Tags: arduino-nano
---


# Question
Title: Where are the programatic definitions for different processors stored?
I need to modify an existing library that relies on being able to detrmine what board / processor the code is being run on. To do this, it uses definitions such as this for an Arduino Mega:

```
// Arduino Mega
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)

```

I need to update the library for a further 2 boards, namely the Raspberry pi pico (mbed os) and the Robotis OpenCR.

I can't seem t find where the processor name is actually defined. If someone could point me in the right direction, that would be great. Thanks.

Edit: If anyone knows what the equivelent define is for the raspbery pi pico - rp2040, that would be fantastic!

# Answer
They are defined by the compiler itself, and based on the name of the microcontroller passed to the compiler as (for AVR GCC) `-mcpu=<mcu name>`.

You can list the defines for a version of GCC using (for example for AVR gcc):

```
avr-gcc -mmcu=atmega328p -dM -E - < /dev/null

```

Not sure what you'd use on Windows for `/dev/null`. Different target compilers use different flags to define the MCU, and you of course need to know the MCU the board uses to pass to the compiler.

You will have to investigate what relevant flags are passed to the compiler for your desired chips, and you can find those by looking in the platform.txt file for the core associated with the board.
> 2 votes

---
Tags: arduino-ide, raspberrypi, core-libraries, board
---


# Question
Title: Error trying to simulate temperature dynamically
I'm trying to simulate dynamic temperature using a small set of data with ESP32. I've just realized that the relay doesn't change the status if there is some variation of the temperature upper or lower the threshold.

If the temperature starts below the modeled temperature, the relay will turn on but, once it reaches the model's temperature or exceeds it, the status doesn't change, and the system will warm up till the next model.

Am I missing something in my code?

```
#include <OneWire.h>
#include <DallasTemperature.h>
#include <NTPClient.h>
#include <WiFi.h>
#include <WiFiUdp.h>

WiFiUDP ntpUDP;

NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 7200, 60000); //UTC+1 (Europe)

unsigned long current_time;

#define WIFI_AP "xxxxx"
#define WIFI_PASSWORD "xxxxx"
//WiFi SETUP
WiFiClient wifiClient;
int status = WL_IDLE_STATUS;
unsigned long lastSend;

const int oneWireBus1 = 0;
OneWire oneWire1 (oneWireBus1);
DallasTemperature sensors1 (&oneWire1);

const int relay1 = 02;

struct SetPoint {
  unsigned long time;
  float temperature;
};

#define DATA_SIZE  17

SetPoint scen1[DATA_SIZE] = {
  {1622652330,26.97},//18h
  {1622652390,25.62},
  {1622678400,24.87},
  {1622689200,24.16},
  {1622700000,23.86},
  {1622710800,25.17},
  {1622721600,26.41},
  {1622732400,27.22},
  {1622743200,26.78},
  {1622754000,25.83},
  {1622764800,25.1},
  {1622775600,24.6},
  {1622786400,24.24},
  {1622797200,26.81},
  {1622808000,29.35},
  {1622818800,29.38},
  {1622829600,30.5}
};

unsigned int pos = 0;

void setup() {
  Serial.begin(115200);
  sensors1.begin();
  pinMode(relay1, OUTPUT);
  InitWiFi();
  lastSend = 0;
  timeClient.begin();

void loop() {

  sensors1.requestTemperatures();
  float temperature1 = sensors1.getTempCByIndex(0);

  timeClient.update();

  long current_time =  timeClient.getEpochTime();

  if (pos < DATA_SIZE && current_time >= scen1[pos].time) {
    if (temperature1 < scen1[pos].temperature) {
      digitalWrite (relay1, HIGH);
    }
    else if (temperature1 > scen1[pos].temperature) {
      digitalWrite (relay1, LOW);
    }
    pos++;
  }

  Serial.println(timeClient.getEpochTime());
  Serial.println(timeClient.getFormattedTime());
  Serial.println(pos);
  Serial.println(scen1[pos].temperature);
  Serial.println(scen1[pos-1].temperature);
  Serial.print("Temperature Censius - Sensor 1: ");
  Serial.print(temperature1);
  Serial.println(" ºC ");
  delay(3000);

}

```

(UPDATE)

Replacing the first `if` with `while` doesn't change anything.

The code works when taking `if` / `else if` out of nested `if`, but in this case I'm not able to increase time (the `pos++` is also commented), and define limits according to the array size.

```
//  if (pos < DATA_SIZE && current_time >= scen1[pos].time) {
    if ((temperature1 < scen1[pos].temperature)&& (current_time >= scen1[pos].time)) {
      digitalWrite (relay1, HIGH);
    }
    else if ((temperature1 > scen1[pos].temperature)&&(current_time >= scen1[pos].time)) {
      digitalWrite (relay1, LOW);
    }
//    pos++;
//  }

```

# Answer
I have to remove the `pos++` from if statement to have digitalWrite working again according to captured temperature:

```
  if (pos < DATA_SIZE && current_time >= scen1[pos].time) {
    if (temperature1 < scen1[pos].temperature) {
    digitalWrite (relay1, HIGH);
    }
    else if (temperature1 > scen1[pos].temperature) {
    digitalWrite (relay1, LOW);
    }
   }

```

Obviously this isn't updating time and the system gets stuck at time 0 of the array.

(UPDATE)

As well observed by Dave Newton, the previous observation is pointless to really fix the problem.

The problem was fixed taking the `if` statement that control the relay from inside the one controlling the time.

Now I can simulate a time interval defined with the array and use the temperature (also present in the array) to turn on/off the relay that controls the heater and simulates environment temperature:

First I created a function that will work as a thermostat:

```
void set_thermostat() {
  sensors1.requestTemperatures();
  float temperature1 = sensors1.getTempCByIndex(0);

  if (temperature1 < scen1[pos].temperature) {
    digitalWrite (relay1, HIGH);
  }
  else if (temperature1 > scen1[pos].temperature) {
    digitalWrite (relay1, LOW);
  }
}

```

Then I can it at the `loop` function, outside the statement that increases the time, based on the one defined by the array:

```
  if (pos < DATA_SIZE && current_time >= scen1[pos].times) {
    pos++;
  }

  set_thermostat();

```

This reproduces exactly what I've been looking for, with real-time control of the temperature comparing the environmental one with the model.
> 1 votes

---
Tags: esp32, relay, array, temperature-sensor, loop
---


title: I need help with my final year project

text:
# Question
Title: I need help with my final year project
I am building a project using bluetooth control as well as an ir sensor. The logic behind my program is when I press a key I want my robot to execute a series of program and while the program is executing if an obstacle is detected I need the motors to stop and then continue from the same point after the obstacle is removed. I am uploading my code for ref.

```
#include <Servo.h>
#include <AFMotor.h>
#include <Servo.h>
int obstaclePin = 12;
int obstacle = LOW;
AF_DCMotor motor1(1);
AF_DCMotor motor2(2);
AF_DCMotor motor3(3);
AF_DCMotor motor4(4);
Servo myservo1;
Servo myservo2;
int pos = 0;

char bt='S';
void setup()
{
  Serial.begin(9600);
  pinMode(obstaclePin,INPUT);
  myservo1.attach(10);
  myservo2.attach(9);
  motor1.setSpeed(100);
  motor2.setSpeed(100);
  motor3.setSpeed(100);
  motor4.setSpeed(100);
  Stop();
}

void loop() {
 bt=Serial.read();
  if(bt=='F')
{
  forward();
  delay(2000);
  backward();
  delay(2000);
  left();
  delay(2000);
  right();
  delay(2000);
  Stop();
}

if(bt=='B')
{
forward();
 delay(8000);
 left();
 delay(1500);
 ServoControl();
 delay(500);
 backward();
 delay(1000);
 right();
 delay(3000);
 forward();
 delay(8000);
 Stop();
}

if(bt=='L')
{
 forward();
 delay(10000);
 left();
 delay(1500);
 ServoControl();
 delay(500);
 backward();
 delay(1000);
 right();
 delay(3000);
 forward();
 delay(10000);
 Stop();
}

if(bt=='R')
{
 forward();
 delay(12000);
 left();
 delay(1500);
 ServoControl();
 delay(500);
 backward();
 delay(1000);
 right();
 delay(3000);
 forward();
 delay(12000);
 Stop();
}

if(bt=='S')
{
 Stop();
}
if(bt=='O')
{
  servoOpen();
}
if(bt=='C')
{
  servoCLose();

}

}
void forward()
{
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}

void backward()
{
  motor1.run(BACKWARD);
  motor2.run(BACKWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);
}
void left()
{
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
}
void right()
{
  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}
void Stop()
{
  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
}
void servoOpen()
{
  for (pos = 0; pos <= 100; pos += 1) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo1.write(pos);
    myservo2.write(pos);
  }
}

void servoCLose()
{

  for (pos = 100; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
    myservo1.write(pos);
    myservo2.write(pos);
  }
}
void ServoControl()
{
  for (pos = 0; pos <= 100; pos += 1) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo1.write(pos);
    myservo2.write(pos);
    delay(40);                       // waits 15ms for the servo to reach the position
  }
  for (pos = 100; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
    myservo1.write(pos);
    myservo2.write(pos);
    delay(40);                       // waits 15ms for the servo to reach the position
  }
}
void obstacleD()
{
  obstacle = digitalRead(obstaclePin);
   if(obstacle == HIGH)
  {
    Stop();
  }
}

```

I don't know where to add the obstacle detection so it would work like an interrupt. the main problem I was experiencing was that whenever I tried running the code on my Arduino it would completely change the logic and noting would work even if I put the command in the serial monitor until an obstacle was detected. I'm a newbie at programming and using Arduino.

# Answer
Your main problem is, that you are using many blocking calls, especially `delay()`. During that the Arduino cannot do anything else. You need to use a non-blocking coding style, doing multiple things one after another in fast succession. Here the style from the `BlinkWithoutDelay` example using `millis()` is very useful. There are lots of tutorials about that online (on this site or many others), so I will not go into detail, how that works.

---

**Quick fix:** If you just need a quick fix and the code structure of your project is not relevant for your grade, you can do the following:

Replace the `obstacleD()` function with one, that will also wait for a specific time and also check the IR sensor during that time. Something like this:

```
void obstacleD(unsigned long wait, void (*function)(void)){
    unsigned long start_time = millis();
    unsigned long already_waited = 0;
    while(millis()-start_time < wait-already_waited){
        if(digitalRead(obstaclePin)){
            already_waited += millis()-start_time;
            Stop();
            while(digitalRead(obstaclePin));
            start_time = millis();
            function();
        }
    }
}

```

Then in the rest of your code instead of `delay(1000)` (or similar) you are calling

```
obstacleD(1000, forward);

```

The first parameter is the waiting time, the second one is the function, that was lastly called (since we need to recall it, if an obstacle is found and then removed). We are noting the start time of the function into `start_time`. The first while loop will loop, until we waited as long as provided (difference between current time and start time will then be greater than the wait time minus the time we already waited). In that loop we are checking the IR sensor pin. If it reads HIGH, we add the elapsed time to our `already_waited` variable, stop and then loop while the IR sensor pin stays high. When the pin goes LOW again we leave this inner while loop, update to our new `start_time` and again execute the function to start the motors again. The code should continue the path like without an obstacle, even if multiple time an obstacle is placed during one path element.

Note, that the above code is not tested in any way. You might need to make minor changes.

---

**Interrupt quick fix:** You could implement the stopping on obstacle with an actual interrupt. Something like this:

```
void obstacle_detected(){
    while(digitalRead(obstaclePin));
}

void setup(){
    ...
    attachInterrupt(obstaclePin, obstacle_detected, RISING);
}

```

Though this is also not a good solution, since you totally block any other code, until the obstacle is removed, including receiving serial data (one byte is received by the hardware, but that has to be read by an interrupt. If another byte is send before that, the original byte is lost). Normally you would only set a flag in the ISR (interrupt service routine), but your main code isn't ready for using that flag correctly.

---

**The good-structured-code way:** To get the desired behavior with a good structured code, you need to completely restructure/rewrite your current code. As mentioned above you need to create a code, that does not block for long times, but only does things, if they need to be done at that time, and otherwise execute other code. You need to learn the usage of `millis()`.

Also your code would greatly benefit from a Finite State Machine (FSM), as Majenko already wrote in a comment. Here you first draw a diagram with your complete behavior structure, divided up into states, that do exactly one thing. The states are connected by state transitions (arrows from one state to another) (and we can even repeat a state by drawing an arrow from a state back to itself). Then you can convert that into a code structure using a state variable (integer or enum) and a `switch` statement, where each case has the code for one state. You can look at my answer to this question for more information. Or you can search for the term "finite state machine" or "FSM" on this site or google (for google you maybe should add "arduino" to the search query to get relevant results).

All in all you would create a code, that handles the wanted behavior without any hardware interrupts (not really needed here) and which is easily extendable, without getting problems with the program flow.

---

Note:

The for loop in `servoCLose()` is totally unnecessary. You don't have any delay to slow it down, so it will go to the end position in way less time, than the motor needs to even start moving. Just use `Servo.write()` one single time there with the desired angle. That is enough, unless you want it to move slowly. Then you would need a way to delay between the writes (either `delay()` or with `millis()`, depending on your then overall approach).
> 1 votes

---
Tags: arduino-uno, bluetooth, ir, arduino-motor-shield
---


# Question
Title: Issue with bluetooth and a large number LED strip
I want to be able to control multiple LED strip via bluetooth with one arduino. I coded my own android app and everything work fine with one or two led strip with few pixel. But as soon as I had to many pixel data send by BT is missing a few byte (ex "colfff5dff" instead of "color fff5dff"). It doen't happen every time but it's unrealiable. I feel like sending data to the led strip take so many time that it skip some letter.

I'm ussing dsd tech hc-05 with an arduino UNO R3 and a esp8266 led strip.

```
#include <Adafruit_NeoPixel.h>
#include <SoftwareSerial.h>

#ifdef __AVR__
 #include <avr/power.h>
#endif

//SoftwareSerial blueTooth(13,12);

#define PIN       5
#define SIZE      200

#define BRIGHTNESS 200

enum MODE {FIXED, LOOP_RGB, RUNNING, RAINBOW};
enum MODE mode = FIXED;

Adafruit_NeoPixel strip(SIZE, PIN, NEO_RGB + NEO_KHZ800);

int lastTime;

uint32_t color;
char Incoming_value = 0;
char bufferStr[100];
int bufferIndex = 0;

void setup() {

  Serial.begin(9600); //open the serial port
  Serial.setTimeout(10);
  strip.begin();
  strip.show();
  strip.setBrightness(50);

  color = Adafruit_NeoPixel::Color(0, 255 ,0 );
}

void loop() {
  if(Serial.available() > 0)
  {
    String s = Serial.readString();
    Serial.print(s);

    //I've tried some other way like read();  readString();  readBytes(); readBytesUntil();

    /*
     * ---- not needed for the issue
     */
  }
  switch (mode){
    case FIXED : fixedMode(); break;
    case RUNNING : runningLights(); break;
    case RAINBOW : rainbow(); break;
    }
    showAll();
}

void parseBlueTooth(){
  //---- not needed for the issue
}

void fixedMode(){
  setAll(color);
  showAll();
}

void rainbow(){
  //---- not needed for the issue
}

void runningLights() {
  //---- not needed for the issue
}

void setAll(byte r, byte g, byte b) {
  setAll(Adafruit_NeoPixel::Color(r,g,b));
}

void setAll(uint32_t color) {
  strip.fill(color, 0, SIZE);
}

void showAll(){
  long curTime = millis();
  if(curTime - lastTime >16){
    if(strip.canShow()) {
      strip.show();
    }
    lastTime = curTime;
  }

}

```

# Answer
> 1 votes
IMHO, after reading Majenko and raddevus reply, you may do something to "reduce missing data"

1. reduce baud rate (may be 9600), give more time for bluetooth data transfer.
2. add a checksum byte for your data.

Rererence :

https://lucidar.me/en/serialib/most-used-baud-rates-table/

# Answer
> 0 votes
Your problem is that you are using two blocking routines that can't operate together. Both the SoftwareSerial and the NeoPixel objects take time to perform operations stopping anything else from happening.

* SoftwareSerial blocks inside an ISR while receiving a byte
* NeoPixel blocks with interrupts disabled while outputting the LED status

That means that while NeoPixel is being updated SoftwareSerial is incapable of receiving any data. It was fine when you only had a few LEDs, since NeoPixel only took a very short time to update, but now that you have more LEDs it takes too long to update and SoftwareSerial can no longer work reliably.

In order to get around the problem you will have to use a hardware UART port. The Uno only has one - pins 0/1 and the `Serial` object. If you're not using that for communication with your computer you can connect your Bluetooth module there instead and use `Serial` instead of `SoftwareSerial` \- however you will most probably need to disconnect your Bluetooth module every time you want to upload fresh code to your Arduino.

# Answer
> -1 votes
I am working with HC-05 also and retrieving files over it. I send commands and get files back over Bluetooth. The speed of bluetooth *should* be fine. (Although you need to set it faster -- mine's at 38400)

Up in your `setup()` loop do:

```
Serial.begin(38400)

```

Also your code to read off serial is a bit different.

You just need the following:

```
while (Serial.available()){
    command = Serial.read();
}

```

I was sending String-based commands but just today I decided to change them to 1 byte commands because it is much easier to deal with in a switch statement. In the code above my `command` variable is a `byte`.

Then my switch looks like the following in loop():

```
switch (command){
    case 49: { // ASCII Char 1 - get Temperature
      SW_Serial.print(getString(currentRoom) + " : " + currentTemp);
      // CALL YOUR SPECIFIC CODE TO DO EACH THING IN EACH CASE
      break;
    }
    case 50: { // ASCII char 2 - start data write
      // #### Allow Data Write start/stop to be done via BT
      // turns on logging of temp data (to SD card)
      // turn on data writing and LED
      // CALL YOUR SPECIFIC CODE TO DO EACH THING IN EACH CASE
...

```

Of course, each time through the loop you should set your `command` variable back to 0 (I use 0 as the no-command). Otherwise you'll keep processing on the same command value.

---
Tags: bluetooth, led-strip
---


# Question
Title: LCD randomly goes one character further in the ascii table
Here's my code:

```
#include <LiquidCrystal.h>
int rs = 11;
int rw = 10;
int en = 9;
int d0 = 1;
int d1 = 2;
int d2 = 3;
int d3 = 4;
int d4 = 5;
int d5 = 6;
int d6 = 7;
int d7 = 8;
LiquidCrystal lcd(rs, rw, en, d0, d1, d2, d3, d4, d5, d6, d7);

void setup() {
  // put your setup code here, to run once:
  lcd.begin(16, 2);
  Serial.begin(4800);
  lcd.setCursor(0,0);
  lcd.print("Loading...");
  delay(3000);
  lcd.setCursor(1,1);
  lcd.print("waht");
}

void loop() {

}

```

And here's the output:

Also note the first line of text starts in the second column. I've tried with a different LCD and the same issue occurs. It seems to go one character further in ascii (ex: the '**.**'s become '**/**') if that's any clue to what's going on. In a separate program (exact same setup) I can print "Hello World" on the first line no problem. Anyone know why it's doing this and how to fix it? Thanks

# Answer
Your Least Significant Bit is always 1 (Check the ASCII table to see this). You might have a problem with your wiring, double check the pin you use and that the continuity is good.

Also, as KIIV said in comment, depending on the board you use, you might have a conflict with the serial port (Which pull the line high when not transmitting, explaining the result you get). Try moving pin 1 to another one.
> 2 votes

---
Tags: lcd
---


# Question
Title: How do i make this map() application work as intended?
I want to map the value range 0-63 like this:

```
x       y
0-15  = 0
16-31 = 1
32-47 = 2
48-63 = 3

```

However, using map function `y = map(x, 0, 63, 0, 3);` returns:

```
x       y
0-15  = 0
16-31 = 0
32-47 = 1
48-63 = 2

```

Is this due to truncating fractions, or something else?

Is there a better alternative?

# Answer
`map()` doesn't *quite* work as you'd expect. The formula is:

```
(x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

```

And all those values are `long`, which is a "long" integer. So all operations are done as integers, and that means that you lose an awful lot of precision in the calculation, since all decimal components are completely ignored.

It means that you only get the maximum output when you put in the maximum input.

As Michael Keijzers notes your expected output is `x/16` (or `x>>4` in bitwise notation), and that can be achieved with `map()` if you set the maximum input to be 48, not 63.

However a simple right shift 4 bits (or divide by 16 if the compiler is clever enough to implement it as a right shift) is a more efficient solution by far, since the processing involved is almost negligible, whereas multiplying and dividing is a relatively expensive set of operations.
> 2 votes

# Answer
You could try:

```
y = map(x, 0, 64, 0, 4);

```

Majenko showed you the formula used by `map()`. You can check that the formula works nicely if you think in terms of half-open intervals:

\[0, 64) → \[0, 4)

But this is still way less efficient than a bit shift.
> 1 votes

---
Tags: map
---


# Question
Title: Nature of the voltage reference instability of internal 1.1V reference of ATmega328P (Nano)
The ATmega328P data sheet in table 29-11 on page 324 notes that the internal 1.1V reference (VBG) may vary between 1.0V and 1.2V. In this answer this is called "not stable or accurate".

Question: Is this "unstable" or "inaccurate" or even both if I define it as

* "unstable" if it varies over the day, say with temperature or VCC or or some such.
* "inaccurate" if it is a rather stable voltage for a specific Nano-board I have in hand, just not the typical 1.1V.

In the latter case I could measure the value accurately and scale my analog measurements with the measured value instead of the 1.1V.

# Answer
I would say it was "stable but not accurate". The internal reference uses a bandgap voltage reference, which is pretty stable over the operating temperature range of the IC.

The output of the bandgap reference *is* fed through an amplifier to buffer it, which may introduce some instability with temperature, but this is not documented so cannot even be estimated.

The inaccuracy comes from minor differences in the manufacturing process. These don't change over time, so once calibrated for a precise value of voltage reference you should not see much in the way of variance in that value for different temperatures or power supply fluctuations.
> 3 votes

---
Tags: arduino-nano, analogreference
---


# Question
Title: Convert float to byte, from Arduino to Raspberry Pi i2c
I'm trying to send the temperature value from the DHT sensor to a raspberry pi through I2C. Which is the best way to do it?. The temp value is a float, and I think I have to convert it to byte and send that with Wire.write() to the raspberry, is that right?. Right now I'm sending bytes from the raspberry (with Python) to the Arduino (C++): Python:

```
from smbus import SMBus
import time

address = 0x8
bus = SMBus(1)

While True:
  bus.write_byte(address, 4)
  time.sleep(1)
  print(bus.ready_byte(address))

```

Arduino code:

```
#include <Wire.h>
#include <DHT.h>
...

void setup() {
  dht.begin();
  Wire.begin(0x8);
  Wire.onReceive(receiveEvent);
}

void receiveEvent () {
  float temp = dht1.readTemperature();
  delay(1000);
  byte tempByte[4] = {temp, 0, 0, 0};
  Wire.write(tempByte[0]);
}

```

So the raspberry is printing 0.

Thanks for any help.

# Answer
> 5 votes
First of all, if you want the Arduino to send data as a slave, it should do so `onRequest()`, not `onReceive()`. Thus:

```
void setup() {
    Wire.begin(0x08);
    Wire.onRequest(handleRequest);
}

```

Next, as pointed out by chrisl in a comment, you should not delay within the `onRequest` handler. I would go further and say that you should not even call `dht1.readTemperature()`, as that could take too much time to be done in interrupt context. Instead, have the main loop query the sensor periodically, and have the latest reading always available:

```
volatile float temperature;  // latest valid reading

void loop() {
    float new_temperature = dht1.readTemperature();
    noInterrupts();
    temperature = new_temperature;
    interrupts();
    // ...
}

```

Note that the latest value is updated with interrupts disabled. This is to avoid a data race that could happen if the Arduino receives a request while it is in the middle of updating the value. Notice also that interrupts are disabled during a very short time: just the time needed to update the variable.

Lastly, to send the data, you can use the version of `Wire.write()` that accepts a buffer of arbitrary length:

```
void handleRequest() {
    Wire.write((uint8_t *) &temperature, sizeof temperature);
}

```

The temperature will be sent LSB-first, as a float, formatted as per IEEE 754. The Raspberry Pi should be able to digest it in this very same format.

---
Tags: arduino-mega, i2c, raspberrypi, float, dht22
---


# Question
Title: Need HELP!! Serial communication has a very "Strange Problem"
I am working on building a serial command receiver. The idea is came from the boot loader. However, I got a very strange problem that I have no idea what could cause it.

As the first screenshot show, the print isn't finished because "===a=" is stuck, like this.

In the code, it should print out and the others.

```
char* receiveCmd(Stream &_serial, char &cmd_ptr, int &l_ptr) {
  Stream* serial = &_serial;

  if (serial->available() && (uint8_t)serialRead(_serial) == CMD_START) {
    int buf_count = 0; //start at data
    cmd_ptr = serialRead(_serial); //cmd_byte

    char low_byte = serialRead(_serial);
    char high_byte = serialRead(_serial);

    uint16_t length = low_byte; //data_length
    length = length | (high_byte << 8);

    Serial.println("\n\n===a===");
    Serial.println(length);
    Serial.println("===b===");

    l_ptr = (int)length;

    char* _buf = (char*)malloc(length * sizeof(char));

    while (buf_count != length) {
      if (serial->available()) {
        _buf[buf_count] = serial->read();
        buf_count++;
      }
    }

    char checksum = serialRead(_serial); //checksum, don't bother it yett
    char stop_byte = serialRead(_serial);

    if (stop_byte != CMD_EOF) {
      free(_buf);
      return NULL; //error
    }

    return _buf;
  }

  return NULL;
}

```

Anyway, the problem is fixed when I print out other variables first, then the length var..

```
char* receiveCmd(Stream &_serial, char &cmd_ptr, int &l_ptr) {
  Stream* serial = &_serial;

  if (serial->available() && (uint8_t)serialRead(_serial) == CMD_START) {
    int buf_count = 0; //start at data
    cmd_ptr = serialRead(_serial); //cmd_byte

    char low_byte = serialRead(_serial);
    char high_byte = serialRead(_serial);

    uint16_t length = low_byte; //data_length
    length = length | (high_byte << 8);

    Serial.println("\n\n===a===");
    Serial.println(low_byte, HEX);
    Serial.println(high_byte, HEX);
    Serial.println(length);
    Serial.println("===b===");

    l_ptr = (int)length;

    char* _buf = (char*)malloc(length * sizeof(char));

    while (buf_count != length) {
      if (serial->available()) {
        _buf[buf_count] = serial->read();
        buf_count++;
      }
    }

    char checksum = serialRead(_serial); //checksum, don't bother it yett
    char stop_byte = serialRead(_serial);

    if (stop_byte != CMD_EOF) {
      free(_buf);
      return NULL; //error
    }

    return _buf;
  }

  return NULL;
}

```

Other code is exactly the same. Does anyone know what may cause it? I can't print out those thing during production because it is only for debugging. If I remove those print, the code is also stuck(because of the length variable again).

For additional information, the serial signal is generated from other Arduino and AltSerial Library. The structure is like this.

```
void sendCmd(Stream &_serial, char cmd, char* payload, int length) {
  Stream* serial = &_serial;
  char buf[6 + length]; //start, data_length, data, checksum, stop

  buf[0] = CMD_START; //start_byte
  buf[1] = cmd; //cmd_byte
  buf[2] = length & 0xff; //data_length - low byte
  buf[3] = (length >> 8) & 0xff; //data_length - high byte
  buf[4 + length] = (char)calcCRC(payload); //checksum
  buf[5 + length] = CMD_EOF; //stop_byte

  for (int i = 0; i < length; i++) //load buf
    buf[4 + i] = payload[i];

  for (int i = 0; i < sizeof(buf); i++)
    serial->print(buf[i]);
}

```

I have used `Serial.print(altSerial.read(), HEX)` to check whether the byte is received correctly. They are all correct. That's why it is confusing me.QAQ

===== UPDATED INFORMATION =====

I have narrowed the problem. It seems like the below code is the main cause regard the issue. But no solution for this still.

```
uint16_t length = low_byte; //data_length
length = length | (high_byte << 8);

```

Thank you.

# Answer
> 2 votes
Why it does not work? You already got the answer in comments:

* You are reading more bytes from the serial stream than what you know are available. Then, your `length` variable can contain garbage, which makes `malloc()` fail even if you have plenty of available memory.
* You write into the memory buffer even if the allocation failed, which makes your program corrupt its memory. From this point, anything can happen.

You may notice that the behavior of your program depends on the timing. Adding more instructions, or delays, may make it work. This is simply because you give your peer more time to send its data packet. Of course, relying on the timings is not a good approach: you instead have to make sure you never `read()` more than what is actually `available()`.

Here is an (untested) attempt to do this correctly and in a non-blocking fashion. It is based on a finite state machine. What is original about this state machine is that it is implemented as a `switch`/`case` where *every single case* falls through:

```
/*
 * Packet format:
 *   CMD_START cmd_byte length_L length_H [payload] checksum CMD_EOF
 */
char *receiveCmd(Stream &serial, char &cmd_ref, int &l_ref) {

    // The current state is defined by what parts of the packet
    // we have already received.
    static enum {
        GOT_NONE, GOT_START, GOT_HEADER, GOT_PAYLOAD
    } state = GOT_NONE;

    // Variables only valid in the states GOT_HEADER and GOT_PAYLOAD.
    static char cmd_byte;
    static uint16_t length;
    static char *buffer;
    static size_t buffer_pos;

    switch (state) {
        case GOT_NONE:
            if (serial.available() < 1 || serial.read() != CMD_START)
                break;
            state = GOT_START;
            // fallthrough
        case GOT_START:
            if (serial.available() < 3)
                break;
            cmd_byte = serial.read();
            length = serial.read();
            length |= (uint16_t) serial.read() << 8;
            buffer = (char *) malloc(length);
            if (!buffer) {
                Serial.print(F("ERROR: Failed to allocate "));
                Serial.print(length);
                Serial.println(F(" bytes."));
                state = GOT_NONE;
                break;
            }
            buffer_pos = 0;
            state = GOT_HEADER;
            // fallthrough
        case GOT_HEADER:
            while (buffer_pos < length && serial.available())
                buffer[buffer_pos++] = serial.read();
            if (buffer_pos < length)
                break;
            state = GOT_PAYLOAD;
            // fallthrough
        case GOT_PAYLOAD:
            if (serial.available() < 2)
                break;
            serial.read();  // consume checksum
            if (serial.read() != CMD_EOF) {
                Serial.println(F("ERROR: Expected CMD_EOF."));
                free(buffer);
                state = GOT_NONE;
                break;
            }
            cmd_ref = cmd_byte;
            l_ref = length;
            state = GOT_NONE;
            return buffer;
    }
    return NULL;
}

```

You can think of this `switch`/`case` as a set of actions to perform sequentially in order to process the whole packet. However, if the function gets stuck for lack of incoming data, it just bails out. On the next call, the `switch` puts it back where it left.

---
Tags: serial, uart, print
---


# Question
Title: Adafruit Thermal Printer unwanted gradient
I have thermal printer from adafruit and when printing images I have problems getting a proper black.

I tried playing with the dot print time and the dot feed time using the `setTimes` function, but this seem to have no effect.

```
  unsigned long dotPrintTime = 3000*30L;
  unsigned long dotFeedTime = 2100*30L;
  printer.setTimes(dotPrintTime, dotFeedTime);

```

Also the `setHeatConfig` seems to have no effect. I tried different values.

```
  uint8_t dots = 11;
  uint8_t _time = 120;
  uint8_t interval = 40;
  printer.setHeatConfig(dots, _time, interval);

```

Here an image of the result:

Is it possible to print fully black the whole width of the paper?

# Answer
Thermal printers generate quick pulses of heat to change thermal paper from white to a darker color. This may require more than the expected amount of current most Arduino project need.

Consider checking the maximum current rating of your power source. From the Adafruit printer web page regarding using this Mini Thermal Receipt Printer:

> This printer in particular requires 5 to 9 Volts, 1.5 Amps current! That means you will need a fairly beefy supply and you cannot run it off of USB power. An external adapter is required!

Also consider trying different thermal paper manufactures and colors.

Lastly, consider how you might avoid BPA from thermal paper.
> 3 votes

---
Tags: arduino-uno, adafruit
---


title: How to change Arduino Nano MODEL_ID

text:
# Question
Title: How to change Arduino Nano MODEL_ID
I'm working on a project using a set of different Arduino Nano connected to a Raspberry Pi through USB. Now my question is: *"how can I, from the Pi's point of view, differentiate all of those Arduino and associate them with their respective tty?"*

I found some part of my answer in this question. The answering guy proposes to manually change the Arduino `MODEL_ID` when compiling and to use it afterwork to identify the device. The problem is that I don't know how to achieve that.

I tried to edit the `boards.txt` file to add a new board configuration with custom `vid.x` and `pid.x` (why all those 4 different values?) but after selecting my board and uploading, the `MODEL_ID` still stays the same:

```
ID_MODEL_FROM_DATABASE=HL-340 USB-Serial adapter
ID_MODEL_ID=7523

```

Can't I just specify somehow the `USB_PID` macro to the compiler command line?

# Answer
> How to change Arduino Nano MODEL\_ID?

The Arduino Nano used a special USB-Serial adapter (FTDI FT232RL). You can change the ID but this requires some special hacking. Please see the provided links.

Cheers!
> 0 votes

# Answer
Finally find the solution =)

You don't have to change the ID vendor or ID product: it is possible to attribute a permanent name with devpath (where the device is plugged) The only downside of using the devpath is that the devices will always have to stay plugged into the same physical port.

Answer here:PersistentUSBDevices / Alternative filtering via Devpath
> 3 votes

---
Tags: arduino-nano, compile, command-line
---


title: Esp32 Https Problem

text:
# Question
Title: Esp32 Https Problem
I am working on a project in which i have to send GET request to my Company's Https server. I have successfully sent the GET request using NodeMCU v 1.0 (ESP 12E). The **NodeMCU 1.0 (ESP 12E)** Arduino library uses SSL certificate Fingerprint ,host name and url to send the GET request. it is easy to find the fingerprint of Certificate using this website -\> https://www.grc.com/fingerprints.htm

But in ESP 32 Arduino Library i have to pass the SSL certificate . I have no idea how to find the SSL certificate of my Company's website.

The format of the SSL certificate used in ESP 32 Arduino library is given below :

```
/*
const char* ca = \
"-----BEGIN CERTIFICATE-----\n" \
"MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/\n" \
"MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\n" \
"DkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0Nlow\n" \
"SjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMT\n" \
"GkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOC\n" \
"AQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EF\n" \
"q6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8\n" \
"SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0\n" \
"Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWA\n" \
"a6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj\n" \
"/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0T\n" \
"AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIG\n" \
"CCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNv\n" \
"bTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9k\n" \
"c3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAw\n" \
"VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC\n" \
"ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz\n" \
"MDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwu\n" \
"Y3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsF\n" \
"AAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJo\n" \
"uM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/\n" \
"wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwu\n" \
"X4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlG\n" \
"PfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6\n" \
"KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==\n" \
"-----END CERTIFICATE-----\n";
*/

```

Is there any easy way to find the SSL certificate of any website which uses Https instead of simple http ?

Thanks in advance

# Answer
in chrome:

* press \[F12\]
* click the "Security" tab
* click the "View Certificate" button under "Security overview"
* click the "details" tab on the "Certificate" popup
* click the "Copy to File..." button
* click the "Next" button
* check the "base64 encoded x509" option
* click the "Next" button
* click the "Browse" button and choose a folder for the export
* enter a file name in the provided space
* click the "Next" button
* click the "Finish" button
* browse to the folder and open the export using a text editor

The export file has the same format, you just need to convert to a C literal usiing end-of-line slashes and quotes, an exercise i'll let you handle. There might be some fancy tool that does all this for you, I'd love to hear about one, but I know this is a fairly universal way to get it done.
> 0 votes

# Answer
Using e.g., openssl is possible. The command could go like this from the shell: `openssl s_client -showcerts -servername www.theserver.io -connect www.theserver.io:443 -certform DER`

Including `>mycertif.der` at the end of the command, you get the information in a file so you can cut-paste that part of the command output. Best,
> 1 votes

# Answer
Even if it's an old question... I suggest **not** rely on methods describe here. Of course you can get the SSL certificate from the browser and copy-paste it into your code. But each time the server will renews the certificate, the key change! If you have a "free" certificate, like the one from Let's Encrypt, used for example in all the shared hosting of all major web hosting companies, the key will change every... 3 months! So you'll have to update your ESP code each 3 months... For testing purpose, that's OK but for real "application" it's not a good option.

So,how can we do?

* Option 1: add a module on your web server, allowing to have a pre-defined SSL key. You just set the key for a specific folder and copy it to your ESP. My server is an Apache one and it seems this modules don't exist for Apache.
* Options 2: edit your Apache conf (commonly at etc/apache2/) for your serveur. In many cases, each time a customer access your server with http, Apache will change the call to https.
This is made with a rewrite rule. You can change this like that:

```
  RewriteCond %{HTTPS} off
  RewriteCond %{THE_REQUEST} !/XXXXXX [NC]
  RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

  RewriteCond %{HTTPS} on
  RewriteCond %{THE_REQUEST} /XXXXXX [NC]
  RewriteRule ^ http://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

```

where XXXX is the name fo the folder in which you will put the script called by your ESP. With that all folder on your site are using https except the one you use with your ESP. Of course this mean your ESP call is done using http and not https but in many cases we have to use ESP+https not for real security reason but because the web site is in https.
> 1 votes

---
Tags: esp8266, esp32
---


# Question
Title: How can I add an additional temperature sensor (EZO RTD of Atlas Scientific) to an Atlas Scientific bare-bones wifi pool kit?
## Problem summary

When I changed the I2C address of a sensor (EZO RTD) to another address (e.g., 50 or 100) from its default address (102), it didn't work on my Atlas Scientific bare-bones WiFi Hydroponics Kit.

## Specific description

I tried to add a temperature sensor (EZO RTD) to an Atlas Scientific bare-bones WiFi Hydroponics Kit that already has a pH Sensor (EZO pH) and a temperature sensor (EZO RTD) on the pH port and Temperature port, respectively. Since a provided setup guide of Atlas Scientific says that each sensor on the kit has to have a different I2C address when multiple sensors are used on it. So I assigned an I2C address "50" to the additional sensor and then added it to the AUX port (and tried the Temperature port as well), but it didn't work at all. Meanwhile, the temperature sensor with the default I2C address 102) works very well on both the Temperature and AUX ports. I guess this might be related to a coding problem. Atlas Scientific's provided code is as follows: THE CODE IS DELETED BY MYSELF

Thanks for reading my problem.

Jayjay

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

I solved this problem based on the answer I voted for.

The code I made is as follows:

```
#include <iot_cmd.h>
#include <ESP8266WiFi.h>                                         //include esp8266 wifi library
#include "ThingSpeak.h"                                          //include thingspeak library
#include <sequencer4.h>                                          //imports a 4 function sequencer
#include <sequencer1.h>                                          //imports a 1 function sequencer
#include <Ezo_i2c_util.h>                                        //brings in common print statements
#include <Ezo_i2c.h> //include the EZO I2C library from https://github.com/Atlas-Scientific/Ezo_I2c_lib
#include <Wire.h>    //include arduinos i2c library

WiFiClient client;                                              //declare that this device connects to a Wi-Fi network,create a connection to a specified internet IP address

//----------------Fill in your Wi-Fi / ThingSpeak Credentials-------
const String ssid = "WIFI NAME";                                 //The name of the Wi-Fi network you are connecting to
const String pass = "WIFI PASSWORD";                             //Your WiFi network password
const long myChannelNumber = ;                            //Your Thingspeak channel number
const char * myWriteAPIKey = "";                 //Your ThingSpeak Write API Key
//------------------------------------------------------------------

Ezo_board PH = Ezo_board(99, "PH");       //create a PH circuit object, who's address is 99 and name is "PH"
Ezo_board EC = Ezo_board(100, "EC");      //create an EC circuit object who's address is 100 and name is "EC"
Ezo_board RTD = Ezo_board(102, "RTD");    //create an RTD circuit object who's address is 102 and name is "RTD"
Ezo_board RTD2 = Ezo_board(50, "RTD2");   //create an RTD circuit object who's address is 50 and name is "RTD2"
Ezo_board PMP = Ezo_board(103, "PMP");    //create an PMP circuit object who's address is 103 and name is "PMP"

Ezo_board device_list[] = {   //an array of boards used for sending commands to all or specific boards
  PH,
  EC,
  RTD,
  RTD2,
  PMP
};

Ezo_board* default_board = &device_list[0]; //used to store the board were talking to

//gets the length of the array automatically so we dont have to change the number every time we add new boards
const uint8_t device_list_len = sizeof(device_list) / sizeof(device_list[0]);

//enable pins for each circuit
const int EN_PH = 14;
const int EN_EC = 12;
const int EN_RTD = 15;
const int EN_AUX = 13;

const unsigned long reading_delay = 1000;                 //how long we wait to receive a response, in milliseconds
const unsigned long thingspeak_delay = 15000;             //how long we wait to send values to thingspeak, in milliseconds

unsigned int poll_delay = 2000 - reading_delay * 2 - 300; //how long to wait between polls after accounting for the times it takes to send readings

//parameters for setting the pump output
#define PUMP_BOARD        PMP       //the pump that will do the output (if theres more than one)
#define PUMP_DOSE         -0.5      //the dose that the pump will dispense in  milliliters
#define EZO_BOARD         EC        //the circuit that will be the target of comparison
#define IS_GREATER_THAN   true      //true means the circuit's reading has to be greater than the comparison value, false mean it has to be less than
#define COMPARISON_VALUE  1000      //the threshold above or below which the pump is activated

float k_val = 0;                                          //holds the k value for determining what to print in the help menu

bool polling  = true;                                     //variable to determine whether or not were polling the circuits
bool send_to_thingspeak = true;                           //variable to determine whether or not were sending data to thingspeak

bool wifi_isconnected(){                            //function to check if wifi is connected
  return (WiFi.status() == WL_CONNECTED);
}

void reconnect_wifi(){                                    //function to reconnect wifi if its not connected
  if(!wifi_isconnected()){
    WiFi.begin(ssid, pass);
    Serial.println("connecting to wifi");
  }
}

void thingspeak_send(){
  if (send_to_thingspeak == true) {                                                    //if we're datalogging
    if(wifi_isconnected()){
      int return_code = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
      if (return_code == 200) {                                                          //code for successful transmission
          Serial.println("sent to thingspeak");
      }else{
        Serial.println("couldnt send to thingspeak");
      }
    }
  }
}

void step1();      //forward declarations of functions to use them in the sequencer before defining them
void step2();
void step3();
void step4();
Sequencer4 Seq(&step1, reading_delay,   //calls the steps in sequence with time in between them
               &step2, 300,
               &step3, reading_delay,
               &step4, poll_delay);

Sequencer1 Wifi_Seq(&reconnect_wifi, 10000);  //calls the wifi reconnect function every 10 seconds

Sequencer1 Thingspeak_seq(&thingspeak_send, thingspeak_delay); //sends data to thingspeak with the time determined by thingspeak delay

void setup() {

  pinMode(EN_PH, OUTPUT);                                                         //set enable pins as outputs
  pinMode(EN_EC, OUTPUT);
  pinMode(EN_RTD, OUTPUT);
  pinMode(EN_AUX, OUTPUT);
  digitalWrite(EN_PH, LOW);                                                       //set enable pins to enable the circuits
  digitalWrite(EN_EC, LOW);
  digitalWrite(EN_RTD, HIGH);
  digitalWrite(EN_AUX, LOW);

  Wire.begin();                           //start the I2C
  Serial.begin(9600);                     //start the serial communication to the computer

  WiFi.mode(WIFI_STA);                    //set ESP8266 mode as a station to be connected to wifi network
  ThingSpeak.begin(client);               //enable ThingSpeak connection
  Wifi_Seq.reset();                       //initialize the sequencers
  Seq.reset();
  Thingspeak_seq.reset();
}

void loop() {
 String cmd;                            //variable to hold commands we send to the kit

  Wifi_Seq.run();                        //run the sequncer to do the polling

  if (receive_command(cmd)) {            //if we sent the kit a command it gets put into the cmd variable
    polling = false;                     //we stop polling
    send_to_thingspeak = false;          //and sending data to thingspeak
    if(!process_coms(cmd)){              //then we evaluate the cmd for kit specific commands
      process_command(cmd, device_list, device_list_len, default_board);    //then if its not kit specific, pass the cmd to the IOT command processing function
    }
  }

  if (polling == true) {                 //if polling is turned on, run the sequencer
    Seq.run();
    Thingspeak_seq.run();
  }
}

//function that controls the pumps activation and output
void pump_function(Ezo_board &pump, Ezo_board &sensor, float value, float dose, bool greater_than){
 if (sensor.get_error() == Ezo_board::SUCCESS) {                    //make sure we have a valid reading before we make any decisions
    bool comparison = false;                                        //variable for holding the reuslt of the comparison
    if(greater_than){                                               //we do different comparisons depending on what the user wants
      comparison = (sensor.get_last_received_reading() >= value);   //compare the reading of the circuit to the comparison value to determine whether we actiavte the pump
    }else{
      comparison = (sensor.get_last_received_reading() <= value);
    }
    if (comparison) {                                               //if the result of the comparison means we should activate the pump
      pump.send_cmd_with_num("d,", dose);                           //dispense the dose
      delay(100);                                                   //wait a few milliseconds before getting pump results
      Serial.print(pump.get_name());                                //get pump data to tell the user if the command was received successfully
      Serial.print(" ");
      char response[20];
      if(pump.receive_cmd(response, 20) == Ezo_board::SUCCESS){
        Serial.print("pump dispensed ");
      }else{
        Serial.print("pump error ");
      }
      Serial.println(response);
    }else {
      pump.send_cmd("x");                                          //if we're not supposed to dispense, stop the pump
    }
  }
}

void step1() {
  //send a read command. we use this command instead of RTD.send_cmd("R");
  //to let the library know to parse the reading
  RTD.send_read_cmd();
  RTD2.send_read_cmd();
}

void step2() {
  receive_and_print_reading(RTD);             //get the reading from the RTD circuit
    if ((RTD.get_error() == Ezo_board::SUCCESS) && (RTD.get_last_received_reading() > -1000.0)) { //if the temperature reading has been received and it is valid
    PH.send_cmd_with_num("T,", RTD.get_last_received_reading());
    EC.send_cmd_with_num("T,", RTD.get_last_received_reading());
    ThingSpeak.setField(2, String(RTD.get_last_received_reading(), 2));                 //assign temperature readings to the third column of thingspeak channel
  } else {                                                                                //if the temperature reading is invalid
    PH.send_cmd_with_num("T,", 25.0);
    EC.send_cmd_with_num("T,", 25.0);                                                          //send default temp = 25 deg C to EC sensor
    ThingSpeak.setField(2, String(25.0, 2));                 //assign temperature readings to the third column of thingspeak channel
  }

  Serial.print(" ");
  receive_and_print_reading(RTD2);
  if ((RTD2.get_error() == Ezo_board::SUCCESS) && (RTD2.get_last_received_reading() > -1000.0)) { //if the temperature reading has been received and it is valid
    PH.send_cmd_with_num("T,", RTD2.get_last_received_reading());
    EC.send_cmd_with_num("T,", RTD2.get_last_received_reading());
    ThingSpeak.setField(3, String(RTD2.get_last_received_reading(), 2));                 //assign temperature readings to the third column of thingspeak channel
  } else {                                                                                //if the temperature reading is invalid
    PH.send_cmd_with_num("T,", 25.0);
    EC.send_cmd_with_num("T,", 25.0);                                                          //send default temp = 25 deg C to EC sensor
    ThingSpeak.setField(3, String(25.0, 2));                 //assign temperature readings to the third column of thingspeak channel
  }

}

void step3() {
  //send a read command. we use this command instead of PH.send_cmd("R");
  //to let the library know to parse the reading
  PH.send_read_cmd();
  EC.send_read_cmd();
}

void step4() {
  receive_and_print_reading(PH);             //get the reading from the PH circuit
  if (PH.get_error() == Ezo_board::SUCCESS) {                                          //if the PH reading was successful (back in step 1)
     ThingSpeak.setField(1, String(PH.get_last_received_reading(), 2));                 //assign PH readings to the first column of thingspeak channel
  }
  Serial.print("  ");
  receive_and_print_reading(EC);             //get the reading from the EC circuit
  if (EC.get_error() == Ezo_board::SUCCESS) {                                          //if the EC reading was successful (back in step 1)
     ThingSpeak.setField(2, String(EC.get_last_received_reading(), 0));                 //assign EC readings to the second column of thingspeak channel
  }

  Serial.println();
  pump_function(PUMP_BOARD, EZO_BOARD, COMPARISON_VALUE, PUMP_DOSE, IS_GREATER_THAN);
}

void start_datalogging() {
  polling = true;                                                 //set poll to true to start the polling loop
  send_to_thingspeak = true;
  Thingspeak_seq.reset();
}

bool process_coms(const String &string_buffer) {      //function to process commands that manipulate global variables and are specifc to certain kits
  if (string_buffer == "HELP") {
    print_help();
    return true;
  }
  else if (string_buffer.startsWith("DATALOG")) {
     start_datalogging();
    return true;
  }
  else if (string_buffer.startsWith("POLL")) {
    polling = true;
    Seq.reset();

    int16_t index = string_buffer.indexOf(',');                    //check if were passing a polling delay parameter
    if (index != -1) {                                              //if there is a polling delay
      float new_delay = string_buffer.substring(index + 1).toFloat(); //turn it into a float

      float mintime = reading_delay*2 + 300;
      if (new_delay >= (mintime/1000.0)) {                                       //make sure its greater than our minimum time
        Seq.set_step4_time((new_delay * 1000.0) - mintime);          //convert to milliseconds and remove the reading delay from our wait
      } else {
        Serial.println("delay too short");                          //print an error if the polling time isnt valid
      }
    }
    return true;
  }
  return false;                         //return false if the command is not in the list, so we can scan the other list or pass it to the circuit
}

void get_ec_k_value(){                                    //function to query the value of the ec circuit
  char rx_buf[10];                                        //buffer to hold the string we receive from the circuit
  EC.send_cmd("k,?");                                     //query the k value
  delay(300);
  if(EC.receive_cmd(rx_buf, 10) == Ezo_board::SUCCESS){   //if the reading is successful
    k_val = String(rx_buf).substring(3).toFloat();        //parse the reading into a float
  }
}

void print_help() {
  get_ec_k_value();
  Serial.println(F("Atlas Scientific I2C hydroponics kit                                       "));
  Serial.println(F("Commands:                                                                  "));
  Serial.println(F("datalog      Takes readings of all sensors every 15 sec send to thingspeak "));
  Serial.println(F("             Entering any commands stops datalog mode.                     "));
  Serial.println(F("poll         Takes readings continuously of all sensors                    "));
  Serial.println(F("                                                                           "));
  Serial.println(F("ph:cal,mid,7     calibrate to pH 7                                         "));
  Serial.println(F("ph:cal,low,4     calibrate to pH 4                                         "));
  Serial.println(F("ph:cal,high,10   calibrate to pH 10                                        "));
  Serial.println(F("ph:cal,clear     clear calibration                                         "));
  Serial.println(F("                                                                           "));
  Serial.println(F("ec:cal,dry           calibrate a dry EC probe                              "));
  Serial.println(F("ec:k,[n]             used to switch K values, standard probes values are 0.1, 1, and 10 "));
  Serial.println(F("ec:cal,clear         clear calibration                                     "));

  if(k_val > 9){
     Serial.println(F("For K10 probes, these are the recommended calibration values:            "));
     Serial.println(F("  ec:cal,low,12880     calibrate EC probe to 12,880us                    "));
     Serial.println(F("  ec:cal,high,150000   calibrate EC probe to 150,000us                   "));
  }
  else if(k_val > .9){
     Serial.println(F("For K1 probes, these are the recommended calibration values:             "));
     Serial.println(F("  ec:cal,low,12880     calibrate EC probe to 12,880us                    "));
     Serial.println(F("  ec:cal,high,80000    calibrate EC probe to 80,000us                    "));
  }
  else if(k_val > .09){
     Serial.println(F("For K0.1 probes, these are the recommended calibration values:           "));
     Serial.println(F("  ec:cal,low,84        calibrate EC probe to 84us                        "));
     Serial.println(F("  ec:cal,high,1413     calibrate EC probe to 1413us                      "));
  }

  Serial.println(F("                                                                           "));
  Serial.println(F("rtd:cal,t            calibrate the temp probe to any temp value            "));
  Serial.println(F("                     t= the temperature you have chosen                    "));
  Serial.println(F("rtd:cal,clear        clear calibration                                     "));
 }

```

# Answer
Did you update the code above to add your new sensor?

A quick look at Atlas' site and their Github page didn't find an obvious instruction to do what you're try to do, so that's the first thing I'd try if you haven't already. Below the Thinkspeak Credentials section, add your new device to the I2C devices definitions, then add its name to the array of available devices. I called the new temp sensor RTD2 in my example below, but you could probably call it something more descriptive of its function or placement. It looks like there is a name string in each definition that (I'm guessing) will be displayed in Thingspeak's data, and would be a good place to put a short description.

```
        Ezo_board PH = Ezo_board(99, "PH");       //create a PH circuit object, who's address is 99 and name is "PH"
        Ezo_board EC = Ezo_board(100, "EC");      //create an EC circuit object who's address is 100 and name is "EC"
        Ezo_board RTD = Ezo_board(102, "RTD");    //create an RTD circuit object who's address is 102 and name is "RTD";
        Ezo_board RTD2 = Ezo_board(50, "RTD2");   //create an RTD circuit object who's address is 50 and name is "RTD2"
        Ezo_board PMP = Ezo_board(103, "PMP");    //create an PMP circuit object who's address is 103 and name is "PMP"

        Ezo_board device_list[] = {   //an array of boards used for sending commands to all or specific boards
          PH,
          EC,
          RTD,
          RTD2,
          PMP
        };

```

Update:

On review, it looks like you'll need to define an Arduino pin to enable the new device (in the `//enable pins for each circuit` section) and enable it at the head of `setup()` where the the other devices' pins are set to OUTPUT mode, and set this pin HIGH (guessing that your new RTD will be identical to your current one):

```
//enable pins for each circuit
const int EN_PH = 14;
const int EN_EC = 12;
const int EN_RTD = 15;
const int EN_RTD2 =    <some available pin# here> ;
const int EN_AUX = 13;

```

And in setup():

```

 pinMode(EN_RTD2, OUTPUT);

  ...

 digitalWrite(EN_RTD2, HIGH);

```

Update 2:

I think what we did above will get your new sensor data logged to Thingspeak, since I see a message referring to a "datalog mode" in `print_help()`. If you're expecting the control process to act your new sensor data in some way, you'll need to understand what it does now and what you want it to do differently based on the newly available data. But I would still take getting the system to just log the new data as your first step.
> 0 votes

---
Tags: arduino-ide
---


# Question
Title: Run computation only on request over serial
An Arduino Nano is set up to perform A/D conversions and send results out over `Serial`. Currently the code structure is like

```
loop() {
  delayUntilNextTargetTime();
  measure();
  sendMeasurementsToSerial();
}

```

Though I make already sure that `delayUntilNextTargetTime` does not blindly `delay(MILLIS)` but rather subtracts the computation time from the time to sleep to prevent drift, I would rather get the timing from the host computer.

The idea is that the host computer sends a command string over the serial when it wants data, so the loop could look like

```
loop() {
  if (!Serial.available()) return;
  measure();
  sendMeasurementsToSerial();
}

```

Now I wonder if there is a way to do this without idle polling, something along the lines of

```
loop() {
  if(Serial.available()) {
    measure();
    sendMeasurementsToSerial();
  }
  sleepUntilSerialPotentiallyHasData();
}

```

I read that saving power is hard and likely not worth the effort, in particular when having a USB power supply. It is pure curiosity to see

* what it takes to bring the system into, say, IDLE mode, possibly stopping the timers too, because they are not used (I guess)
* and what it takes to get out of IDLE mode correctly again such that A/D conversion in `measure()` works without flaws.

# Answer
> 3 votes
On a Nano you can `#include <avr/sleep.h>`, then simply call `sleep_mode()` from `loop()`. This will put the device to sleep, by default in IDLE mode, until the next interrupt fires. The Nano will wake up at least once every 1,024 µs, to service the timer interrupt that is used to implement the Arduino timing function(`millis()`, `delay()`, etc.). Most of the time this `loop()` will do nothing more than testing `Serial.available()`, so the MCU will be awake only for a couple of microseconds every 1,024 µs, which is not much.

If you disable the timer interrupt, all the timing functions will be off, but the MCU will still be waken by the serial port interrupt as soon as data is available.

---
Tags: serial, interrupt, loop
---


# Question
Title: "avrdude: stk500_getsync(): not in sync: resp=0x00," aka Some Dude Named Avr Won't Let Me Upload My Program
I made an awesome program the other day, and I wanted to upload it to my Arduino. After clicking the upload button, some mean dude named avr came along and stopped me, saying:

> avrdude: stk500\_getsync(): not in sync: resp=0x00

*All* I want to do is just upload my program, but avr won't let me. He's even unintelligible, so can someone tell me what the heck he's trying to say and how to get rid of him?

---

i.e.:

Whenever I try to upload a program to my Arduino, I get this error message:

> avrdude: stk500\_getsync(): not in sync: resp=0x00

What does this mean, and how can I fix it?

# Answer
> 114 votes
This is caused by a generic connection error between your computer and the Arduino, and can result from many different specific problems.

Here are some easy things that can often fix this error:

* Disconnect and reconnect the USB cable.
* Press the reset button on the board.
* Restart the Arduino IDE.
* Make sure you select the right board in `Tools ► Board ►`, e.g. If you are using the Duemilanove 328, select that instead of Duemilanove 128. The board should say what version it is on the microchip.
* Make sure you selected the right port in `Tools ► Serial Port ►`. One way to figure out which port it is on is by following these steps:
    1. Disconnect the USB cable.
    2. Go to `Tools ► Serial Port ►` and see which ports are listed (e.g. COM4 COM5 COM14).
    3. Reconnect the USB cable.
    4. Go back to `Tools ► Serial Port ►`, and see which port appeared that wasn't there before.
* Make sure digital pins 0 and 1 do not have any parts connected, including any shields.

If none of those work, you will want to try to isolate the issue by replacing things: try a different computer on the same arduino, try a different arduino on the same computer, and try using a different USB cable.

If the issue is with the computer:

* Double-check all computer-related issues in the "easy fixes" list above.
* Reinstall the IDE.
* Reinstall the drivers.

If the issue is with the Arduino:

* Double-check all board-related issues in the "easy fixes" list above.
* Make sure the microcontroller is seated correctly.
* You may need to burn the bootloader.
* Replace the microcontroller if you have another one handy nearby.
* You may have bricked your Arduino. Sorry :(

# Answer
> 76 votes
Another fix:

Change `Tools->Processor->Atmega 328P` to `Atmega 328P (Old Bootloader)`. Remind that the `Processor` option is only available when you select some specific Boards at `Tools>Board`.

This worked for my Arduino Nano with CH340, using Arduino IDE 1.8.5 under Linux Ubuntu 17.10. Besides, this will probably happen if you use IDE 1.8.9 or newer and you get an old or cloned Nano.

# Answer
> 13 votes
Unfortunately, it can also mean that you burned your microcontroller. Were you doing anything dangerous right before you tried to upload a new sketch? Is the microcontroller still working, with its previously loaded sketch?

# Answer
> 12 votes
If none of the above steps work, try reinstalling Avrdude and the avr-gcc compiler. I had to do this after my Mega started suffering from this.

If you installed Avrdude and avr-gcc separately, simply uninstall them. if not, you may have to reinstall the Arduino IDE. These steps will depend on your operating system.

# Answer
> 12 votes
In my case I hadn't wired the RTS pin of the FTDI chip to a capacitor which went to the RST pin of the Arduino Pro Mini. Once I installed this connection, I no longer got the error and I was able to upload code.

Nick Gammon explains this in his forum. I've added a picture of where/how the capacitor should be placed.

# Answer
> 10 votes
I've had the same message. Every time it has been solved by selecting the right port ie USB under the menu Tools then Ports. Its a simple step but I always forget. I'll unplug the Arduino to stop the current program, plug it in again to my computer to upload the new program and get the error, panic, curse, and only then, remember.

# Answer
> 7 votes
I had the exact same problem. I tried installing the IDE in another laptop and uploaded the program from that laptop. Problem solved. Then I came back to my laptop, uninstalled the IDE and re-install it.. it started working.

However, I wasn't satisfied because I couldn't find the source of the problem... so I tried running everything again the same exact way... I found the problem but not sure if that can be the actual cause of it.

In my project, I needed to carry out serial communication between arduino and MATLAB (GUI). In order to see/verify the output(type) of MATLAB (GUI) serial data, I used HYPERTERMINAL and also VIRTUAL SERIAL PORT EMULATOR. I noticed that every time when when hyperterminal is running or VSPE is running while my serial monitor is on it screws up the uploading feature of the program. I'm not sure if it's because of the VSPE or HYPERTERMINAL, but reinstalling the IDE worked for me.

# Answer
> 6 votes
For people using Linux Mint I found that by selecting the "TTY SO" port instead of the one labeled "Arduino" it would work (I can't tell you exactly because I don't have that computer in front of me right now).

Then the next time I used the Arduino I again got the same message so I switched back to the "Arduino" port and it has worked that way ever since.

I am not as technically knowledgeable as the rest of you guys so I have no idea why this works or what the problem was, but it worked which is all I care about. Maybe this will be useful to someone.

# Answer
> 6 votes
I uninstalled the IDE and drivers etc, installed it all again, then I ran the Arduino IDE as an administrator and set to run compatibility as windows 7 (I'm currently using 10).

I also changed the programmer to AVR ISP (I don't think this matters, but I changed it anyway).

All is working again... hopefully, this can help someone else out too.

# Answer
> 4 votes
I had a similar issue with my Uno board

```
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x90

```

Tried many methods

* Press reset before sending packets
* different IDE versions
* Change cable
* Change controller itself
* Loopback test

but all of the above failed.

I use Ubuntu 16.04.4 LTS `4.15.0-33-generic` (while writing this comment). The CDC ACM module was not loaded, therefore no `/dev/ttyACM0` device was created to select in `Arduino IDE -> Tools -> Port`

Therefore, Get the module name and load it

```
$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 005: ID 2341:0043 Arduino SA Uno R3 (CDC ACM)
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

$ sudo modprobe cdc-acm

```

The above command will insert the required module. Now i'm able to select the right port and upload the code

Out of various solutions this worked for me, hope this helps someone too.

# Answer
> 3 votes
An unusual one but I've been swapping out the microcontrollers a lot and i got this error when one wasn't seated correctly.. i was able to burn a few times but i guess it slipped back out - a little push on the back of the ATMega328 fixed it!

# Answer
> 3 votes
I had this error come up too. It was the first time using a new Arduino Nano board after I had soldered on headers. Just tyring the Blink Sketch, nothing was connected to the board.

I found a tiny short of solder between the GROUND and RESET pins. I picked it off and then I could upload ok.

I suppose this might happen if you had the same short on a circuit somewhere.

# Answer
> 2 votes
There is also the possibility of the the controller itself being placed the wrong way in the socket on the Arduino. This can be dangerous for the controller (which may get zapped) but, in my case, it only gave the out of sync error, preventing me from uploading code.

So just check if the notch on the IC is in the right direction (you can cross check with images of board online). The notch on the Uno's controller should point towards edge of board.

# Answer
> 2 votes
Just had this same error with a brand new Mini Pro. Since the default blink program that came preloaded with most Arduino is running, I know that the unit is probably OK.

So I inspected the headers I just soldered one more time, and found that there was not enough solder on the TX0 pins. After re-soldering every works.

# Answer
> 2 votes
I solved it by updating the boards (under "board manager")

# Answer
> 1 votes
After lots of unplugging, checking ports, restarting IDE, etc. The ting which seemed to make a difference fixing this fault with Arduino Mega 2560 was to uninstall the windows USB arduino driver then reinstall it usig the driver here & select manually from the list\>com ports\>arduino http://drivers.softpedia.com/get/Other-DRIVERS-TOOLS/Others/Arduino-Mega-2560-USB-Driver-1110-for-Windows-7-64-bit.shtml I may have tested it on my uno then back to the mega so there's a small chance talking to the uno made AVRDUDE happy but unlikely.

# Answer
> 1 votes
When I get a problem uploading to my boards I upload a different program like the blink example. This seems to reset something and I am then able to upload my own program (which is quite large).

It might be worth trying this to see if it works in your case, although I have no idea why it works.

# Answer
> 1 votes
I faced the same problem for some code today and I solved it as follows:

1- First I ran a basic LED blinking code. It gave the same error. It confirms that the error is in uploading and has nothing to do with compiling. I also checked my code was compiling fine.

2- I took another board, but it was working fine on this PC. That means computer and the USB wire is OK.

3- I connected the faulty board to another PC, and surprisingly, there was no such error in uploading. That gave me hint about issues in driver in the first PC.

4- So I uninstalled the driver and re-installed it on the first PC by downloading from here

( make sure that while installing the driver from this link, you keep your board connected to the PC)

It worked fine now :-)

# Answer
> 1 votes
I had this error in my Linux Mint 17.3 laptop with Arduino Nano avrdude: stk500\_getsync(): not in sync: resp=0x00

Solved:

* removed all that had 'arduino' or 'avr' in its name
* removed directories .arduino and .arduino15 (Note the dot in the name)
* removed ver 1.8.7 with uninstall of the packet
* apt-get install arduino (ver 1.1.0)
* tested with a simple sketch (everything OK)
* installed ver 1.8.7 with the install of the packet
* compiled.
* selected ATmega328p(Old bootloader) for processor, Arduino Nano for card and /dev/ttyUSB0 for port =\> IT WORKS !

It seems that the 'Old bootloader' was the trick in this case. I have now both ver 1.1.0 an 1.8.7, who cares.

# Answer
> 1 votes
What I tried was to not connect one Ground of one board to the other ground on the other board. This stopped the problem for me.

# Answer
> 1 votes
If you use `arduino-cli` and a Arduino Nano clone, you can change the bootloader to the old one, as said in other answers, by using the following command to upload to the Arduino:

```
arduino-cli upload -v -p /dev/ttyUSB0 --fqbn arduino:avr:nano:cpu=atmega328old program_name

```

Explanation:

| command | explanation |
| --- | --- |
| `arduino-cli` | call `arduino-cli` |
| `-v` | Use verbose output |
| `-p /dev/ttyUSB0` | The port, use `arduino-cli board list` to find the right port |
| `--fqbn arduino:avr:nano:cpu=atmega328old` | Use avr board library, nano board and the Atmega328 CPU with the old bootloader |
| `program_name` | Replace this with the name of the program you want to upload |

---
Tags: uploading, avrdude, faq
---


# Question
Title: Trouble obtaining values from Nextion screen to Arduino
Currently I have a setup running an Arduino BME 280 sensor and a 4.3" Nextion screen. What my program does is sent all the calculated values from the BME to numbers and progress bars in my Nextion on a screen called "Run".

This page consists of 3 values: Delta T, Temperature and Humidity as well as 3 buttons for an alarm. Each of these displayed values is connected to their own progress bar. Each of the individual values has a lower and upper alarm setting which can be adjusted on a following Nextion screen called "Settings".

So basically what I am struggling with is obtaining the obtaining the values from my "settings" screen to write the "if" function in my Arduino i.e (if the button is enabled on the run page and the value is less than X on the "Settings" page or more than Y on the "Settings" page, sound the alarm).

I have used the .getValue function, but it does not return a value to my Arduino program. Can anyone please assist. It will be highly appreciated.

```
// Include required libraries
#include <NexTouch.h>
#include <NexDualStateButton.h>
#include <NexNumber.h>
#include <NexProgressBar.h>
#include <NexText.h>
#include <Nextion.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

//Define BME parameters
#define SEALEVELPRESSURE_HPA (1013.25)

Adafruit_BME280 bme; // I2C

//Define variables
int Delta_T;
int Temp_disp;
float Temp_wb;
float Temp;
int rh;

//Define NEXTION variables
//Transport Page
NexNumber Trans_deltaT = NexNumber(2, 10, "n0");
NexNumber Trans_T = NexNumber(2, 11, "n1");
NexNumber Trans_H = NexNumber(2, 12, "n2");

//Run Page
NexNumber Run_deltaT = NexNumber(3, 14, "n0");
NexNumber Run_T = NexNumber(3, 15, "n1");
NexNumber Run_H = NexNumber(3, 16, "n2");
NexDSButton Delta_Temp= NexDSButton(3, 12, "bt0");
NexDSButton Temperature= NexDSButton(3, 22, "bt1");
NexDSButton Hum= NexDSButton(3, 13, "bt2");

//Settings Page
NexNumber DT_min= NexNumber(4, 5, "n6");
NexNumber DT_max= NexNumber(4, 12, "n3");
NexNumber T_min= NexNumber(4, 6, "n7");
NexNumber T_max= NexNumber(4, 14, "n4");
NexNumber Hum_min= NexNumber(4, 7, "n8");
NexNumber Hum_max= NexNumber(4, 16, "n5");

NexTouch *nex_listen_list[] = {
  &Delta_Temp,
  &Temperature,
  &Hum,
  &Run_deltaT,
//  &DT_min,
//  &DT_max,
//  &T_min,
//  &T_max,
//  &Hum_min,
//  &Hum_max
    NULL
};

void Delta_TempPopCallback(void*ptr) {
  uint32_t DT = 0;          // Button State
  uint32_t DT_act = 0;
  uint32_t DelT_min = 0;    //Define DT_min setting
  uint32_t DelT_max = 0;    //Define DT_max setting

  DT_min.getValue(&DelT_min);
  DT_max.getValue(&DelT_max);
  Delta_Temp.getValue(&DT);
  Run_deltaT.getValue(&DT_act);

  Serial.println();
  Serial.println();
  Serial.println(DelT_min);

  // Read value of dual state button to know the state (0 or 1)

  if (DT == 0 && DT_act < DelT_min || DT_act > DelT_max) {  // If dual state button is equal to 1 (meaning is ON)...
    digitalWrite(2, HIGH);  // Turn ON internal LED
    Serial.println("ON");
  } else {                  // Since the dual state button is OFF...
    digitalWrite(2, LOW);   // Turn OFF internal LED
    Serial.println("OFF");
  }
}

void setup() {
  Serial.begin(9600);
  bme.begin();
  pinMode(2, OUTPUT);
  Delta_Temp.attachPop(Delta_TempPopCallback);
}

void loop() {
  Temp = bme.readTemperature();
  Temp_disp = Temp;
  // Serial.print("Temperature = ");
  // Serial.print(Temp);
  // Serial.println(" *C");

  rh=bme.readHumidity();
  // Serial.print("Humidity = ");
  // Serial.print(rh);
  // Serial.println(" %");

  Temp_wb = atan(0.151977 * pow(rh + 8.313659, 0.5)) * Temp + atan(Temp + rh) - atan(rh - 1.676331) + 0.00391838 * pow(rh, 1.5) * atan(0.023101 * rh) - 4.686035;
  // Serial.print("Wet Bulb Temp= ");
  // Serial.print(Temp_wb);
  // Serial.println(" *C");

  Delta_T=Temp-Temp_wb;
  // Serial.print("Delta T=");
  // Serial.print(Delta_T);
  // Serial.println(" *C");
  // Serial.println();

  Trans_deltaT.setValue(Delta_T);
  Trans_T.setValue(Temp_disp);
  Trans_H.setValue(rh);

  Run_deltaT.setValue(Delta_T);
  Run_T.setValue(Temp_disp);
  Run_H.setValue(rh);

  nexLoop(nex_listen_list);

  delay(50);
}

```

# Answer
I had to repeat the getvalue code multiple times, there seems to be a bug which a youtuber pointed out in his video. https://github.com/rvxfahim/AHU-Firmware/blob/main/development\_HMI.ino you can see from line 133, I called it so many times to be safe because it sometimes returned nothing or probably returned zero I don't remember it was a long time ago.
> 1 votes

---
Tags: serial, arduino-nano, tft
---