title: My program is using too much memory

text:
# Question
Title: My program is using too much memory
I work in a warehouse and I was tasked to make a device which will show the location of any product when Product ID is given. All of our product has 3 things. Product ID, Rack Number and Gap number.

So the basic program is like that When I enter Product ID: 1640 The program will show in display that it is located in RCK 113 GAP 88

For this I used Arduino Mega, 4x3 Keypad and 16x2 LCD Display with I2C adapter. I found a Arduino Keypad Calculator code on the Internet and modify my code from there. So currently my code is working fine and everything

What I noticed is Arduino mega has only 2% memory left with all that string value (For that I couldn't use Arduino Uno at first). Now due to new products are added I need more space or ways to store data elsewhere.

I can not use internet or WIFI as Another team has already made a device using ESP8266 Nodemcu which shows data from a Google sheet but since my device stores data in itself it is very fast (almost instant) to show any result on the other hand the device with NODEMCU ESP8266 can be easily updated and doesn't bother about size yet it is very slow to show result and needs good wifi connection so it is not efficient in warehouse environment. So every staff use my device on the go and other device as a backup

Currently I have around 1000 product address stored in my device but a new shipment of almost 3000 product is coming and my mega has only 2% memory left.

So any genius here can you help me to compress my program more ? or any fault I made during my coding ? Also this is my first post and sorry for my bad English.

My Code is given below. It is huge please take your time to understand it.

Even I can't copy my code here

Body is limited to 30000 characters; you entered 132142.

This is a sample of my code for you to understand

Here is full code uploaded. Download

**What I want to know is, if it is possible to add a Arduino SD card module and keep portion of my string memory in there.**

```
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>

const byte ROWS = 4;
const byte COLS = 4;
unsigned int integerValue=0;
//define the keymap
char keys [ROWS] [COLS] = {
  {'1', '2', '3', 'X'},
  {'4', '5', '6', '*'},
  {'7', '8', '9', '='},
  {'/', '0', '-', '+'}
};
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};

//create the keypad
Keypad myKeypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
LiquidCrystal_I2C lcd(0x27, 16, 2);

//variables declaration
boolean valOnePresent = false;
boolean result = false;
String num1;
int ans;
boolean getvalue = false;

void setup(){
  Serial.begin(9600);
  lcd.init(); // initialize the lcd
  lcd.backlight();
  frstscreen();
  //lcd.clear();

}

void loop(){
  char key = myKeypad.getKey();

  if (key != NO_KEY && (key=='1'||key=='2'||key=='3'||key=='4'||key=='5'||key=='6'||key=='7'||key=='8'||key=='9'||key=='0')){
      num1 = num1 + key;
      int numLength = num1.length();
      lcd.setCursor(15 - numLength, 1);
      lcd.print(num1);
      valOnePresent = true;
  }

  else if (valOnePresent == true && key != NO_KEY && key == '='){

      ans = num1.toInt();

      lcd.clear();
      lcd.setCursor(15,1);
      lcd.autoscroll();
      lcd.print(ans);
      lcd.noAutoscroll();
      result = true;

  }
  else if (key != NO_KEY && key == 'X'){
    lcd.clear();
    valOnePresent = false;
    num1 = "";
    frstscreen();
    getvalue = false;
}

    integerValue = ans;

if (result == true) {

if (integerValue ==  9   ) { IDScrn(); lcd.print("109");lcd.setCursor(12,1);lcd.print("63 "); delayfunc();}
if (integerValue == 15    ) { IDScrn(); lcd.print("107");lcd.setCursor(12,1);lcd.print("60 "); delayfunc();}
if (integerValue == 15    ) { IDScrn(); lcd.print("109");lcd.setCursor(12,1);lcd.print("63 "); delayfunc();}
if (integerValue == 20    ) { IDScrn(); lcd.print("109");lcd.setCursor(12,1);lcd.print("63 "); delayfunc();}
if (integerValue == 22    ) { IDScrn(); lcd.print("110");lcd.setCursor(12,1);lcd.print("68 "); delayfunc();}
if (integerValue == 23    ) { IDScrn(); lcd.print("109");lcd.setCursor(12,1);lcd.print("63 "); delayfunc();}

//TOP and components

if (integerValue ==  1001   ) { IDScrn(); lcd.print("RCK 115 COL A                  "); delayfunc();}
if (integerValue == 1002   ) { IDScrn(); lcd.print("RCK 115 COL A                  "); delayfunc();}
if (integerValue == 1003   ) { IDScrn(); lcd.print("RCK 115 COL A                  "); delayfunc();}

//Stock and CBOX

if (integerValue ==   376    ) { ComScrn(); lcd.print(" Stock Box 1"); delayfunc();}
if (integerValue ==   15     ) { ComScrn(); lcd.print(" Stock Box 1"); delayfunc();}
if (integerValue ==   919    ) { ComScrn(); lcd.print(" Stock Box 1"); delayfunc();}

//CBOX

if (integerValue ==   245    ) { ComScrn(); lcd.print(" 39K COL I "); delayfunc();}
if (integerValue ==   245    ) { ComScrn(); lcd.print(" 10K COL I "); delayfunc();}
if (integerValue ==   245    ) { ComScrn(); lcd.print(" 47k COL I "); delayfunc();}
if (integerValue ==   245    ) { ComScrn(); lcd.print(" 1k  COL I "); delayfunc();}
if (integerValue ==   245    ) { ComScrn(); lcd.print(" 2k  COL I "); delayfunc();}
if (integerValue ==   245    ) { ComScrn(); lcd.print(" 4.7k  COL I "); delayfunc();}
if (integerValue ==   245    ) { ComScrn(); lcd.print(" 27k COL I "); delayfunc();}
if (integerValue ==   766    ) { ComScrn(); lcd.print(" 0 ohm   COL I "); delayfunc();}
if (integerValue ==   766    ) { ComScrn(); lcd.print(" 220 ohm COL I "); delayfunc();}
if (integerValue ==   766    ) { ComScrn(); lcd.print(" 560 ohm COL I "); delayfunc();}
if (integerValue ==   766    ) { ComScrn(); lcd.print(" 470 ohm COL I "); delayfunc();}
if (integerValue ==   766    ) { ComScrn(); lcd.print(" 330 ohm COL I "); delayfunc();}
if (integerValue ==   766    ) { ComScrn(); lcd.print(" 100 ohm COL I "); delayfunc();}
if (integerValue ==   1291     ) { ComScrn(); lcd.print(" Cbox 1  GAP 101 "); delayfunc();}
if (integerValue ==   1314     ) { ComScrn(); lcd.print(" Cbox 1  GAP 101 "); delayfunc();}

if (getvalue == false) { noproduct(); }

}
 }
void frstscreen()
{
  lcd1stline();
  lcd.print("Warehouse Stock");
  lcd.setCursor(0,1);
  lcd.print("Enter ID: ");
}
void pressA(){

  lcd.clear();
  lcd.setCursor(0,1);
  lcd.print("Press A again");
}
void noproduct(){

  lcd1stline();
  lcd.print("Not Found");
  lcd.setCursor(0,1);
  lcd.print("Press A again");
  result= false;
}
void delayfunc(){
  result = false;
  delay (2000);
  pressA();
  getvalue = true;

}
void lcd1stline(){
lcd.clear();
lcd.setCursor(0,0);
}
void IDScrn(){
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("ID: ");
  lcd.setCursor(4,0);
  lcd.print(integerValue);
  lcd.setCursor(0,1);
  lcd.print("RCK     GAP");
  lcd.setCursor(4,1);
}

void ComScrn(){
    lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("ID: ");
  lcd.setCursor(4,0);
  lcd.print(integerValue);
  lcd.setCursor(1,1);
}

```

# Answer
There are lots of repetitions in your code. This is something you should generally avoid, not only because of memory usage, but also, and most importantly, because of maintainability.

The most common way of getting rid of repetitions is to write a loop that walks through an array. For the first part of your program (the rack/gap scheme), that array could look like this:

```
// Data structure describing a recorded location.
struct Location {
    uint16_t id;
    uint8_t rack;
    uint8_t gap;
};

// List of recorded product locations.
const Location locations[] = {
    {  9, 109, 63 },
    { 15, 109, 63 },
    { 20, 109, 63 },
    { 22, 110, 68 },
    { 23, 109, 63 },
    // etc...
};

// Number of items in the above list.
const size_t nb_locations = sizeof locations / sizeof locations[0];

```

Note that the structure uses the smallest possible integers for each field, in order to save memory. The main benefit, however, is that the data is now in a format that is easier to update: a simple list of numbers.

Then, all the code that handles this data becomes a loop, instead of a repetition. For example, the following function can print the location of any item on the LCD. It returns `true` or `false` to let you know whether it did find the requested item:

```
// If the item is found, print its location and return true.
// Otherwise return false.
bool print_location(uint16_t id) {
    for (size_t i = 0; i < nb_locations; i++) {
        if (locations[i].id == id) {
            IDScrn();
            lcd.print(locations[i].rack);
            lcd.setCursor(12,1);
            lcd.print(locations[i].gap);
            delayfunc();
            return true;  // found
        }
    }
    return false;  // not found
}

```

This scheme still has the problem that all the data is copied to RAM at initialization. If you have 4,000 items, that would require 16,000 bytes of RAM, or about twice the RAM of your Mega. You can save RAM by keeping all constant data in flash, using the `PROGMEM` qualifier. You have 32 times more flash than RAM. You would then need, however, to bring each item back to RAM in order to use it, which can be done with the `memcpy_P()` function. Here is a version of the previous code that stores the array in flash:

```
// List of recorded product locations.
PROGMEM const Location locations[] = {
    {  9, 109, 63 },
    { 15, 109, 63 },
    { 20, 109, 63 },
    { 22, 110, 68 },
    { 23, 109, 63 },
    // etc...
};

// Number of items in the above list.
const size_t nb_locations = sizeof locations / sizeof locations[0];

// If the item is found, print its location and return true.
// Otherwise return false.
bool print_location(uint16_t id) {
    for (size_t i = 0; i < nb_locations; i++) {
        Location location;  // RAM copy of locations[i]
        memcpy_P(&location, &locations[i], sizeof location);
        if (location.id == id) {
            IDScrn();
            lcd.print(location.rack);
            lcd.setCursor(12,1);
            lcd.print(location.gap);
            delayfunc();
            return true;  // found
        }
    }
    return false;  // not found
}

```

This approach should enable you to store all the database in the flash of your Mega, and maybe even on an Uno. That being said, I second the commenters that say that using an SD card should make upgrading the database a lot more convenient.
> 9 votes

# Answer
Did you try using the (PROGMEM) `F` macro. It is described in the official Arduino documentation at the end of https://www.arduino.cc/reference/en/language/variables/utilities/progmem/

This forces all strings to be stored in Flash memory instead of the scarce SRAM memory.

You can try with a few strings to see if the memory lowers and calculate if it would be enough (to fit in Flash). If even Flash is not enough, than SD card would be an alternative.

Also some refactorings that might clean up the code (not necessarily reduce the memory used):

* instead of the many `if (integerValue == xxx)` constructs, use `switch`/`case` statements.
* A possible bug are the identical values within (like 245 and 766 used many times, but for different products)
* Move the function lcd.print("...") inside function `ComScrn` and pass the string (using `F(..)`)
* Similar as above but for `IDScrn`, using two strings and set the cursor inside `IDScrn` as well.
* `(key != NO_KEY && key == 'X')` ... if `key` is `'X'` it can never be NO\_KEY so the first check can be removed.
* `if (result == true)` can be written as `if (result)`.
> 1 votes

# Answer
***What I want to know is, if it is possible to add a Arduino SD card module and keep portion of my string memory in there***

Well, given that two contributors have already gave a handful of advices to both improving your code and the benefits of using an SD card. I find nothing else to say except answering your very specific question.

The answer is simple, and it is a yes. There is no problem in dividing your data into two parts, one part on your microcontroller/Arduino and the other part on your SD card, you will have to know which part is where so you can access it without any problems and almost instantly as well.

I hope that answers your question fully.
> 0 votes

# Answer
The Arduino Uno uses a rather old, weak processor. It is still a perfectly cromulent microcontroller - it does just fine - but much newer ones do exist.

You mentioned the ESP8266. Did you know it has 40kB of RAM compared to the Uno's 2kB? And the successor, the ESP32, has 320kB of RAM.

Since your application is basically a miniature computer, with a keyboard and screen, have you considered using something that's designed as a miniature computer? A Raspberry Pi (any model) has more gigabytes of RAM than you know what to do with. But it does use a lot more power. But you can also write the software in a normal Linux way (if you happen to like Linux programming). Or, you could consider writing an app for your Android cellphone.

If you insist on using the Uno, another option is to add an SPI RAM expansion chip, for example this 1-euro chip with 32kB (they do go bigger). Now, the Uno has *no* built-in RAM expansion ability, so you can't just access it with pointers or something, but you can still use the SPI bus to tell the chip to read or write certain bytes, kinda like you can with an SD card.

After writing this, I realized SPI RAM is not so useful for your application, because you don't want to store the data only while the device is turned on. You could use a SPI FRAM or SPI EEPROM chip instead which can store data while it's powered off. The Arduino IDE doesn't have a way to automatically put data into any of these chips... so to input the data you'd probably have to send it over the serial port, into a separate program you wrote, which writes it to the chip. Or you could make a user interface that allows the user to edit the data directly on the device.

Or you can use an SD card, yes. Honestly that's probably the simplest way.
> -1 votes

---
Tags: arduino-uno, arduino-mega, display, keypad
---


# Question
Title: NodeMCU ESP8266 Ver 0.1 not powering on with VIN
I'm trying to power on my NodeMCU ESP8266 Ver 0.1 (thats what is written in board), via VIN and Ground with my phone charger.

I'm 100% sure that the USB charger is working, providing 5V, and that the ground and VIN are connected to the right positions.

If I use the same phone charger via the NodeMCU USB, the program blinks the builtin led alright.

If I power via VIN, it flashes when I connect the charger to DC, but the program does not work. It seems as the NodeMCU is not powering on complety.

Bizarrely, if I short 3V and G pins, the board starts working normally as powered directly via USB port.

This is the code

```
/*
 ESP8266 Blink by Simon Peter
 Blink the blue LED on the ESP-01 module
 This example code is in the public domain

 The blue LED on the ESP-01 module is connected to GPIO1
 (which is also the TXD pin; so we cannot use Serial.print() at the same time)

 Note that this sketch uses LED_BUILTIN to find the pin with the internal LED
*/

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);     // Initialize the LED_BUILTIN pin as an output
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, LOW);   // Turn the LED on (Note that LOW is the voltage level
                                    // but actually the LED is on; this is because
                                    // it is acive low on the ESP-01)
  delay(1000);                      // Wait for a second
  digitalWrite(LED_BUILTIN, HIGH);  // Turn the LED off by making the voltage HIGH
  delay(2000);                      // Wait for two seconds (to demonstrate the active low LED)
}

```

Just as a follow up: I've never solved the problem in this specific board, so I ended up buying a newer one which works fine.

# Answer
> 1 votes
I faced the same issue. My problem was on this version of board both ground (G) pins on the side of Vin pin (I say left side of the board when usb is towards bottom direction) do not have connection with the ground of the 3.3v regulator or to the Gnd pin on right side of the board !! No continuity from ground pin to regulator is the problem I understood. The moment I connected 5v between Vin and Right side 'G' pin it started working. Check and try if not resolved yet.

# Answer
> -1 votes
Interesting problem. The input range for Vin is 5.5 to 10 volts. This link will give you more information: https://www.make-it.ca/nodemcu-arduino/nodemcu-details-specifications/ I would not venture to guess that your board is OK, since you short pins all kinds of nasties can happen. Also you do not state your reference point for your voltage measurements so I assume it is ground but the readings do not appear correct. How are you 100% sure that the USB charger is working, providing 5V, and that the ground and VIN are connected to the right positions. Did you measure it with the load connected? Can the charger output the voltage at the current you require?

---
Tags: power, nodemcu
---


# Question
Title: Where is the Arduino IDE boards.txt file for Nano Every located?
My Arduino Nano Every runs at 16Mhz (but the 4809 can support internal 20Mhz).
I know it may be possible to alter the boards.txt file and set it to build for 20Mhz. However, I can't find the boards.txt for these new boards (MegaAVR). Where is the boards.txt located?

# Answer
> 0 votes
I found the boards.txt file at: `~/.arduino15/packages/arduino/hardware/megaavr/1.8.7`

The Nano Every portion of the boards.txt looks like the following:

```
##############################################################

nona4809.name=Arduino Nano Every

nona4809.vid.0=0x2341
nona4809.pid.0=0x0058

nona4809.upload.tool=avrdude
nona4809.upload.protocol=jtag2updi
nona4809.upload.maximum_size=49152
nona4809.upload.maximum_data_size=6144
nona4809.upload.speed=115200
nona4809.upload.use_1200bps_touch=true
nona4809.upload.extra_params=-P{serial.port}

nona4809.build.mcu=atmega4809
nona4809.build.f_cpu=16000000L
nona4809.build.board=AVR_NANO_EVERY
nona4809.build.core=arduino
nona4809.build.variant=nona4809
nona4809.build.text_section_start=.text=0x0
nona4809.build.extra_flags={build.328emulation} -DMILLIS_USE_TIMERB3 -DNO_EXTERNAL_I2C_PULLUP
#nona4809.build.extra_flags=-B{runtime.tools.atpack.path}/gcc/dev/{build.mcu}

nona4809.bootloader.tool=avrdude
nona4809.bootloader.file=atmega4809_uart_bl.hex
nona4809.bootloader.SYSCFG0=0xC9
nona4809.bootloader.BOOTEND=0x00
nona4809.bootloader.OSCCFG=0x01
nona4809.fuses.file=fuses_4809.bin

menu.mode=Registers emulation
nona4809.menu.mode.on=ATMEGA328
nona4809.menu.mode.on.build.328emulation=-DAVR_NANO_4809_328MODE
nona4809.menu.mode.off=None (ATMEGA4809)
nona4809.menu.mode.off.build.328emulation=

##############################################################

```

If you change the following line from:

```
nona4809.build.f_cpu=16000000L

```

to:

```
nona4809.build.f_cpu=20000000L

```

Then go in and turn on verbose when you build in the Arduino IDE you will see that avrdude will pass in the following when it builds your sketch:

```
DF_CPU=20000000L

```

Will this push the CPU to 20Mhz? Not sure, but at least you know where this is now.

**UPDATE**

**FYI** \- Do not set your board to 20Mhz. Especially if you have Serial Communication going on. I have software serial set up to communicate with an attached bluetooth device and when you set the CPU to 20Mhz other things are not set properly and the Serial communication fails.

# Answer
> 2 votes
In addition to set the

```
nona4809.build.f_cpu=20000000L

```

you will have to set the corresponding fuse byte to

```
nona4809.bootloader.OSCCFG=0x02

```

this enables the 20 MHz clock.

---
Tags: arduino-ide, atmega, arduino-nano-every
---


title: Rp2040 dual core example sketches

text:
# Question
Title: Rp2040 dual core example sketches
So i have a rp2040 board, and i could not find a dual core example codes. The closest i could find is the scheduler library example given to me by the IDE

```
/*
 Multiple Blinks

 Demonstrates the use of the Scheduler library for the boards:

 - Arduino Nano 33 BLE, or
 - Arduino Portenta H7, or
 - Arduino Nano RP2040 Connect

 Hardware required :
 * None (LEDs are already conencted to RGB LED)

 ATTENTION: LEDs polarity is reversed (so loop3 will turn the LED off by writing 1)

 created 8 Oct 2012
 by Cristian Maglie
 Modified by
 Scott Fitzgerald 19 Oct 2012

 This example code is in the public domain

 http://www.arduino.cc/en/Tutorial/MultipleBlinks
*/

// Include Scheduler since we want to manage multiple tasks.
#include <Scheduler.h>

// On Nano RP2040 Connect, RGB leds are connected to the wifi module
// The user APIs are the same, but we can't convert to int, so use defines
#if defined(ARDUINO_NANO_RP2040_CONNECT)

#include "WiFiNINA.h"
#define led1  LEDR
#define led2  LEDG
#define led3  LEDB

// On Nicla Sense ME, RGB leds are connected via an I2C module
// The user APIs are the same, but we can't convert to int, so use defines
#elif defined(ARDUINO_NICLA)

#include "Nicla_System.h"
#define led1  LEDR
#define led2  LEDG
#define led3  LEDB

#else

int led1 = LEDR;
int led2 = LEDG;
int led3 = LEDB;

#endif

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

  // Setup the 3 pins as OUTPUT
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);

  // Add "loop2" and "loop3" to scheduling.
  // "loop" is always started by default.
  Scheduler.startLoop(loop2);
  Scheduler.startLoop(loop3);
}

// Task no.1: blink LED with 1 second delay.
void loop() {
  digitalWrite(led1, HIGH);

  // IMPORTANT:
  // When multiple tasks are running 'delay' passes control to
  // other tasks while waiting and guarantees they get executed.
  delay(1000);

  digitalWrite(led1, LOW);
  delay(1000);
}

// Task no.2: blink LED with 0.1 second delay.
void loop2() {
  digitalWrite(led2, HIGH);
  delay(100);
  digitalWrite(led2, LOW);
  delay(100);
}

// Task no.3: accept commands from Serial port
// '0' turns off LED
// '1' turns on LED
void loop3() {
  if (Serial.available()) {
    char c = Serial.read();
    if (c == '0') {
      digitalWrite(led3, LOW);
      Serial.println("Led turned off!");
    }
    if (c == '1') {
      digitalWrite(led3, HIGH);
      Serial.println("Led turned on!");
    }
  }

  // IMPORTANT:
  // We must call 'yield' at a regular basis to pass
  // control to other tasks.
  yield();
}

```

but i do not think its using the second core of the rp2040. Does anybody have an example codes? because im really lost how to do it

# Answer
**Note: This information is about the pure "Arduino" core, not the "MBED" core. The MBED core gets in the way of using the RP2040 SDK, so install the pure bare metal core from here.**

By default the second core isn't doing anything.

But you can run anything you want on it directly. No need for any libraries. You use the function `multicore_launch_core1(func)` to start a function on that core. You could make it Arduino-like by writing a wrapper function, such as this code:

```

void setup2() {
    pinMode(1, OUTPUT);
}

void loop2() {
    digitalWrite(1, HIGH);
    delay(750);
    digitalWrite(1, LOW);
    delay(750);
}

void main2() {
    setup2();
    while (1) {
        loop2();
    }
}

void setup() {
    multicore_launch_core1(main2);
    pinMode(0, OUTPUT);
}

void loop() {
    digitalWrite(0, HIGH);
    delay(1000);
    digitalWrite(0, LOW);
    delay(1000);
}

```
> 3 votes

---
Tags: arduino-nano-rp2040
---


# Question
Title: Why can't I just plug a stepper or gimbal motor (BLDC) into the ground, 5v, and analog pins of my Arduino?
I plugged a BLDC gimbal motor in to my Arduino today, and it made a very small jitter. I tried to set an analog pin for the signal pin of the motor (motor had three pins, I assumed one was power, one was ground, and one was signal/data/position) but the motor barely moved. I wanted to see my motor spin at some constant rate determined by that signal pin, or maybe move to the position specified in the signal pin.

Upon further research, I find many pages advising me to use "controllers" or other complicated setups to manage a motor. I am confused as to why it is so complicated. Can't it be simple to plug a stepper motor into an Arduino and get some constant revolutions based on Arduino control?

# Answer
Not only is the available current limited, but a stepper motor in particular is not capable of running just by supplying power.

It's drive coils must be energized in sequence to "pull" the rotor around, and sequenced at a rate that drives the rotor at the desired RMP. The circuitry to do that is external to the stepper, usually a combination of logic signals from a micro-controller (typically) and hardware to translate those signals into drive currents sequenced to the stator-coils. This is what makes steppers so flexible - controllable in direction and speed, down to the single-step level (subject to the rotor's interia) - at the cost of more complex drive circuitry. In short, steppers need to be programmed, continuously, to drive them however the mechanical system requires.
> 1 votes

# Answer
It is a power issue. By that I mean `Power = Votage x Current`.

Put simply, the 5V supply regulator IC on the Arduino is only designed to power the microcontroller(s) and a handful of other electronic components.

The Arduino has a little 5V regulator that is capable of delivering 100mA to 500mA depending on your Arduino. Don't forget that the microcontroller itself uses roughly 20mA. The remaining current is capable of runing very low power items such as sensors, switches, LEDs etc but not parts that require more power. Unfortunately motors require a lot more power than what the regulator on the Arduino can provide.

I suggest that you use a second 5V supply. For example you could use:

* Benchtop power supply
* Plugpack or phone charger type power supply
* An old computer power supply
* A DC/DC converter (like this one)

These are just a few. There are many more options.
> 0 votes

# Answer
A brushless DC motor consists of three coils of wire wired in a Y (wye) or Δ (delta) configuration and a magnetic rotor. The coils are evenly spaced around the 360 degrees of the motor. There can be multiple poles, or "copies" of each coil, so it's not necessarily 120 degrees from a coil A to a coil B - e.g. it could be ABCABCABC to go around the full circle with 40 degrees between coils. There are no power or ground or data wires, just electromagnets.

Anyway, when current goes through one of the coils it forms an electromagnet and attracts the rotor to that position. We say the coil is energized. By repeatedly energizing and de-energizing different coils you make the rotor spin around in circles. If you energize A, then B, then C, then A, then B, then C it spins one way; energize C, then B, then A, then C, then B, then A and it spins the other way. The current direction also matters because an opposite current produces an opposite magnetic field. Of course you also have to get the timing right - so the magnetic force is always pulling the rotor *ahead* of where it currently is. When the rotor catches up with the magnet coil you switch to the next one. I'm oversimplifying.

To use one you can buy a controller which *does* have power and data and ground wires, as well as the 3 wires for the magnets, and you tell the controller to go, and it handles all the switching and timing for you. You could design your own, but good luck.

---

Steppers are the same basic idea but optimized for low speed and precise movements instead of big movements. Because you don't care about timing so much for a stepper - you're moving it one step at a time and not really trying to use its inertia - you *can* write your own control algorithm if you want. Note the Arduino's digital pins still can't output enough current so you still need some circuitry. Or you can buy a stepper motor controller.
> 0 votes

---
Tags: motor, stepper
---


# Question
Title: Arduino Uno R3 stops executing code, when trying to instantiate multiple HX711 objects
This is my first time asking something on this platform, so if form or anything else is off, please feel free to point out things about how I could refine it and ask more concisely in the future.

I'm trying to develop an orthosis, which uses 4 load cells (full-bridge type) and 4 HX711 load cell amplifiers to inform patients via an app when they exceed their prescribed weight limit.

I have test code to calibrate the load cells and the code for the project itself. On the same Arduino, with the same components connected the test code, which only instantiates 4 HX711 objects and reads them after calibration, works fine. The full-blown project code uses exactly the same lines as well as the same hardware setup, but after the 2nd HX711 is instantiated I get no further Serial output and for all I can tell without a debugging jig, it looks like the Arduino stops executing code. If I try running the project code with only two HX711 objects (leaving the others physically connected, but commenting out the respective lines) the code works just fine.

So far I tried measuring RAM consumption, the Arduino should have 2048 bytes available, of which my project code seems to use 1483 bytes. My sensor test code uses 276 bytes, which means that technically I shouldn't be able to run out of memory. I also tried using another Arduino as a power source for the HX711 modules, just in case that the entire setup is asking for too much from a single Arduino - had no luck with that either. I would be really thankful for any pointers in the right direction since I can't figure it out on my own.

I'm using the following library for my HX711 modules: https://github.com/bogde/HX711

Project code (stops working after line 126):

```
#include <SoftwareSerial.h>
#include <SPI.h>
#include <SD.h>
#include "DHT.h"
#include "RTClib.h"
#include "HX711.h"

#define DHTPIN (uint8_t) 8
#define DHTTYPE DHT11
#define LED (uint8_t) 5
#define BUZZER (uint8_t) 9
#define BAUD 9600
#define NUM_CHARS (byte) 32
#define CHIP_SELECT (uint8_t) 10
#define SENSOR1_DATA (uint8_t) A0
#define SENSOR2_DATA (uint8_t) A2
#define SENSOR3_DATA (uint8_t) A4
#define SENSOR4_DATA (uint8_t) 7
#define SENSOR1_SCK (uint8_t) A1
#define SENSOR2_SCK (uint8_t) A3
#define SENSOR3_SCK (uint8_t) A5
#define SENSOR4_SCK (uint8_t) 6
#define TEST_DURATION 3000
#define NOT_CONNECTED 0
#define LIVE_VIEW 1
#define SETTINGS 2

// Constants
const int CHAR_SIZE = sizeof(char);

// Hardware interface settings
SoftwareSerial btSerial(2, 3);
RTC_DS1307 rtc;
DHT dht(DHTPIN, DHTTYPE);

HX711 SENSOR1;
HX711 SENSOR2;
HX711 SENSOR3;
HX711 SENSOR4;

// Hardware status & settings
boolean ledEnabled = true;
boolean isLedOn = false;
boolean buzzerEnabled = true;
boolean isBuzzerOn = false;
boolean error = false;

float threshold1 = 0.0f;
float threshold2 = 0.0f;
float threshold3 = 0.0f;
float threshold4 = 0.0f;

// Hardware testing
boolean ledTestinProgress = false;
unsigned long ledTestStart = 0;
boolean buzzerTestinProgress = false;
unsigned long buzzerTestStart = 0;

// Modes
int8_t mode = 0;

// Bluetooth
char data[NUM_CHARS];
boolean newData = false;

void receive();
void processMessage();
void testLED();
void testBuzzer();
void loadSettings();
void saveSettings();

extern void* __bss_end;
extern void* __brkval;

int get_free_memory()
{
  int free_memory;

  if((int)__brkval == 0)
    free_memory = ((int)&free_memory) - ((int)&__bss_end);
  else
    free_memory = ((int)&free_memory) - ((int)__brkval);

  return free_memory;
}

void setup() {
    pinMode(LED, OUTPUT);
    pinMode(BUZZER, OUTPUT);
    Serial.begin(BAUD);
    rtc.begin();
    if (!SD.begin(CHIP_SELECT)) {
        Serial.println(F("ERROR: SD init failed."));
        error = true;
    } else {
        loadSettings();

        Serial.println(F("SD initialized."));
        Serial.println(F("Settings: "));
        Serial.print(F("LED: "));
        Serial.println(ledEnabled);
        Serial.print(F("Buzzer: "));
        Serial.println(buzzerEnabled);
        Serial.print(F("Threshold 1: "));
        Serial.println(threshold1);
        Serial.print(F("Threshold 2: "));
        Serial.println(threshold2);
        Serial.print(F("Threshold 3: "));
        Serial.println(threshold3);
        Serial.print(F("Threshold 4: "));
        Serial.println(threshold4);

    }

    dht.begin();

    SENSOR1.begin(SENSOR1_DATA, SENSOR1_SCK);
    SENSOR1.set_scale(-63.f);
    SENSOR1.tare();
    Serial.println(F("Sensor 1 initialized."));

    SENSOR2.begin(SENSOR2_DATA, SENSOR2_SCK);
    SENSOR2.set_scale(-58.f);
    SENSOR2.tare();
    Serial.println(F("Sensor 2 initialized."));

    SENSOR3.begin(SENSOR3_DATA, SENSOR3_SCK);
    SENSOR3.set_scale(-50.f);
    SENSOR3.tare();
    Serial.println(F("Sensor 3 initialized."));

    SENSOR4.begin(SENSOR4_DATA, SENSOR4_SCK);
    SENSOR4.set_scale(-46.f);
    SENSOR4.tare();
    Serial.println(F("Sensor 4 initialized."));

    btSerial.begin(BAUD);
}

void loop() {
    if (!error) {
        receive();
        processMessage();

        DateTime now = rtc.now();
        float sensor1 = SENSOR1.get_units() / 1000;
        float sensor2 = SENSOR2.get_units() / 1000;
        float sensor3 = SENSOR3.get_units() / 1000;
        float sensor4 = SENSOR4.get_units() / 1000;

        Serial.print(F("Sensor 1: "));
        Serial.println(sensor1);
        Serial.print(F("Sensor 2: "));
        Serial.println(sensor2);
        Serial.print(F("Sensor 3: "));
        Serial.println(sensor3);
        Serial.print(F("Sensor 4: "));
        Serial.println(sensor4);

        if (isnan(sensor1) || isnan(sensor2) || isnan(sensor3) || isnan(sensor4)) return;

        if (!buzzerTestinProgress && !ledTestinProgress) {
            if (threshold1 > 0 && sensor1 > threshold1 ||
                threshold2 > 0 && sensor2 > threshold2 ||
                threshold3 > 0 && sensor3 > threshold3 ||
                threshold4 > 0 && sensor4 > threshold4) {
                if (buzzerEnabled)
                {
                    tone(BUZZER, 1000);
                    isBuzzerOn = true;
                }
                if (ledEnabled) {
                    digitalWrite(LED, HIGH);
                    isLedOn = true;
                }
            } else {
                if (isBuzzerOn) {
                    noTone(BUZZER);
                    isBuzzerOn = false;
                }

                if (isLedOn) {
                    digitalWrite(LED, LOW);
                    isLedOn = false;
                }
            }
        }

        if (mode == LIVE_VIEW) {
            btSerial.print(F("<"));
            btSerial.print(F("M;"));
            btSerial.print(now.unixtime());
            btSerial.print(F(";"));
            if (threshold1 > -1.0f) btSerial.print(sensor1);
            else btSerial.print(-1.0f);
            btSerial.print(F(";"));
            if (threshold2 > -1.0f) btSerial.print(sensor2);
            else btSerial.print(-1.0f);
            btSerial.print(F(";"));
            if (threshold3 > -1.0f) btSerial.print(sensor3);
            else btSerial.print(-1.0f);
            btSerial.print(F(";"));
            if (threshold4 > -1.0f) btSerial.print(sensor4);
            else btSerial.print(-1.0f);
            btSerial.println(F(">"));
        }

        if (ledTestinProgress && ((millis() - ledTestStart >= TEST_DURATION))) {
            ledTestStart = 0;
            ledTestinProgress = false;
            digitalWrite(LED, LOW);
        }

        if (buzzerTestinProgress && ((millis() - buzzerTestStart >= TEST_DURATION))) {
            buzzerTestStart = 0;
            buzzerTestinProgress = false;
            noTone(BUZZER);
        }

        delay(250);
    } else {
        tone(BUZZER, 1000);
        digitalWrite(LED, HIGH);
        delay(1000);
        noTone(BUZZER);
        digitalWrite(LED, LOW);
        delay(1000);
    }

    Serial.print(F("Free RAM: "));
    Serial.println(get_free_memory());
}

// Receive a Bluetooth message from the companion app
// Valid messages are encapsulated within '<' and '>' to ensure that the whole message is received.
void receive() {
    static boolean receiving = false;
    static byte index = 0;
    char startMarker = '<';
    char endMarker = '>';
    char rc;

    while (btSerial.available() > 0 && !newData) {
        rc = btSerial.read();
        delay(10);

        if (receiving) {
            if (rc != endMarker) {
                data[index] = rc;
                index++;

                if (index >= NUM_CHARS) {
                    index = NUM_CHARS - 1;
                }
            } else {
                data[index] = '\0';
                receiving = false;
                index = 0;
                newData = true;
            }
        } else if (rc == startMarker) {
            receiving = true;
        }
    }
}

// Processes a received message based on length and content
void processMessage() {
    if (newData) {
        int dataLength = strlen(data);

        Serial.println(data);

        if (dataLength == 1) {
            switch (data[0]) {
                case 'l': mode = LIVE_VIEW;
                break;
                case 's': {
                    mode = SETTINGS;
                    btSerial.print(F("<S;"));
                    btSerial.print(ledEnabled);
                    btSerial.print(F(";"));
                    btSerial.print(buzzerEnabled);
                    btSerial.print(F(";"));
                    btSerial.print(threshold1);
                    btSerial.print(F(";"));
                    btSerial.print(threshold2);
                    btSerial.print(F(";"));
                    btSerial.print(threshold3);
                    btSerial.print(F(";"));
                    btSerial.print(threshold4);
                    btSerial.println(F(">"));
                }
                break;
                case 'H': btSerial.println(F("<W>"));
            }
        } else if (dataLength == 2) {
            if (strcmp(data, "LT") == 0) testLED();
            if (strcmp(data, "BT") == 0) testBuzzer();
        } else {
            char* token = strtok(data, ";");
            int count = 0;

            if (strcmp(token, "S") == 0) {
                while (token != NULL) {
                    token = strtok(NULL, ";");
                    if (count == 0) ledEnabled = atoi(token);
                    if (count == 1) buzzerEnabled = atoi(token);
                    if (count == 2) threshold1 = atof(token);
                    if (count == 3) threshold2 = atof(token);
                    if (count == 4) threshold3 = atof(token);
                    if (count == 5) threshold4 = atof(token);
                    count++;
                }

                saveSettings();
            }
        }

        newData = false;
    }
}

// Initiate an LED test
void testLED() {
    ledTestStart = millis();
    ledTestinProgress = true;
    digitalWrite(LED, HIGH);
}

// Initiate a buzzer test
void testBuzzer() {
    buzzerTestStart = millis();
    buzzerTestinProgress = true;
    tone(BUZZER, 1000);
}

// Load settings from SD card
void loadSettings() {
    File settingsFile = SD.open("settings.txt", FILE_READ);

    if (settingsFile) {

        char settings[10];
        int index = 0;

        while (settingsFile.available()) {
            settings[index] = settingsFile.read();
            index++;
        }

        settingsFile.close();
        settings[index] = '\0';

        int count = 0;

        char* token = strtok(settings, ";");
        ledEnabled = atoi(token);

        while (token != NULL) {
            token = strtok(NULL, ";");
            if (count == 0) buzzerEnabled = atoi(token);
            if (count == 1) threshold1 = atof(token);
            if (count == 2) threshold2 = atof(token);
            if (count == 3) threshold3 = atof(token);
            if (count == 4) threshold4 = atof(token);
            count++;
        }
    } else {
        Serial.println(F("ERROR: Reading settings failed."));
        error = true;
    }
}

// Save settings to SD card
void saveSettings() {
    SD.remove("settings.txt");

    File settingsFile = SD.open("settings.txt", FILE_WRITE);
    if (settingsFile) {
        settingsFile.print(ledEnabled);
        settingsFile.print(";");
        settingsFile.print(buzzerEnabled);
        settingsFile.print(";");
        settingsFile.print(threshold1);
        settingsFile.print(";");
        settingsFile.print(threshold2);
        settingsFile.print(";");
        settingsFile.print(threshold3);
        settingsFile.print(";");
        settingsFile.print(threshold4);
        settingsFile.println(";");

        settingsFile.close();
    } else {
        Serial.println(F("ERROR: Saving settings failed."));
        error = true;
    }
}

```

Sensor test code (working flawlessly with the same hardware setup):

```
#include "HX711.h"

#define SENSOR1_DATA (uint8_t) A0
#define SENSOR2_DATA (uint8_t) A2
#define SENSOR3_DATA (uint8_t) A4
#define SENSOR4_DATA (uint8_t) 7
#define SENSOR1_SCK (uint8_t) A1
#define SENSOR2_SCK (uint8_t) A3
#define SENSOR3_SCK (uint8_t) A5
#define SENSOR4_SCK (uint8_t) 6

extern void* __bss_end;
extern void* __brkval;

HX711 SENSOR1;
HX711 SENSOR2;
HX711 SENSOR3;
HX711 SENSOR4;

int get_free_memory()
{
  int free_memory;

  if((int) __brkval == 0)
    free_memory = ((int)&free_memory) - ((int)&__bss_end);
  else
    free_memory = ((int)&free_memory) - ((int)__brkval);

  return free_memory;
}

void setup() {
    Serial.begin(9600);
    Serial.println(F("Sensor Test"));

    SENSOR1.begin(SENSOR1_DATA, SENSOR1_SCK);
    SENSOR1.set_scale(-63.f);
    SENSOR1.tare();
    Serial.println(F("Sensor 1 initialized."));

    SENSOR2.begin(SENSOR2_DATA, SENSOR2_SCK);
    SENSOR2.set_scale(-58.f);
    SENSOR2.tare();
    Serial.println(F("Sensor 2 initialized."));

    SENSOR3.begin(SENSOR3_DATA, SENSOR3_SCK);
    SENSOR3.set_scale(-50.f);
    SENSOR3.tare();
    Serial.println(F("Sensor 3 initialized."));

    SENSOR4.begin(SENSOR4_DATA, SENSOR4_SCK);
    SENSOR4.set_scale(-46.f);
    SENSOR4.tare();
    Serial.println(F("Sensor 4 initialized."));
}

void loop() {
  Serial.print(F("S1: "));
  Serial.print(SENSOR1.get_units(), 1);
  Serial.print(F(" | S2: "));
  Serial.print(SENSOR2.get_units(), 1);
  Serial.print(F(" | S3: "));
  Serial.print(SENSOR3.get_units(), 1);
  Serial.print(F(" | S4: "));
  Serial.println(SENSOR4.get_units(), 1);
  Serial.print(F("Free RAM: "));
  Serial.println(get_free_memory());
}

```

Wiring diagram (Fritzing):

Changelog:

* Code is now embedded in the question.

# Answer
> 1 votes
You'll need to use a library that support multiple HX711's. The HX711-multi library by compugician has worked great for me.

> The main difference this library introduces is the ability to sample multiple HX711 units simultaneously. It is optimized for intoducing minimal (effectively zero) overhead.

# Answer
> 0 votes
If I have seen this correctly, you are currently only measuring the memory requirement in the loop(). To find out how much memory your code is using you should measure the memory consumption in any function which is memory hungry. You should call this line in all functions that are likely to put a heavy load on the heap.

```
freeRAM = min(freeRAM, get_free_memory());

```

freeRAM is a global defined int with an initial value of 2048 (or what the RAM size is). It is not enough to measure the memory usage only in loop(), because every function uses the heap during a call and frees the memory afterwards if variables not static.

---
Tags: arduino-uno, sensors
---


# Question
Title: Can internal and external pull up/pull down resisters be used together?
What happens if a sketch uses code like `pinMode(18,INPUT_PULLDOWN)` to configure internal pull-down (or pull-up) resistors, but is used in a circuit where external resistors are also present?

Are there likely to be any problems, conflicts or unexpected behaviour, e.g. if software sets a pull-down, but there is an external pull-up, or visa versa?

I am using an ESP32 (which has both internal pull-ups and pull-downs available on most GPIO pins), but I would appreciate a general answer. To clarify, I am not after the pros and cons of using external resistors (which is discussed in other questions), but the potential pitfalls of using both, especially if they are pulling in opposite directions.

# Answer
The main risk if you use both internal and external pullup/down resistors working in opposite directions is that the input will be left at an intermediate voltage that is not guaranteed to be read as high or low. Furthermore a little noise on the input might flip a read from high to low or vice versa. There is no risk of damaging the input however
> 4 votes

# Answer
It is actually beneficial for the chip to have an additional pull-up or pull-down. It can help to reduce noise and to protect from ESD on the pin coming in. The internal resistors can only take a very small amount of current and an external can take some of the current in case an ESD event is happening. The downsides of an external resistor are (not complete list):

* space requirements
* cost (although very low cost)
* slightly increased power consumption

If these are not a problem for you, an external resistor is a good idea.

Here is a video (not me), that explains the ESD-part it in more detail.

EDIT: I just re-read your question and saw that you asked about mixing pull-up and pull-down. That you should normally not do as jksemple said.
> 1 votes

# Answer
When you add the external resistor it will be connected to the internal pull resistor (up or down) depending on configuration. The pull resistor will either be series or parallel with the external resistor. In series it will behave as a voltage divider, in parallel it will increase the current required to cause the pin to change state. Mixing will not harm the computer as the pull resistor is designed to be connected to the opposite polarity externally. With the data sheet and the value of your resistor you can calculate the current and or voltage. You do not want to use external pull up and pull down resistors on the same pin. It may work but it is best to do the calculations to see if it will give you a viable value.
> 1 votes

# Answer
pinMode(18,INPUT\_PULLDOWN) ? There is no such thing! you use a resistor for that. only pullup internal available\_
> -1 votes

---
Tags: pins, pull-up
---


# Question
Title: Help needed with I2C LCD + Arduino - DS-LCDD5
I am new to this forum and a relative beginner to Arduino (software wise) Have built many projects, but always just copy/paste/modify example code.

I found a couple of these modules (a PIC18 daughter board on the back of a common 16x2 LCD) It says in the data sheet that it can be controlled via I2C, but my skill level is too low to figure out how to do it. Can somebody please give me advice on how to proceed?

The "I2C Scanner" sketch identifies it at address 0x14 , but the usual I2C-LCD libraries don't work on it. I use it with an Arduino UNO, SDA(A4), SCL(A5), 1k8 pullup resistors on each. The module is working 100% with the 1 wire serial method as per the manual.

This is how I think it should work, but it does nothing:

```

// Include Arduino Wire library for I2C
#include <Wire.h>

// Define Slave I2C Address
#define SLAVE_ADDR 0x14   // 7bit address = 0010100D, 0x14 hex

void setup () {

 Wire.begin();                           // Initialize I2C communications as Master

  // Write something to the Slave
 Wire.beginTransmission(0x14);           //  0x14  (SLAVE_ADDR)  0010100
  Wire.write(0x28);                       //  00101000
  Wire.write(0x00);                      //  Register address  "0"
  Wire.write("A");                       //  some text
  Wire.endTransmission();

 }

void loop () {

}

```

Link to manual: http://www.i-lcd.com/PDFs/Drivers/Technical%20data%20on%20DS-LCDD5%20Interface%20Module%20(IDS).pdf

# Answer
So, after I "remembered" that I have an oscilloscope, I hooked it up and noticed that I don't receive an "acknowledge" from the module.

Then I played around with the clock speed, and found I do get an "acknowledge" if I set it between 16000kHz and 18000kHz with the "Wire.setClock" command. :thinking:

Then by mere coincidence, I found that text must got to R1 NOT R0 and control commands to R2 NOT R1. :grimacing: But I could not get any of the RGB commands to work. I tried this on all 6 of the modules which I have, same results. I will just stick to serial comms when I need to use any of these.

So, either the datasheet is wrong or the firmware in the module is flawed. At least I learned a lot about the workings of I2C in the process, which my goal was.

https://forum.arduino.cc/t/need-help-with-i2c-code-for-a-16x2-lcd-ds-lcdd5/918289/28?u=jdev99

Thank you for all advice. Joe

Working code:

'''

// Include Arduino Wire library for I2C #include \<Wire.h\>

// Define Slave I2C Address #define SLAVE\_ADDR 0x14 // 7bit address = 0010100D, 0x14h

void setup () {

Wire.begin(); // Initialize I2C communications as Master Wire.setClock(16000); // only 16000 - 18000 work

//Clear display Wire.beginTransmission(0x14); Wire.write(0x02); Wire.write(0x01); Wire.endTransmission();

}

void loop () {

//Start print on line1, pos1 Wire.beginTransmission(0x14); Wire.write(0x02); Wire.write(128); Wire.endTransmission();

// Write something to the Slave Wire.beginTransmission(0x14); // 0x14 (SLAVE\_ADDR) 0010100 Wire.write(0x01); // Register address "0" Wire.write("ABCDEFGHIJKLMNOP"); // some text Wire.endTransmission();

delay(3000);

//Clear display Wire.beginTransmission(0x14); Wire.write(0x02); Wire.write(0x01); Wire.endTransmission();

//Start print on line2, pos1 Wire.beginTransmission(0x14); Wire.write(0x02); Wire.write(192); Wire.endTransmission();

// Write something to the Slave Wire.beginTransmission(0x14);
Wire.write(0x01);
Wire.write("1234567890-=+\*/@");
Wire.endTransmission();

delay(3000);

//Clear display Wire.beginTransmission(0x14); Wire.write(0x02); Wire.write(0x01); Wire.endTransmission();

}

'''
> 2 votes

# Answer
Try Replacing the "A" to single quotes 'a' `Wire.write('A');` or `Wire.write(0x41);`

you can also try and add `(byte)` before the hex value: `Wire.write((byte)0x28);`
> 0 votes

---
Tags: i2c, lcd
---


# Question
Title: Rp2040 How to signal the second core from first core as an indicator to do something
Im new to dual core programming and i do not know the best practices yet. In my current project, i would like the second core to only do something after it is being told by the first core.

The approach i am using somewhat of a brute force is something like this:

```
bool indicator = false;
int a,b;

void loop () { // core1
  if(indicator == false){  //check if core2 is still processing
     a=random(100);
     b=random(100);
     indicator = true;
  }
}

void loop1(){ //core2
  if(indicator == true){
     int sum = a+b;
     Serial.println(sum);
     indicator == false;
  }
}

```

this is just a simplified idea of how my code is going to be. Are there better ways of going about this? In general i want to tell core2 from core1 that it needs to start/stop doing something.

# Answer
What you have created there is called a *semaphore*.

In multi-threaded (or multi-core) programming there are two important signalling concepts:

* **Mutex** \- This is an object of some form that is used to allow access to a shared resource by only one core or thread at a time. A thread tries to "lock" a mutex before using a resource. A mutex can only be "locked" by one thread at a time, and if the mutex is already locked by another thread it can either block (aka a "spinlock") waiting for the mutex to be unlocked, or it can fail gracefully and try again later.
* **Semaphore** \- This is a simple flag that is used for one thread to tell another thread that something has happened or that it should do something. It is typically set by one thread then read and cleared by the other thread.

As I mentioned before, a *semaphore* is what you have created, and a simple boolean value is the most basic semaphore there is. Note, though, that you should really have the variable as `volatile` to prevent the compiler optimizing it away.

The RP2040 SDK has some functions built in for allowing the cores to communicate, including a "lockout" facility allowing one core to tell the other to stall until such time as it should start processing again, and a FIFO to allow the asynchronous passing of data from one core to the other.
> 3 votes

---
Tags: arduino-nano-rp2040
---


title: Plug in analog sensor into digital pin

text:
# Question
Title: Plug in analog sensor into digital pin
If I take an Arduino (samd21, if it matters) and plug in an analog sensor/pot into a digital pin and then set that pin to be an input, would digitalRead(#) trigger HIGH and LOW at some threshold point? Or does it not work at all?

# Answer
According to SAMD21 the digital input pin detects **HIGH** if the voltage on pin is higher than 0.55 of supply voltage. So at 3.3 V it is **1.8 V**.

The input pin detects **LOW** if the voltage is lower than 0.3 of supply voltage. It is **0.99 V** at 3.3 V.

For voltages between these values (1 V to 1.8 V) the result can be HIGH or LOW.
> 4 votes

# Answer
Yes. If you read the datasheet you will find a set of voltage specifications. The ones you are interested in are VIH and VIL.

Most MCUs use a "Schmitt Trigger" for the inputs. This means that when the voltage rises above the HIGH threshold (VIH) the input switches to HIGH. When the voltage drops below the LOW threshold (VIL) the input switches to LOW. This "hysteresis" provides a certain amount of noise rejection to give a clean digital input signal.
> 4 votes

---
Tags: digital, analog
---


title: What does a delay(0) actually do?

text:
# Question
Title: What does a delay(0) actually do?
I've seen some code where the developers add `delay(0)`, it doesnt make sense, what does it do? Delay with zero milliseconds, why?

```
bool DFRobotDFPlayerMini::waitAvailable(unsigned long duration){
  unsigned long timer = millis();
  if (!duration) {
    duration = _timeOutDuration;
  }
  while (!available()){
    if (millis() - timer > duration) {
      return false;
    }
    delay(0);
  }
  return true;
}

```

# Answer
Delay (traditionally) has two functions that it performs:

1. Wait for a period
2. Yield processing to other threads through the `yield()` weak symbol.

By using a `delay(0)` the author thinks they are saying "I don't want to delay here, but if anything is using the `yield()` function it can run now."

However, that is *not* correct.

The code for `delay()` in the AVR core looks like this:

```
void delay(unsigned long ms)
{
    uint32_t start = micros();

    while (ms > 0) {
        yield();
        while ( ms > 0 && (micros() - start) >= 1000) {
            ms--;
            start += 1000;
        }
    }
}

```

You can see that, as well as delaying for a period, `yield()` is regularly called. However that only ever happens if `ms` is greater than 0. If you pass `0` as the delay length then the `delay()` function essentially does nothing at all.

Now it *could* be that an earlier version of the core had `yield()` always being called even with `ms==0`, but the current version doesn't. Maybe this is a hangup from an old coding style. But for the current core if you want to yield you must explicitly call `yield()` or delay for *at least one millisecond*.
> 10 votes

---
Tags: delay
---


# Question
Title: Can't Upload Sketches to Arduino Nano Every
first-time builder here. I just got my Arduino Nano Every in the mail from Mouser, and I'm trying to upload a modified version of the blink example to my new brand-new board. However, every time I try to upload a sketch, the IDE just spins its wheels for around 5 minutes before giving up. I've been trying to look through similar questions and haven't found anything that has solved my issue. My OS is Windows 10.

Here's a snippet of the log (I've turned on verbose reporting for compilation and upload):

```
Arduino: 1.8.13 (Windows 10), Board: "Arduino Nano Every, None (ATMEGA4809)"
…
Forcing reset using 1200bps open/close on port COM1
…
         Using Port                    : COM1
         Using Programmer              : jtag2updi
         Overriding Baud Rate          : 115200
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
avrdude: jtagmkII_getsync(): sign-on command: status -1
An error occurred while uploading the sketch

```

Here are the settings I'm currently using:

* Board is set to Arduino Nano Every, using Arduino MegaAVR Boards 1.8.6
* Registers emulation: none (ATMEGA4809)
* Port: COM1 (there are no other options that appear for me, and no other port pops up in the device manager when I plug the board in)
* Programmer: Onboard Atmel mEDBG (UNO WiFi Rev2)

Here's what I've tried so far:

* Disabled antivirus
* Uninstalled and reinstalled Arduino IDE
* Turning on registers emulation
* Restarting computer
* Resetting board
* Using different USB cables
* Using different USB ports (3.0 and 2.0)
* Manually installing Arduino drivers to Windows (Windows said the most up-to-date drivers were already installed after I specified the directory to search in)
* Nothing is connected to the board.
* The pin-13 LED blinks, so there's a bootloader on the board.
* I've reset the board before uploading.

Any help would be very much appreciated. I'm about to give up and just return the board and swap it for a different one.

# Answer
> 2 votes
Here is a trick I use on some boards but first be the baud rate is the same in the terminal as in the sketch (Serial.begin(115200). If so then remove everything then put a jumper between ground and reset. Then put a jumper between TX and RX (pin o and pin 1 on uno). launch the IDE and what you type in the console should be echoed back to you. If this works the hardware is connected fine.

# Answer
> -1 votes
I was getting the same error when I got my brand new Nano Every.

I had Registers emulation: ATMEGA328

I changed it to None (ATMEGA4809) and it uploaded without problems.

I'm on ubuntu 18.04, and this is after the IDE prompted me to install the megaAVR boards library (1.8.7) of course.

---
Tags: arduino-nano, sketch, uploading, debugging
---


# Question
Title: Is there a need to put a delay in the main loop
Im a complete beginner. Generally speaking, is there any need at all to have a delay in the main loop()? Im not used to writing infinite loops

Is it correct to say that the delay() command is simply helpful for tutorials (i.e turn light on, wait, turn light off. wow!) but normally speaking a delay would not be helpful, and instead we are just rapidly infinitely polling our connected devices. Is that correct?

(I get that in some specialized cases it might be helpful to put a delay in the loop. Im not asking about the specialized cases.)

# Answer
There is no absolute need for any Arduino program to use `delay()`

The *blink without delay* sketch that is included in the standard sketch examples is the canonical illustration of this.

In most cases you don't need to poll your sensors thousands of times a second. It is good discipline to only poll sensors as often as makes sense for the specific application. Sometimes this might be once every five minutes. For example an ambient temperature sensor. In those cases there is nothing to be gained be polling a thousand times a second. To do so wastes resources and is a poor habit that could be troublesome for battery powered applications.

For example, the use of `millis()` for timing allows you to effectively poll several peripherals each at different intervals, perhaps averaging some readings to reduce noise, perhaps also updating a display at other intervals that suit human perception.

For long running battery powered applications it is likely that you will benefit from finding out about putting the microcontroller to sleep using `sleep()` or `deepSleep()` and using interrupts to wake it. A real time clock (RTC) or the watchdog timer interrupt can perhaps be used to schedule your sensor readings and other actions, perhaps in conjunction with `millis()`.

For very simple programs that don't need precise timings. `delay()` can be the simplest and clearest way to manage timings.
> 3 votes

# Answer
No, there is no need to use `delay()` at all. Unlike the `sleep()` or `deepSleep()` commands, delay does not save power or do anything else that's special.

The standard implementation of `delay` is just doing a busy-wait until the time has elapsed, something like:

```
void delay(int ms)
{
    int end = millis() + ms;
    while (millis() < end) {}; // do nothing
}

```

So for the CPU itself, this just wastes CPU cycles, it doesn't save any power.
> 1 votes

---
Tags: loop, delay
---


# Question
Title: ATtiny85 giving multiple wake from IDLE if INT0 held low
Desired behaviour:

1. Go to IDLE sleep mode.
2. When PB2 (blue trace) goes low wake up and give a 10 ms HIGH on PB1 pulling a pull-up low (yellow trace on Figure 1).
3. Go to 1.

What I get:

*Figure 1. (1) The input triggers, (2) the CPU wakes from sleep, (3) the CPU goes back to sleep and wakes up repeatedly until (9) the input goes high again.*

I want one 10 ms low pulse and then go back to sleep until the next negative going edge on PB2 regardless of how long PB2 is held low.

Even though I set MCUCR to falling edge of INT0 the device seems to wake repeatedly when PB2 is held low. My code below attempts to solve this by switching to rising edge interrupt if the input is low and falling edge interrupt if the input is high. The result is shown in Figure 1.

```
void setup(){
  ADCSRA &= ~_BV(ADEN);               // ADC off. ADC not used.
  pinMode(reedPin, INPUT);
}

void loop(){
  system_sleep();                     // Go straigth to sleep.
  // ---- System woken up by interrupt. ---------
  if (!digitalRead(reedPin)) {        // Check that input is low.
    pinMode(outPin, OUTPUT);          // Enable output.
    digitalWrite(outPin, HIGH);       // Pull motor sensor input low by MOSFET.
    delay(pulseTime);                 // Pulse time.
    digitalWrite(outPin, LOW);        // Pulse off.
  }
}

// From http://interface.khm.de/index.php/lab/experiments/sleep_watchdog_battery/
void system_sleep() {
  MCUCR |= _BV(ISC01);                    // Required for both rising and falling edge interrupt.
  if(digitalRead(reedPin)) {              // Input is high so set interrupt for detecting low.
    MCUCR &= ~_BV(ISC00);                 // Clear MCUCR bit 0 for falling edge interrupt.
  } else {                                // Input is low so set interrupt for detecting high.
    MCUCR |= _BV(ISC00);                  // Set MCUCR bit 0 for rising edge interrupt.
  }
  GIMSK |= _BV(INT0);                     // Enable Pin Change Interrupts
  set_sleep_mode(SLEEP_MODE_IDLE);        // Leaves the clock running for elapsedMillis.
  sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
  sei();                                  // Enable interrupts
  sleep_cpu();                            // sleep
  // ZZZZZZZZZZZzzzzzzzzzzz .......
  // ------- CPU is now asleep and awaiting interrupt. ----------------------
  cli();                                  // Disable interrupts on wake up.
  sleep_disable();                        // Clear SE bit.
}

ISR(INT0_vect){                           // Wake up.
  GIMSK = 0;                              // Disable external interrupts. (Only need one to wake up.)
}

```

Can anyone guide me through this?

Many thanks.

# Answer
The Arduino core configures a timer to deliver a periodic interrupt. This interrupt is used to implement `millis()`, `delay()`, etc. Your code assumes the external interrupt is the only one the microcontroller can receive. I guess the timer interrupts may be the cause of the observed behavior.

I suggest configuring the interrupt for falling edges and leaving it always on. The ISR can take care of starting the pulse, and setting a flag to let the main loop know the pulse is active. The main loop can then stop the pulse when it has been on for long enough:

```
volatile bool pulse_active;     // whether the pulse is on
volatile uint32_t pulse_start;  // time when it started

ISR(INT0_vect) {
    // Start the pulse.
    digitalWrite(outPin, HIGH);
    pulse_active = true;
    pulse_start = millis();
}

void loop() {
    // End the pulse if it's time to do so.
    if (pulse_active && millis() - pulse_start >= pulseTime) {
        digitalWrite(outPin, LOW);
        pulse_active = false;
    }

    // Take a little nap.
    sleep_mode();
}

```

Note that the little nap in the code above can be interrupted by either the external interrupt or the timer interrupt.
> 1 votes

---
Tags: sleep, attiny85, isr
---


# Question
Title: Arduino LiquidCrystal library code prevents ESP32 from running. For 16x2 character display
See bottom for solution.

I am trying to run the Arduino LiquidCrystal library example HelloWorld.ino on an ESP32. It seems like it never even executes the Setup() loop. The ESP resets after eight seconds and then repeats the cycle.

I have used character LCD many times before (with Arduino) but always using I2C. For the current design I am eliminating the I2C to parallel chip and I am instead driving the LCD directly from the ESP32. I am using 4 bit mode to reduce the number of pins required. I have connected Register select, Enable, and D4-D7. These details are not relevant since the ESP32 does not even run with the LiquidCrystal library.

I have looked at the library code and I didn't see anything that I thought would be a problem. But I am a hardware designer (for 36 years) and not a programmer. I use the Arduino IDE because it is quick and easy to test hardware.

The library code can be found here. https://github.com/arduino-libraries/LiquidCrystal/tree/master/src

This is what I get from the serial monitor.

```
rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1240
load:0x40078000,len:13012
load:0x40080400,len:3648
entry 0x400805f8
ets Jun  8 2016 00:22:57

```

I tried the example code, and when that didn't work so I added a couple of serial print lines to the code. I am listing that below.

```
#include <LiquidCrystal.h>

const int rs = 26, en = 25, d4 = 16, d5 = 17, d6 = 18, d7 = 19;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

void setup() {
  Serial.begin(115200);
  Serial.println("Start");

  lcd.begin(16, 2);
  lcd.print("hello, world!");
}

void loop() {
  delay(1000);

  lcd.setCursor(0, 1);
  lcd.print(millis() / 1000);

  Serial.println(millis() / 1000);
}

```

Details that I didn't list above. I am powering the LCD from 5 volts. The LCD data/control lines are specified as VinLo = 0.55v and VinHi = 2.4 volts. Not that this matters since the code above never executes. I have used a Arduino Nano powered with 3.3 volts, running the above code, to confirm that the display actually works under these conditions. I really want this to work with an ESP32-C3. I tried that originally but switched to the ESP32 because it wasn't working with the code.

I hope someone can provide some guidance here. My other option is not using the library and writing my own code, which ends up being brute force and simplistic.

**EDIT:**

A **big thanks** to **Majenko** who was spot on. After removal of the call the code executed properly.

# Answer
My guess:

* the constructor calls `LiquidCrystal::init()`.
* `LiquidCrystal::init()` calls `LiquidCrystal::begin()`.
* `LiquidCrystal::begin()` uses delays.

Those delays may depend on things that aren't configured yet when the constructors are running, and lock up causing a WDT.

Remove the call to `begin()` in the `LiquidCrystal::init()` function and it should at least get past running the constructor so it gets to run the rest of your code.

Quite why they have that call in there is beyond me. Rule number one of writing an Arduino library: *never perform any operations more strenuous than assigning variables in the constructor as resources you may rely on may not have been initialized yet.*
> 2 votes

---
Tags: esp32, lcd, library
---


title: `ConfigTime` daylight saving update

text:
# Question
Title: `ConfigTime` daylight saving update
I'm using an ESP8266 to get clock NTP sync in this manner:

```
void myIOT2::_startNTP(const int gmtOffset_sec, const int daylightOffset_sec, const char *ntpServer)
{
    configTime(gmtOffset_sec, daylightOffset_sec, ntpServer); //configuring time offset and an NTP server
    while (now() < 1627735850)                                /* while in 2021 */
    {
        delay(20);
    }
    delay(100);
}

```

But now, when daylight saving ended on 31/10/2021, what "flags" code that now daylight saving has ended, and 3600 sec have to reduced (or add) ?

in my case `gmtOffset_sec=2*3600` and `daylightOffset_sec=1*3600` `ntpServer="pool.ntp.org"`

# Answer
Summing @juraj's comments

1. instead of defining UTC+x and Daylight offset, using NTZ instead.
2. While ESP8266 has \`TZ.h as part of its core I used relevant TZ as shown.
3. for ESP32: a) replace to `configTzTime` as shown. b) Copy relevant TZ from `TZ.h` for current lib and use as follows.

for ESP8266: `configTime(TZ_Asia_Jerusalem, ntpServer);`

for ESP32: `configTzTime(TZ_Asia_Jerusalem, ntpServer);` // Tz value was copied to code
> 1 votes

---
Tags: time
---


title: Keyboard.h not found on Arduino nano

text:
# Question
Title: Keyboard.h not found on Arduino nano
I am trying to use keyboard on my Arduino nano, but i get this error:

```
'Keyboard' not found. Does your sketch include the line '#include <Keyboard.h>'?

```

As per the answer in Keyboard.h not found, I tried change the board to **Arduino Leonardo**, even though the script gets compiled it doesn't get uploaded (keeps on saying uploading for a long time).

This is the code I use:

```
#include <Keyboard.h>
void setup() {
  Keyboard.begin();
}
void loop() {
}

```

# Answer
To convert the comments into an answer:

You cannot (!) use the `Keyboard` library on the Arduino Uno/Nano/Mini. It needs a native USB interface to configure it as a HID device, but the Uno/Nano/Mini all use the Atmega328p, which doesn't have a native USB interface. These Arduinos use an additional chip on the board which acts as USB-UART-bridge.

You can compile the code for the Leonardo, because it has a native USB interface. But you cannot (!) upload code, which is compiled for the Leonardo, to an Uno/Nano/Mini. Its a completely different chip.

**What to do now:** Get an Arduino board which has a native USB interface, for example the Leonardo or the Micro.
> 1 votes

---
Tags: arduino-nano, keyboard
---


# Question
Title: how to fix mirrored text on 3.2 inch IPS TFT LCD Display ILI9481 480X320 36 Pins for Arduino Mega2560
i am working on a project on my arduino mega2560. I want to show reading of the sensors on the TFT display, the problem is the text displayed on the screen is mirrored. Since i am very new to arduino i don't know how to fix the problem. I have check a few videos on youtube but nothing helped. I am using the example from the UTFT library arduino (AVR) =\> UTFT\_DEMO\_480x320

# Answer
The orientation of the display is controlled by the "Set Address Mode" command (0x36) at line 42 of the ILI9481 driver.

The current value is `0x0A` which is `00001010` in binary. According to the datasheet (8.2.25) bit 6 is "Column Address Order", and that is set to "Left to Right" currently.

Turning that bit on should reverse the column order for the display.

So changing those two lines of code to:

```
LCD_Write_COM(0x36);
LCD_Write_DATA(0x4A);

```

should have the desired effect.
> 1 votes

# Answer
Had this same problem with everything mirrored/backward. Not sure you're still trying, but for any others with this issue, here's how I addressed it..

If using the UTFT library from RinkyDink electronics, open up their initlcd.h file. In the section for Memory Access Control (lines 85-86 in version I have), change the write to:

LCD\_Write\_DATA(0x08);

Bit 0 controls vertical flip, Bit 1 controls horizontal flip.
> 2 votes

# Answer
I had the problem of a mirrored display. none of the solutions above worked. I found that the Line in the source code had the wrong driver defined. change the line in the source code (file name "UTFT\_Demo\_480x320" line# 32 to this: UTFT myGLCD(CTE40, 38, 39, 40, 41); The new part is 'CTE40'. This works with the ILI9486. You can find all of the different chip numbers in the file "UTFT.h'
> 0 votes

---
Tags: arduino-mega, tft
---


# Question
Title: LCD displays more digits than serial monitor
I am doing a BPM monitoring system. The serial monitor displays accurate BPM values ranging from 60 to 100+. But my LCD display is not accurate. Example, on the serial monitor, my bpm is about 67, but on the LCD it displays 676. What do I need to do to fix it?

```
PulseSensorPlayground pulseSensor; // Creates an instance of the PulseSensorPlayground object called "pulseSensor"

void setup() {
    Serial.begin(9600); // For Serial Monitor
    lcd.begin();
    lcd.backlight();

    // Configure the PulseSensor object, by assigning our variables to it.
    pulseSensor.analogInput(PulseWire);
    pulseSensor.blinkOnPulse(LED13); //auto-magically blink Arduino's LED with heartbeat.
    pulseSensor.setThreshold(Threshold);

    // Double-check the "pulseSensor" object was created and "began" seeing a signal.
    if (pulseSensor.begin()) {
        Serial.println("We created a pulseSensor Object !"); //This prints one time at Arduino power-up, or on Arduino reset.
    }
}

void loop() {
    int myBPM = pulseSensor.getBeatsPerMinute(); // Calls function on our pulseSensor object that returns BPM as an "int".
    // "myBPM" hold this BPM value now.
    if (pulseSensor.sawStartOfBeat()) { // Constantly test to see if "a beat happened".
        Serial.println("♥ A HeartBeat Happened ! "); // If test is "true", print a message "a heartbeat happened".
        Serial.print("BPM: "); // Print phrase "BPM: "
        Serial.println(myBPM); // Print the value inside of myBPM.

        lcd.setCursor(0,0);
        lcd.print("BPM: "); // Print phrase "BPM: "
        lcd.print(myBPM);
    }
    delay(50); // considered best practice in a simple sketch.
}

```

# Answer
> 4 votes
The additional "6" seems to come from one of the first values. Maybe the first value printed is just a rogue value and all the following values are correct.

The point is that this rogue value may take one more character on the display than the other (correct) values. And when you just move the cursor and print again the previously displayed text is only changed if it is overwritten by the new text. The correct values are shorter, so the last digit of the rogue value is not overwritten. This of course doesn't happen with Serial, since Serial doesn't print to the same space again and again (like a LCD does with its limited space).

**What to do now:** You can use `lcd.clear()` to remove all text from the display before printing new values. Though this can lead to a noticeable flicker on the display. Often it is better to just make sure to overwrite all possible leftover text with spaces via `lcd.print(" ");`. Insert this after the `lcd.print(myBPM)` (since you want to remove all leftover digits after that). In this case you only have 1 leftover digit, so one space is enough. To be sure that this won't happen again when for whatever reason you get more than one leftover digit you can use multiple spaces (`lcd.print(" ");`).

---
Tags: arduino-uno, lcd
---


# Question
Title: need help for exam please (deadline tomorrow)
what we're required to do on exam

You don't have to completely give me the answers, I just started learning this yesterday so I'm pressured on learning it properly + the exam, thx

# Answer
As written, the exam does not look like you are expected to build something functional. Rather, that you must show that you understand how to drive LEDs and a buzzer, how to write conditional code, etc. I would suggest using a pot to simulate a distance reading, and writing something along these lines:

```
void loop() {
    // Simulate a distance reading between 0 and 4 meters.
    float distance = analogRead(A0) * (4.0/1023);

    // React to the sensor reading.
    if (distance < 3) {
        // ...
    }
    // etc.
}

```
> 4 votes

---
Tags: buzzer
---


# Question
Title: How to Independently run positional and continuous servos using millis()?
I am setting up 3 servos (**2 position servos and 1 '360' continuous rotational servo**) with Arduino. but I failed to run these independently. It runs one after another. I wish to run it in loop independent to each other. Here is the code which I use to run positional servo and CR (360) servo. default servo positions are 90. \*CR 360 servo should be running independently 90-60-120-90 (in loop) \*Pos servo should be running one after another (in loop)

**To run positional servos (tilt/pan):**

```
//tilt servo
    for (pos = 90; pos >= 60; pos -= 1)     //90 ~ 60
  {
    tiltservo.write(pos);
    delay(30);
  }

  for (pos = 60; pos <= 120; pos += 1)      //60 ~ 120
  {
    tiltservo.write(pos);
    delay(30);
  }

  for (pos = 120; pos >= 90; pos -= 1)       //120 ~ 90
  {
    tiltservo.write(pos);
    delay(30);
  }

//pan servo
for (pos = 90; pos >= 60; pos -= 1)          //90 ~ 60
  {
    panservo.write(pos);
    delay(30);
  }

  for (pos = 60; pos <= 120; pos += 1)       //60 ~ 120
  {
    panservo.write(pos);
    delay(30);
  }

  for (pos = 120; pos >= 90; pos -= 1)       //120 ~ 90
  {
    panservo.write(pos);
    delay(30);
  }

```

**To run CR 360 servo:**

```
 legservo.writeMicroseconds(1600);      //CW
 delay(5000);                           //run for 5s
 legservo.writeMicroseconds(1300);      //CCW
 delay(5000);                           //run for 5s

```

Tried this to independently run CR servos, but how to put some wait (3s-4s) in between FW and RW.

```
if (millisNow - lastMillis >= 10000)
{
lastMillis = millisNow;
if (crservoState == 0)
 {
   legservo1.writeMicroseconds(2150); //FW
   crservoState = 1;
 }
  else
 {
   legservo1.writeMicroseconds(850);  //RW
   crservoState = 0;
 }
}

```

**Trial code after suggestions:**

```
uint32_t milliSNow = millis();

  if (milliSNow - lastTimeServoRotate >= 1000)
  {
    if (crservoState == 0)
    {
      if (milliSNow - lastTimeServoRotate >= 10000)
      {
        legservo1.writeMicroseconds(2150);    //FW run
        crservoState = 2;
        lastTimeServoRotate = milliSNow;
      }
    }

    if (crservoState == 1)
    {
      if (milliSNow - lastTimeServoRotate >= 10000)
      {
        legservo1.writeMicroseconds(850);     //RW run
        crservoState = 3;
        lastTimeServoRotate = milliSNow;
      }
    }

    if (crservoState == 2)
    {
      if (milliSNow - lastTimeServoRotate >= 3000)
      {
        legservo1.writeMicroseconds(1500);    //FW STOP
        crservoState = 1;
        lastTimeServoRotate = milliSNow;
      }
    }

    if (crservoState == 3)
    {
      if (milliSNow - lastTimeServoRotate >= 3000)
      {
        legservo1.writeMicroseconds(1500);     //RW STOP
        crservoState = 0;
        lastTimeServoRotate = milliSNow;
      }
    }
  }

```

# Answer
This is covered in the Blink Without Delay Arduino tutorial. Let me paraphrase the main part of the example code here:

```
uint8_t ledState = LOW;
uint32_t lastTimeLedChanged = 0;

void loop() {
    uint32_t now = millis();
    if (now - lastTimeLedChanged >= 1000) {

        // Save the last time we updated the LED.
        lastTimeLedChanged = now;

        // Compute the new state of the LED.
        if (ledState == LOW) {
            ledState = HIGH;
        } else {  // ledState is HIGH
            ledState = LOW;
        }

        // Set the LED to the computed state.
        digitalWrite(LED_BUILTIN, ledState);
    }
}

```

This will make the LED cycle between its two possible states at the desired rate. You can apply this principle as-is to your continuous rotation servo.

For the positional servos, the same principle can still be applied, but there is a catch. Whereas both the LED and the CR servo cycle between two states, the pair of positional servos goes through many states (~~92~~ 240 if I counted correctly). You will thus need:

* more variables to store the current state of the servo pair
* more code to compute the new desired state
* more code to update the state

In order to figure out how to represent the state, you have to look at your current `delay()`-based code, see how many calls to `delay()` are performed on each full cycle, and figure out how to identify each of these calls. Each of these delays corresponds to one state of your system. I would say that you need one variable to know in which of the `for` loops you are, and another variable to know the last position you wrote to the servo in that loop. I will call each of the original `for` loops a “phase”. There are ~~two~~ six such phases:

* phase 0: tilt: 90° → 60°
* phase 1: tilt: 60° → 120°
* phase 2: tilt: 120° → 90°
* phase 3: pan: 90° → 60°
* phase 4: pan: 60° → 120°
* phase 5: pan: 120° → 90°

**Note** there were only two `for` loops in the original question, but it was then edited to include six loops, thus I edited my answer.

An then you will need to store the time of the last update, thus:

```
int phase = 0;  // which of the six phases we are in
int pos = 90;   // last position written to a servo
uint32_t lastTimeServoMoved = 0;

```

Once you have the proper variables to describe the state, updating it is not hard. If you have reached the end of a phase, move to the next one. Then update the position by one step. Thus:

```
void loop() {
    uint32_t now = millis();
    if (now - lastTimeServoMoved >= 30) {

        // Save the last time we updated a positional servo.
        lastTimeServoMoved = now;

        // Compute the new state.
        if (phase == 0 && pos == 60)
            phase = 1;
        else if (phase == 1 && pos == 120)
            phase = 2;
        else if (phase == 2 && pos == 90)
            phase = 3;
        else if (phase == 3 && pos == 60)
            phase = 4;
        else if (phase == 4 && pos == 120)
            phase = 5;
        else if (phase == 5 && pos == 90)
            phase = 0;
        if (phase == 1 || phase == 4)
            pos += 1;
        else
            pos -= 1;

        // Set the servo to the computed state.
        if (phase < 3)
            tiltservo.write(pos);
        else
            panservo.write(pos);
    }
}

```

I personally do not like this kind of repetitive code. If you are comfortable with data structures, I would recommend using an array of structs to store all the information describing the moves that are done in each phase:

```
struct {
    Servo *servo;   // which servo to move
    int step;       // steps by which it moves
    int final_pos;  // final angular position
} moves[] = {
    { &tiltservo, -1, 60 },   // tilt:  90 ->  60
    { &tiltservo, +1, 120 },  // tilt:  60 -> 120
    { &tiltservo, -1, 90 },   // tilt: 120 ->  90
    { &panservo,  -1, 60 },   // pan:   90 ->  60
    { &panservo,  +1, 120 },  // pan:   60 -> 120
    { &panservo,  -1, 90 }    // pan:  120 ->  90
};

```

Then the actual code becomes simpler:

```
void loop() {
    uint32_t now = millis();
    if (now - lastTimeServoMoved >= 30) {

        // Save the last time we updated a positional servo.
        lastTimeServoMoved = now;

        // Compute the new state.
        if (pos == moves[phase].final_pos) {
            phase +=1;
            if (phase == 6)
                phase = 0;
        }
        pos += moves[phase].step;

        // Set the servo to the computed state.
        moves[phase].servo->write(pos);
    }
}

```
> 4 votes

---
Tags: arduino-uno, servo, millis, delay
---


# Question
Title: LoRa recieves only 2-4 packets, then stops working
I'm working on LoRa project using \[Ai-Thinker RA-01 SX1278 433MHz LoRa\]\[1\] with \[sandeepmistry/arduino-LoRa\]\[2\] library. I modified LoRaReciever example so it looks like this

```
#include <SPI.h>
#include <LoRa.h>

void setup() {
  Serial.begin(9600);
  while (!Serial);

  Serial.println("LoRa Receiver");

  if (!LoRa.begin(433E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
}

void loop() {
  // try to parse packet
  int packetSize = LoRa.parsePacket();
  LoRa.onReceive(onReceive);
}
void onReceive(int packetSize) {

  if (packetSize) {
    // received a packet
    Serial.print("Received packet '");

    // read packet
    while (LoRa.available()) {
      Serial.print((char)LoRa.read());
    }

    // print RSSI of packet
    Serial.print("' with RSSI ");
    Serial.println(LoRa.packetRssi());
  }
}

```

I receive 2-4 packets successfully, but then I don't receive any, even though the transmitter is still transmitting. (If I restart my Arduino it receives 2-4 packets again).

I have both LoRa modules really close to each other (about 10 cm) could it cause the problem? - Even when I tried like 15m with walls, problem stayed.

Sometimes, the receiver gets bugged and starts receiving packets all the time (one packet like 50 times), when it's bugged like this, it doesn't stop receiving (unique) packets after any number.

Do you know where the problem could be? Thanks.

I use Arduino Mega

```
#include <SPI.h>
#include <LoRa.h>

void setup() {
  Serial.begin(9600);
  while (!Serial);

  Serial.println("LoRa Receiver");

  if (!LoRa.begin(915E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
}

void loop() {
  // try to parse packet
  int packetSize = LoRa.parsePacket();
  if (packetSize) {
    // received a packet
    Serial.print("Received packet '");

    // read packet
    while (LoRa.available()) {
      Serial.print((char)LoRa.read());
    }

    // print RSSI of packet
    Serial.print("' with RSSI ");
    Serial.println(LoRa.packetRssi());
  }
}

```

This is original LoRaReciever example, but I don't receive anything using it. \[1\]: https://www.laskarduino.cz/ai-thinker-ra-01-sx1278-433mhz-lora-modul/ \[2\]: https://github.com/sandeepmistry/arduino-LoRa

# Answer
> 1 votes
I found the solution. The problem was with calling `onRecieve` in `loop` not in `setup` It should have looked like this...

```
#include <SPI.h>
#include <LoRa.h>

void setup() {
  Serial.begin(9600);
  while (!Serial);

  Serial.println("LoRa Receiver");

  if (!LoRa.begin(433E6)) {
    Serial.println("Starting LoRa failed!");
    while (1);
  }
  LoRa.onReceive(onReceive);
  LoRa.receive();
}

void loop() {
  //do nothing
}
void onReceive(int packetSize) {

  if (packetSize) {
    // received a packet
    Serial.print("Received packet '");

    // read packet
    while (LoRa.available()) {
      Serial.print((char)LoRa.read());
    }

    // print RSSI of packet
    Serial.print("' with RSSI ");
    Serial.println(LoRa.packetRssi());
  }
}

```

---
Tags: arduino-mega, error, lora
---


# Question
Title: How to change variable/sketch through a GUI
Over the past few months, I've been working on a wearable computer mouse using an Arduino and a 9-dof sensor. Most of the sketch is complete, and works as expected.

Recently, I started investigating how to enable a non-technical user to adjust the sensitivity of the device. Currently, I do this by changing a couple of variables in the sketch. My goal is to be able to create a basic GUI, with some buttons (perhaps unsurprisingly), to accomplish the same.

Requirements:

* ability to adjust sensitivity (couple of variables inside sketch) of arduino device through a GUI
* does not slow down sketch (I read that you can use serial, but wouldn't constantly checking for serial slow down the operation of the microcontroller?)
* can be saved as an executable (easy to set up for a nonprogrammer)

It's fine for the solution to upload a new sketch to the microcontroller, or change variables in the EEPROM. Whatever you suggest is best. I came across this, and a few other similar topics, but due to my inexperience was unable to judge whether that's the best way forward.

I'm not looking for a complete solution, of course. Rather, I would really appreciate any guidance on what the basic "structure" of the solution should be. Then I can determine which parts I can do myself, and which I'll need to seek help on.

Thank you very much for looking at this.

# Answer
Reflashing (and with that recompiling) the sketch for every variable change is very over-the-top.

As you already want to write your own program for the PC I would suggest using `Serial`. That will be the easiest to implement. This would work like the following:

* On the Arduino: You regularly check if there is data in the `Serial` buffer, read if in that case. You read until a newline character `\n`, which acts as message delimiter (to distinguish one message from the other). If a full message was received (meaning: you read the newline character) you process the message and write the new values to EEPROM (for saving them permanently).
* On the PC application: Let the user determine each value. You open the Arduinos COM port (the user will have to select the correct one) to communicate via Serial. Then you send each value, that you want to write to the Arduino, in a specific format. For example `<value_name>:<value>`. And don't forget the newline character at the end. Then you can close the COM port and exit the application.

This requires the user to choose the corresponding COM port. With using a custom USB profile (I think a custom HID profile should also be able to receive data) you could eliminate that, but this is a big step in difficulty for you to program.

> I read that you can use serial, but wouldn't constantly checking for serial slow down the operation of the microcontroller?

No, not really. The actual receiving of data is done by the USB hardware. As processing load you only have the placing of data in the buffer (happens inside an ISR), which only is done when actual data is received, and the checking if there is data in the buffer. That also needs very short time. It should not interfere with your sampling rate. The 9-DoF sensor is most likely way slower. The actual processing of the data is also only done when you actually send data. Here the longest will be saving the data in EEPROM.

So all in all you have little to no impact on performance.
> 1 votes

---
Tags: programming, c++, sketch, eeprom
---


# Question
Title: How to debug "No device found on cu.usbserial, An error occurred while uploading the sketch"
I am testing a project on Arduino Nano. I copy-paste the code on the Arduino IDE and click "Upload". I see:

```
No device found on cu.usbserial-<unique id>
An error occurred while uploading the sketch

```

The computer sees the board: when I disconnect the board from the USB socket, the list of ports in `Tools > Port` no longer shows this port.

The error thing happens:

* if I press the reset button first, then click "Upload"
* if I change the USB cable (I tried 5 different ones, one of which worked a few years ago, the last time I used this same board)
* if I use a simple blink code
* if I connect to a different USB port
* if I upgrade the Arduino IDE to the latest software from arduino.cc .

The `Get board info` command shows that the computer can read the VID and the PID, but not the serial number or the board type. If I connect an Arduino Uno to the same socket, I can see the serial number and the board type, but I get the same error message (just with a different port ID). Neither boards show signs of degradation.

The Boards Manager shows that the Arduino AVR Boards, which include Arduino Uno and Arduino Nano, are installed.

When I click "Upload", the IDE compiles the program, then the Nano's L LED blinks, then the TX blinks, then a pause, then the L, then the RX, then the L, then the RX, and then the IDE shows the error. So I suspect that the error is not what the IDE says.

Furthermore, the connection between the Arduino and the IDE is working because the Serial Monitor shows the output of the previous program (at 9600 baud).

Some Arduinos can reset by connecting RX to GROUND and uploading code, but this one does not have an RX pin.

How can I debug this error?

# Answer
It seems that everything is working as it should and the computer and the board can see each other. The only thing left to do is to select the board type so the IDE knows how to send the code in a way that the board can interpret.

Select `Tools > Board > Arduino AVR Boards > Arduino Nano`.

If you have an old or non-Arduino board, try the old bootloader in the processor, as in CH340 Nano avrdude: stk500\_getsync() not in sync resp=0xa4 .
> 1 votes

---
Tags: arduino-ide, arduino-nano
---


# Question
Title: String operations printing random character on Serial Monitor
I want to extract the file name `MyFile.txt` out of a path which is stored in a string `"C:\\MyDirectory\\MyFile.txt";`

I found a simple c code which does the job.

```
string filename = "C:\\MyDirectory\\MyFile.bat";

// Remove directory if present.
// Do this before extension removal incase directory has a period character.
const size_t last_slash_idx = filename.find_last_of("\\/");
if (std::string::npos != last_slash_idx)
{
    filename.erase(0, last_slash_idx + 1);
}

// Remove extension if present.
const size_t period_idx = filename.rfind('.');
if (std::string::npos != period_idx)
{
    filename.erase(period_idx);
}

```

I had to alter few things for arduino code example replace `find_last_of` with `lastIndexOf`, `erase` with `remove` and `rfind` with `lastIndexOf`

Here the `ino` file

```
#include<string>
void setup() {
  Serial.begin(9600);

}

void loop() {
   String filename = "C:\MyDirectory\MyFile.bat";

// Remove directory if present.
// Do this before extension removal incase directory has a period character.
const size_t last_slash_idx = filename.lastIndexOf("\\");
if (std::string::npos != last_slash_idx)
{
    filename.remove(0, last_slash_idx + 1);
}

// Remove extension if present.
const size_t period_idx = filename.lastIndexOf('.');
if (std::string::npos != period_idx)
{
    filename.remove(period_idx);
}
Serial.println(filename);
delay(1000);
}

```

Expected output `MyFile`

When I look into Serial Monitor I get

```
c$$⸮'<;⸮⸮/<⸮⸮$⸮''⸮;,#$$⸮'<;⸮⸮'<⸮⸮$⸮''⸮:$#$$⸮'<;⸮⸮'<⸮⸮$⸮''⸮;$#$$⸮'

```

What am I doing wrong?

# Answer
> 1 votes
> ```
> #include<string>
>
> ```

Remove this. Arduino uses its own `String` class, different from the STL `string`.

> ```
> String filename = "C:\MyDirectory\MyFile.bat";
>
> ```

There is no `'\M'` escape sequence in C++ strings. You probably mean `"C:\\MyDirectory\\MyFile.bat"`.

> ```
> const size_t last_slash_idx = filename.lastIndexOf("\\");
>
> ```

`String::lastIndexOf()` returns an `int`, not `size_t`.

> ```
> if (std::string::npos != last_slash_idx)
>
> ```

No `std::string` here. `String::lastIndexOf()` returns `-1` to signify that the character was not found.

With all these fixes, your sketch should work as intended.

---
Tags: arduino-ide, esp32, c-string
---


title: How to add library to Sloeber

text:
# Question
Title: How to add library to Sloeber
Slober has a menu option: *Arduino -\> Add a library to the selected project*

HOWEVER, the "Import Arduino libraries" dialog that comes up only shows 18 libraries, and has no obvious way to add more.

I selected *Arduino -\> How To*, and selected "Add a library to a sketch", but it told me nothing new. It assumes the library I want to add is in the list, and says nothing about how that list itself is managed, where the libraries in it came from, how to add others, etc.

I theorized that Sloeber's list might be somehow generated from the one maintained by the Arduino IDE... but no, the list of libraries shown in Sketch -\> Include library is ENORMOUSLY longer than Sloeber's list.

So... where, exactly, does Sloeber's library list come from, and how does one go about adding a library to it that's NOT in the list? Say...

* From whatever repository the Arduino IDE itself gets libraries from when you go to Library Manager (confession: I don't use Arduino often enough to *know* where those libraries are actually hosted, or who decides what qualifies to be listed. I assume it's something like MavenCentral and hosted by the Arduino organization... but I might be completely wrong)
* From a "zipfile" (containing whatever files, with whatever additional metadata, is required for Arduino's IDE to regard it as a valid library zipfile)
* From a random Github repo, like https://github.com/mrkaleArduinoLib/gbj\_htu21 (with library.json, library.properties, and subdirectories for src/ and examples/)

# Answer
In `Arduino` or in `Window` menu in `Preferences`
> 0 votes

---
Tags: sloeber
---