title: EtherCard library without TCP

text:
# Question
Title: EtherCard library without TCP
I have connected some sensors to an Arduino Uno (but the final code should run on a Pro-Mini) with an ENC28J60 shield. The sensor code works fine - until I add EtherCard. I tried UIPEthernet first, but it's even worse. The problem is the memory footprint. The ethernet libraries are consuming so much memory that random malfunctions do occur.

So I was thinking about removing TCP from the EtherCard library, because I don't need it anyway. I only need IP, ARP, UDP, and based on that DHCP, DNS and NTP.

Has someone already done this?
Is there a stripped-down library?

The file `tcp.cpp` is pretty big (the biggest in this lib). Is it safe to remove all methods with "tcp" in their name?

Or is there a better solution for this situation?

# Answer
> 1 votes
My EthernetENC library based on the original UIPEthernet library by Norbert Truchsess has settings to balance performance and memory usage. These settings are in utility/uipethernet-conf.h file or can be specified as -D parameters for compilation.

`UIP_CONF_MAX_CONNECTIONS` is a maximum number of connected EthernetClient connections. The default value s 4. You can set it to 0 if you don't use EthernetClient TCp connections. It will save a lot of dynamic memory.

Arduino IDE doesn't have the possibility to set defines for a sketch (For example Sloeber has it). As some workaround to set the defines for different boards for Arduino IDE, you can create a file boards.local.txt next to boards.txt file in hardware package. Set build.extra\_flags for individual boards.

comment by OP:

> Setting uno.build.extra\_flags= -DUIP\_CONF\_MAX\_CONNECTIONS=0 in "boards.txt" in the arduino IDE folder reduced program memory usage by 2442 bytes and dynamic memory usage by 290 bytes.

---
Tags: library, ethernet-shield, enc28j60
---


title: How to use millis instead of delay?

text:
# Question
Title: How to use millis instead of delay?
Sorry if something similar has been answered before...

I am working on a garden timer project that runs on a ESP8266 based NodeMCU and is integrated with Blynk.

I have a waterNow function that activates when I press a button on the Blynk app, it sets pin D5 to HIGH and waits 3 seconds with a delay function, the problem is that with delay the code just halts all other functions until the delay is complete.

After doing some research I found out that the millis function could be used to have a time delay and have the program still run, but I can't get it to work.

How do use the millis function to add a delay?

Any help is appreciated.

Code:-

```
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include "DHT.h"
#include "LiquidCrystal_PCF8574.h"

#define BLYNK_PRINT Serial
#define DHT_PIN_DATA  12
// LCD definations
#define LCD_ADDRESS 0x27
#define LCD_ROWS 2
#define LCD_COLUMNS 16
#define SCROLL_DELAY 150
#define BACKLIGHT 25
#define DHTTYPE DHT22

char auth[] = "ymri204FL9_xZhf6WIRHtQ1qEWOt9zBy";

char ssid[] = "Aihertgtel-Hotspotgfdf-82DB";
char pass[] = "";
int autoSch;
int waterNow;
int morTime;
int afterTime;
int eveTime;
int schTime;
int x;

DHT dht(DHT_PIN_DATA, DHTTYPE);
LiquidCrystal_PCF8574 lcdI2C;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "in.pool.ntp.org", 19800, 600000);
// This function will be called every time Slider Widget
// in Blynk app writes values to the Virtual Pin 1

BLYNK_CONNECTED() {
  Blynk.syncAll();
}

BLYNK_WRITE(V0)
{
  autoSch = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V1)
{
  morTime = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V2)
{
  afterTime = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V3)
{
  eveTime = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V10)
{
  waterNow = param.asInt(); // assigning incoming value from pin V1 to a variable
}

BLYNK_WRITE(V4)
{
  schTime = param.asInt(); // assigning incoming value from pin V1 to a variable
}

void time_run() {
  Blynk.virtualWrite(V11, int(timeClient.getHours()));
  Blynk.virtualWrite(V12, int(timeClient.getMinutes()));
  Blynk.virtualWrite(V13, float(dht.readTempC()));
  Blynk.virtualWrite(V14, float(dht.readHumidity()));
  Serial.println(dht.readTempC());
}

void auto_run1() {
  if (morTime == 1 && String(timeClient.getFormattedTime()) > "06:00:00" && String(timeClient.getFormattedTime()) < "06:20:00") {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    Blynk.syncAll();
  }
  else if (afterTime == 1 && String(timeClient.getFormattedTime()) > "12:00:00" && String(timeClient.getFormattedTime()) < "12:20:00") {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    Blynk.syncAll();
  }
  else if (eveTime == 1 && String(timeClient.getFormattedTime()) > "15:47:00" && String(timeClient.getFormattedTime()) < "13:48:00") {
   // digitalWrite(14, HIGH);
    for (x; x >  10; x++){
  digitalWrite(14, HIGH);
  delay(1000);
  }
    Blynk.virtualWrite(V5, 255);
    Blynk.syncAll();

  }
  else {
    digitalWrite(14, LOW);
    Blynk.virtualWrite(V5, 0);
    Blynk.syncAll();
  }
}

void sch_run2() {
  if (schTime == 1) {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    Blynk.syncAll();
  } else {
    digitalWrite(14, LOW);
    Blynk.virtualWrite(V5, 0);
  }

}

void waterNowrun() {
  if (waterNow == 1) {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    lcdI2C.selectLine(2);
    lcdI2C.print("Watering Now     ");
    delay(3000); // I want to remove this for millis
    Blynk.virtualWrite(V10, 0);
    Blynk.syncAll();
  } else {
    digitalWrite(14, LOW);
    Blynk.virtualWrite(V5, 0);
  }
}
void lcd() {
  delay(300);
  lcdI2C.clear();

  timeClient.update();
  lcdI2C.print(timeClient.getFormattedTime());

  if (autoSch == 0) {
    lcdI2C.setCursor(9, 0);
    lcdI2C.print("Auto");
  } else {
    lcdI2C.print(" Sch");
  }

  if (digitalRead(14) == 1) {
    lcdI2C.selectLine(2);
    lcdI2C.print("Watering Now");
  }
  else
  {

    if (int(timeClient.getHours()) < 6 && morTime == 1 && autoSch == 0) {
      Blynk.syncAll();

      lcdI2C.selectLine(2);
      lcdI2C.print("Auto Wtr at: 6");
    } else if (int(timeClient.getHours()) < 12 && afterTime == 1 && autoSch == 0) {
      Blynk.syncAll();

      lcdI2C.selectLine(2);
      lcdI2C.print("Auto Wtr at: 12");
    } else if (int(timeClient.getHours()) < 18 && eveTime == 1 && autoSch == 0) {
      Blynk.syncAll();
      lcdI2C.selectLine(2);

      lcdI2C.print("Auto Wtr at: 18");
    } else if (int(timeClient.getHours()) >= 18 && morTime == 1 && autoSch == 0) {
      Blynk.syncAll();
      lcdI2C.selectLine(2);

      lcdI2C.print("Auto Wtr at: 6");
    } else {
      Serial.println(timeClient.getHours());
    }

  }

}

void loop()
{
  Blynk.run();
  time_run();
  lcd();
  timeClient.update();

  if (waterNow == 1) {
    waterNowrun();
  }
  if (autoSch == 0) {
    auto_run1();

  } else {
    sch_run2();

  }

}
void setup()
{
  dht.begin();
  lcdI2C.begin(LCD_COLUMNS, LCD_ROWS, LCD_ADDRESS, BACKLIGHT);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);
  pinMode(14, OUTPUT);
  digitalWrite(14, LOW);
  pinMode(16, INPUT_PULLDOWN_16);

  Serial.begin(9600);
  //WiFi.begin(ssid, password);
  Blynk.begin(auth, ssid, pass);
  while ( WiFi.status() != WL_CONNECTED ) {
    delay ( 500 );
    Serial.print ( "." );
  }
  timeClient.begin();
}

```

# Answer
> 2 votes
I am assuming after you start watering you want to set `V10` to `0` after 3 seconds.

First, you will have to set `waterNow` to `0` after you start watring. Otherwise `waterNowrun()` will keep executing.

Second, you need to keep track of the 'watering' state so that you know that you have to start tracking the time.

Third, save the time when the watering started so that you can compare with the current time to see if your '3 seconds' has been passed.

Here is a simple example:

```
// Global variables
const long int MAX_TIME_THRESHOLD_MS = 3000;
bool WateringStarted = false;
long int WateringStartTime = 0;

... ... ...

void waterNowrun()
{
  if (waterNow == 1)
  {
    digitalWrite(14, HIGH);
    Blynk.virtualWrite(V5, 255);
    lcdI2C.selectLine(2);
    lcdI2C.print("Watering Now     ");

    waterNow = 0;
    WateringStarted = true;
    WateringStartTime = millis();

  }
  else   // <------ Why do you even have else! You only call waterNowrun() when waterNow == 1
  {
    digitalWrite(14, LOW);
    Blynk.virtualWrite(V5, 0);
  }
}

... ... ...

void loop()
{
  ... ... ...

  if(WateringStarted && (millis() - WateringStartTime) > MAX_TIME_THRESHOLD_MS)
  {
    WateringStarted = false;
    Blynk.virtualWrite(V10, 0);
    Blynk.syncAll();
  }

  ... ... ...

}

```

I haven't run this code and don't have your setup to check it either. But it should give you some idea. Also, check the comments to your question for some more information about `millis()`.

---
Tags: esp8266, nodemcu, millis, blynk
---


title: Add nRF24L01 to a project

text:
# Question
Title: Add nRF24L01 to a project
I Have a Liquid Level Project that Currently uses an Oled display. I have just discovered the existence of the nRF24L01 wireless communication module; and it is exactly what I need to make my project more user friendly.

Eventually I want to have a dashboard that brings all my info together in one place, but for now I just want to figure out how to get my Liquid Level Project transmitting, and receive the data on another Arduino and view it on the Serial monitor. As is all it does is print out "?" in the Serial monitor.

I have this Sketch on the Liquid Level Project Arduino:

```
#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiAvrI2c.h"
SSD1306AsciiAvrI2c oled;
#define I2C_ADDRESS 0x3C
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

double SensorAnalogValue;
uint8_t calculation=1;
String Show_value;

//create an RF24 object
RF24 radio(9, 8);  // CE, CSN

//address through which two modules communicate.
const byte address[6] = "00001";

void setup()
{

  Serial.begin(9600);
  oled.begin(&Adafruit128x64, I2C_ADDRESS);
  oled.setFont(CalLite24);
  oled.clear();

  radio.begin();

  //set the address
  radio.openWritingPipe(address);

  //Set module as transmitter
  radio.stopListening();

}

void loop()
{

  SensorAnalogValue = analogRead(A0) * 5.0 / 1023.0;
  if (SensorAnalogValue < 1.726) {
    calculation=0;
    Show_value="Low";
  }
  if (SensorAnalogValue > 4.04) {
    calculation=0;
    Show_value="High";
  }
  if(calculation!=0){
  //  Serial.println(SensorAnalogValue);
    Show_value=(String)Liquid_Volume(SensorAnalogValue);
  }
  Serial.println(SensorAnalogValue);

oled.setCursor(20, 0);
  oled.print(Show_value);
  oled.print(" L");
  oled.println(" ");
  oled.print(Show_value);
  oled.print("L");
  oled.println(" ");
delay(500);
   oled.clear();

  radio.write(&Show_value, sizeof(Show_value));
  delay(1000);

  calculation=1;
}
int Liquid_Volume(double Volt) {
  double A =   2.81842;
  double B = -11.00151 ;
  double C =  14.4765 ;
  double D =  28.73579 ;

  return A * Volt * Volt * Volt + B * Volt * Volt + C * Volt + D;
}

```

And the Receiver has this:

```
//Include Libraries
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

//create an RF24 object
RF24 radio(9, 8);  // CE, CSN

//address through which two modules communicate.
const byte address[6] = "00001";

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

  radio.begin();

  //set the address
  radio.openReadingPipe(0, address);

  //Set module as receiver
  radio.startListening();
}

void loop()
{
  //Read the data if available in buffer
  if (radio.available())
  {
    char Show_value[32] = {0};
    radio.read(&Show_value, sizeof(Show_value));
    Serial.println(Show_value);
  }
}

```

I think the problem is in:

```
radio.write(&Show_value, sizeof(Show_value));

```

I believe "radio.write" is used kinda like Serial.print, or oled.print, But I don't really understand the "sizeof" part, maybe that is the problem?

# Answer
```
radio.write(&Show_value, sizeof(Show_value));

```

> I believe "radio.write" is used kinda like Serial.print, or oled.print, But I don't really understand the "sizeof" part, maybe that is the problem?

Sort of. There's kind of two interrelated problems. The major one is that the actual data of a `String` is not contained with the actual `String` type itself. It's allocated on the heap. What the `String` class contains is a pointer to it and some numbers for tracking the allocated size and amount used.

So the first problem is you're not reading the memory that actually contains the text inside the string.

`sizeof(Show_value)` evaluates to the size in bytes of the `String` class itself, which is the size of a pointer and a couple of integers, about 6 bytes, and not the size of the content of the string.

So you're sending a pointer (a memory address) that the receiver wouldn't know what to do with, and some information about how much was allocated and used and nothing of the String content.

Try:

```
radio.write(Show_value.c_str(), Show_value.length());

```

`.c_str()` gets a pointer to the actual string content itself. And `.length()` is the actual size of the used part of the `String`'s allocated area on the heap.

That said, it's better to avoid `String` where you reasonably can.

---

Regarding:

> Does this also mean I need to `replace radio.read(&Show_value, sizeof(Show_value));`

It would. Doing that is a bit more complicated since `.c_str()` yields `const char *`; `String` isn't designed to make write-access to its underlying data as easy.

Without hacking your way around `String`'s expectations, that would require using a temporary buffer. Something like:

```
char buffer[33] = "";  // Note: this will actually fill the entire buffer with '\0', which some find a surprise.
// The idea in the above is to accommodate the maximum RH24L01 packet size 32 bytes plus room for a null terminator.

radio.read(buffer, sizeof buffer - 1);  // We're only making the 32 byte chunk available to the .read() call, and leaving the last byte to it's '\0' value to force null termination in any case.

String s = buffer;

```

This assuming that you're either filling the packet with bytes, or including the null terminator in the packet, or both. If you're using a dynamic payload size, rather than initializing the array with `= "";`, it could be left uninitialized and the received packet size could be used to place the null terminator at the location needed.

You could wrap this in a function if you plan on doing it a lot. But again, it's probably better if you can just use the array and not work with `String`.
> 1 votes

---
Tags: nrf24l01+
---


# Question
Title: Not have to wait for if statement to run
I need some advice. I am trying to code a setup of 4 stepper motors that are connected to a keypad and 2 DC-motors that run a conveyor belt. My goal is to be able to push a key, the correspondning stepper motor starts and the DC-motors starts as well and run for a couple of seconds after the stepper. However, I want to be able to push multiple keys while the DC-motors are running. Right now I need to wait for the DC-motors to be done before I can push another key. How can I make this happen?

I think there will be issues if I code it with a timer since the keys are waiting for an input. I don't have any sensors.

This is my code:

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

const int stepsPerRevolution = 1024;

Stepper myStepper1(stepsPerRevolution, 22, 26, 24, 28);
Stepper myStepper2(stepsPerRevolution, 32, 36, 34, 38);
Stepper myStepper3(stepsPerRevolution, 23, 27, 25, 29);
Stepper myStepper4(stepsPerRevolution, 33, 37, 35, 39);

const int IN1 = 47;
const int IN2 = 45;
const int IN3 = 51;
const int IN4 = 49;

const int ENA = 43;
const int ENB = 53;

const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
  {'D','C','B','A'},
  {'H','G','F','E'},
  {'L','K','J','I'},
  {'P','O','N','M'}
};

byte rowPins[ROWS] = {2, 3, 4, 5}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {6, 7, 8, 9}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){
  Serial.begin(9600);
   myStepper1.setSpeed(10);
   myStepper2.setSpeed(10);
   myStepper3.setSpeed(10);
   myStepper4.setSpeed(10);

  pinMode (IN1, OUTPUT);
  pinMode (IN2, OUTPUT);
  pinMode (IN3, OUTPUT);
  pinMode (IN4, OUTPUT);
  pinMode (ENA, OUTPUT);
  pinMode (ENB, OUTPUT);

}

void loop(){
 // char key = keypad.getKey();
 char key = keypad.waitForKey();

   if (key){
    Serial.println(key);
//control speed
  analogWrite(ENA, 200);
  analogWrite(ENB, 200);
//control direction
int onTime   = 5000;
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);

// ----------------------------------Stepper1-----------------------------

        // just print the pressed key
   if (key == 'A' ){
    Serial.println(key);
     // step one revolution in one direction:
  Serial.println("clockwise");
  myStepper1.step(256);
  delay(100);
}

  // just print the pressed key
   if (key == 'E' ){
    Serial.println(key);
     // step one revolution in one direction:
  Serial.println("clockwise");
  myStepper1.step(512);
  delay(100);
}

  if (key == 'I' ){
    Serial.println(key);
     // step one revolution in one direction:
  Serial.println("clockwise");
  myStepper1.step(768);
  delay(100);
  }

  if (key == 'M' ){
    Serial.println(key);
     // step one revolution in one direction:
  Serial.println("clockwise");
  myStepper1.step(1024);
  delay(100);
  }

//-----------------------Stepper2------------------------

if (key == 'B' ){
    Serial.println(key);
     // step one revolution in one direction:
  Serial.println("clockwise");
  myStepper2.step(256);
  delay(100);
}

  // just print the pressed key
   if (key == 'F' ){
    Serial.println(key);
     // step one revolution in one direction:
  Serial.println("clockwise");
  myStepper2.step(512);
  delay(100);
}

  if (key == 'J' ){
    Serial.println(key);
     // step one revolution in one direction:
  Serial.println("clockwise");
  myStepper2.step(768);
  delay(100);
  }

  if (key == 'N' ){
    Serial.println(key);
     // step one revolution in one direction:
  Serial.println("clockwise");
  myStepper2.step(1024);
  delay(100);
  }

 //------------------------Stepper3--------------------

if (key == 'C' ){
    Serial.println(key);
     // step one revolution in one direction:
  Serial.println("clockwise");
  myStepper3.step(256);
  delay(100);
}

  // just print the pressed key
   if (key == 'G' ){
    Serial.println(key);
     // step one revolution in one direction:
  Serial.println("clockwise");
  myStepper3.step(512);
  delay(100);
}

  if (key == 'K' ){
    Serial.println(key);
     // step one revolution in one direction:
  Serial.println("clockwise");
  myStepper3.step(768);
  delay(100);
  }

  if (key == 'O' ){
    Serial.println(key);
     // step one revolution in one direction:
  Serial.println("clockwise");
  myStepper3.step(1024);
  delay(100);
  }

 //------------------------Stepper4--------------------

if (key == 'D' ){
    Serial.println(key);
     // step one revolution in one direction:
  Serial.println("clockwise");
  myStepper4.step(256);
  delay(100);
}

  // just print the pressed key
   if (key == 'H' ){
    Serial.println(key);
     // step one revolution in one direction:
  Serial.println("clockwise");
  myStepper4.step(512);
  delay(100);
}

  if (key == 'L' ){
    Serial.println(key);
     // step one revolution in one direction:
  Serial.println("clockwise");
  myStepper4.step(768);
  delay(100);
  }

  if (key == 'P' ){
    Serial.println(key);
     // step one revolution in one direction:
  Serial.println("clockwise");
  myStepper4.step(1024);
  delay(100);
  }

//---------DC_Motor---------

   delay(onTime);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
    digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);

 }
}

```

# Answer
> 1 votes
The `delay(onTime);` statement in the `//---------DC_Motor---------` section of your code is preventing anything else taking place until the end of the DC motor run. Instead of delaying, you need to test how long the motor has been running, and do nothing if that time has not been reached yet. As others have pointed out, the BlinkWithoutDelay example program demonstrates how to do this. But in short, the motor section needs to do:

```
// Start motor here
timeMotorStarted = millis();
   :
   :
   :
if( millis() - timeMotorStarted > onTime ){  // has motor run long enough?
  // stop the motor
}

```

---
Tags: stepper
---


# Question
Title: StoreProhibited error while trying to read file to PROGMEM
I'm trying to read a file from micro SD on an ESP32-cam board and upload to an FTP server, but when I try to read data from the opened file to an unsigned char, it gives me the following error:

```
Guru Meditation Error: Core  1 panic'ed (StoreProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x4008c674  PS      : 0x00060030  A0      : 0x800ed1c7  A1      : 0x3ffb1e20
A2      : 0x00000000  A3      : 0x3ffd7c78  A4      : 0x00000080  A5      : 0x00000000
A6      : 0x474e5089  A7      : 0x0a1a0a0d  A8      : 0x00000000  A9      : 0x3ffb1df0
A10     : 0x00000080  A11     : 0x3ffb66e4  A12     : 0x3ffd7c78  A13     : 0x00000080
A14     : 0x00002494  A15     : 0xff000000  SAR     : 0x00000018  EXCCAUSE: 0x0000001d
EXCVADDR: 0x00000000  LBEG    : 0x4008c670  LEND    : 0x4008c68c  LCOUNT  : 0x00000007

ELF file SHA256: 0000000000000000

Backtrace: 0x4008c674:0x3ffb1e20 0x400ed1c4:0x3ffb1e30 0x400ed245:0x3ffb1e60 0x400d06e7:0x3ffb1e80 0x400d084f:0x3ffb1f20 0x400d2b5a:0x3ffb1fb0 0x4008efde:0x3ffb1fd0

Rebooting...

```

The code is the following:

```
// Wifi and FTP Client Lib
#include <WiFi.h>
#include <WiFiClient.h>
#include "ESP32_FTPClient.h"

// MicroSD
#include "driver/sdmmc_host.h"
#include "driver/sdmmc_defs.h"
#include "sdmmc_cmd.h"
#include "esp_vfs_fat.h"

// FTP Server credentials
char ftp_server[] = "192.168.1.50";
char ftp_user[]   = "username";
char ftp_pass[]   = "password";

// wifi access
const char* ssid = "ssid";
const char* password = "psk";

// file to be read and uploaded
FILE *fileUpload = NULL;

// ftp client object
ESP32_FTPClient ftp (ftp_server, ftp_user, ftp_pass);

// micro sd initialization
static esp_err_t init_sdcard()
{
  esp_err_t ret = ESP_FAIL;
  sdmmc_host_t host = SDMMC_HOST_DEFAULT();
  sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
  esp_vfs_fat_sdmmc_mount_config_t mount_config = {
    .format_if_mount_failed = false,
    .max_files = 10,
  };
  sdmmc_card_t *card;
  ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card);
}

void FTP_upload( void );
void FTP_upload()
{

  // initialize file name
  char fileName[100];
  sprintf(fileName, "/sdcard/img.png");
  fileUpload = fopen(fileName, "r+");

  // notify reading of the file
  Serial.print("Reading file: ");
  Serial.println(fileName);
  if (fileUpload == NULL)
  {
    Serial.println("Cannot open file");
    return;
  }

  // retrieve file size
  fseek(fileUpload, 0, SEEK_END);
  long int size = ftell(fileUpload);
  fclose(fileUpload);

  // print file size to serial
  Serial.print("File size: ");
  Serial.println(size);

  // Reading data to array of unsigned chars
  fileUpload = fopen(fileName, "r+");
  unsigned char * in PROGMEM = (unsigned char *) malloc(size);

  // display allocated memory
  Serial.print("Allocated memory: ");
  Serial.println(sizeof(in));

  // read file to allocated memory
  int bytes_read = fread(in, sizeof(unsigned char), size, fileUpload); // <------- THIS ROW RISES THE ERROR

// close file
  fclose(fileUpload);

  // Open FTP connection
  Serial.println("Starting FTP upload...");
  ftp.OpenConnection();

  //Create a file and write the image data to it;
  ftp.InitFile("Type I");

  // change remote directory
  ftp.ChangeWorkDir("/Shared/");

  // specify remote file name
  String strNome = "img.png";

  // convert String to char
  const char *f_name = strNome.c_str();

  // create a new file with the given name inside the remote directory
  ftp.NewFile( f_name );

  // write data read above from local file to remote file
  ftp.WriteData(in, sizeof(in));

  // close remote file
  ftp.CloseFile();

  // notify completed upload
  Serial.println("File uploaded successfully");

  // wait
  delay(100);

}

void setup() {

  // begin serial communication
  Serial.begin(115200);

  // initialize micro sd
  esp_err_t errSD = init_sdcard();
  if (errSD != ESP_OK) {
    Serial.printf("Cannot initialize SD. Error code: 0x%x", errSD);
    return;
  }

  // begin wifi connection
  WiFi.begin(ssid, password);

  // wait for the connection to be estabilished
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  // notify successful connection
  Serial.println("");
  Serial.println("WiFi connected");

  // show the assigned IP
  Serial.print("IP: ");
  Serial.println(WiFi.localIP());

  // call the FTP upload procedure
  FTP_upload();

}

void loop() {
  // empty
}

```

How can I solve this? Thank you

# Answer
> 1 votes
Solved, I changed the method a little.

In a loop, I read a portion of the file and write it to the opened FTP remote file, then I close both at the end of the cycle

```
// open FTP connection
ftp.OpenConnection();

// open local file
fileUpload = fopen("/sdcard/img.png", "r+");

// initialize file type
ftp.InitFile("Type I");

// change remote directory
ftp.ChangeWorkDir("/Shared/");

// define remote file name
String strName = "img.png";

// convert to char
const char *f_name = strName.c_str();

// create remote file with given name
ftp.NewFile( f_name );

// read all file in a loop
unsigned char buff[64];
while(!feof(fileUpload)){

    // read a portion of the file
    fread(buff, sizeof(char), sizeof(buff), fileUpload);

    // write that portion to the remote file
    ftp.WriteData(buff, sizeof(buff));
}

// close both the local and the remote file
fclose(fileUpload);
ftp.CloseFile();

```

---
Tags: arduino-ide, esp32, sd-card
---


# Question
Title: Unexpected output for simple code involving calculating a time interval of 10ms
I had written some code that involved doing something after 10 milliseconds had elapsed, however it was performing unexpectedly. Upon debugging, I think I have identified the error, and I wrote some code with *just* that block:

```
unsigned long int newtime=0;
unsigned long int prevtime=0;
int time;
void setup()
{
  Serial.begin(9600);
}

void loop()
{
newtime=millis();
time=newtime-prevtime;
if(time==10){
  Serial.println(prevtime);
  prevtime+=10;
}

}

```

The serial monitor "freezes on 150. it shows the values 0,10,20...as expected but it freezes on 150...and then nothing happens.

What exactly is causing this?

# Answer
> 3 votes
The problem is, that you are filling up the Serial buffer rather fast, because you try to send ASCII numbers every 10ms at only 9600ms. When the buffer is full, `Serial.println()` will wait, until there is enough space free in the buffer for the current data. That makes your loop lasting significantly longer.

In that case the time, where the `time` is exactly 10 is missed. Thus the code does nothing at that point, until time rolls over and gets 10 again (48 days I think).

While you can mitigate the problem by using a higher baudrate, the main problem is still

```
if(time==10){

```

You have only provided an example code. Your real code might sometimes take longer than 10ms out of some other reason (actually this already gets critical, when the loop takes longer than 1ms, since it then might already miss the one moment, where `time` is 10). To futureproof your code and make sure, that you don't hunt down the same bug again and again, you should do, what you were told in the comments, and use

```
if(time>=10){

```

Depending on your code the event will still happen after 10ms the absolute most of the time. But this variant also doesn't break, if the loop takes longer than 10ms sometimes.

# Answer
> 2 votes
your logic is just tricky to confuse. It is repeatable because along as you not change the if logic, the code is going to run till it displays 150. then it will stop. You can also check the same behaviour here

Once the time difference is not exactly equal to 10, the if part will not be executed. Hence, the `prevtime` will not catch up with the `newtime` anymore. newTime will soon grow to be bigger and the difference will always be greater than 10.

I suggest visiting https://www.arduino.cc/en/Tutorial/BuiltInExamples/BlinkWithoutDelay to get some hints on tracking time in a safer way.

---
Tags: programming, c++
---


# Question
Title: How do I make my Arduino do a specific action when the computer is locked/unlocked?
I have a windows computer connected to my Arduino Uno. I work in a area with a bunch of cubicles and we leave our desk fairly regularly to go and troubleshoot other computers (I'm a service desk technician). When we leave we are instructed to raise and lower a small flag so management can see whether or not we are sitting at our desk. I've attached my arduino to a servo motor with the following code.

```

#include <Servo.h>

Servo myservo;  // create servo object to control a servo
#define servoPin 3 //~
#define pushButtonPin 2

int angle =0;    // initial angle  for servo
int angleStep =20;
const int minAngle = 0;
const int maxAngle = 90;

int buttonPushed =0;

void setup() {
  // Servo button demo by Robojax.com
  Serial.begin(9600);          //  setup serial
  myservo.attach(servoPin);  // attaches the servo on pin 3 to the servo object
  pinMode(pushButtonPin,INPUT_PULLUP);
   Serial.println("Nathan's Status flag");
}

void loop() {
  if(digitalRead(pushButtonPin) == LOW){
    buttonPushed = 1;
  }
   if( buttonPushed ){
  // change the angle for next time through the loop:
  angle = angle + angleStep;

    // reverse the direction of the moving at the ends of the angle:
    if (angle <= minAngle || angle >= maxAngle) {
      angleStep = -angleStep;
       buttonPushed = 0;
    }
    myservo.write(angle); // move the servo to desired angle
      Serial.print("Moved to: ");
      Serial.print(angle);   // print the angle
      Serial.println(" degree");
  delay(100); // waits for the servo to get there
   }
}

```

We also have a policy that we need to keep our computers locked for obvious reasons. I learned my lesson with that early on. I would like to edit my code so that when I lock my computer the flag goes down, then when my computer is unlocked it goes back up. That way as long as I remember to keep my computer locked when I'm away I don't have to worry about the flag. Here is my breadboard/arduino layout.  I also have processing on my computer and am planning on using that. (https://processing.org/)

Any help is greatly appreciated.

# Answer
Read a value through serial (what exactly is entirely up to you) to do the same job the button does now.

Use `Serial.read()` to get that data, and `Serial.available()` to know if there is any data to read.

How you generate that value on the PC to send through serial we cannot help you with, as that is outside the scope of this site.
> 1 votes

---
Tags: arduino-uno, servo, processing-lang
---


# Question
Title: Is it possible to read extended ASCII from the serial port?
My project requires that `Serial.read()` be able to accept extended ASCII characters (`0x80` \<=\> `0xFF`). For example, I would expect reading the character `¥` to yield the decimal value `157`. Instead, the `read()` command has two successful reads, with the values: `194` and `165`. Of course, I could create a lookup table and convert, but this is not a viable option. I am conforming to the `Grbl` standard protocol, which uses these single-byte extended ASCII characters as **interrupts**. Such a two-byte structure precludes a simple peek/read approach necessitated by the protocol.

**Edit** I tried to simplify the question for this context, but failed to account for the fact that the Arduino IDE will send the input as Unicode. Regardless, it still does not work when sending bytes directly. Namely, if I send the byte `0x93` via C# as `Serial.Write("\u0093")`, the Arduino's `Serial.read()` does not see any bytes available. Sending normal ASCII, e.g., `Serial.Write("\u0018")`, works fine.

# Answer
Yes, of course, you can read any byte sequence. As you have experienced, if you send the byte values 194 and 165, your Arduino reliably reads 194 and 165.

Now, you have to be aware that there are tons of incompatible character encodings that could all be called “extended ASCII”. I do not know which one you have in mind. Maybe there is such an encoding where “¥” has the code point 157. Nowadays, however, almost any modern computer system uses Unicode, and serializes the characters using UTF-8. The character “¥” is serialized in UTF-8 as the pair of bytes 194 and 165.

If you want to use the Grbl protocol, send interrupts as *bytes*, do not think about them as “characters”.
> 1 votes

---
Tags: serial
---


title: Interfacing SPI (MCP3903)

text:
# Question
Title: Interfacing SPI (MCP3903)
I'm trying to interface MCP3903. I haven't really don't any SPI interfacing before and I can't seem to find clear enough answer for newbs. Please bare with me.

I'm trying to use this library. http://www.kerrywong.com/2014/05/10/mcp3903-library/

On the website there is the following circuit diagram.

I can see SDI, SDO pins on the ESP module, how do I connect the SCK and CS pins? If they can be any pins how do I declare them on the test program on the website?

Thank you

# Answer
> 0 votes
SPI0 and SPI1 are used internally to access the ESP32’s attached flash memory. SPI2 and SPI3 are general purpose SPI controllers, sometimes referred to as HSPI and VSPI, respectively. They are open to users.

A quick google search shows:

So you can use IO5, IO18, IO19 and IO23.

---
Tags: esp32, spi, adc
---


title: void declaration error

text:
# Question
Title: void declaration error
I am new to Arduino and C++ and I was practicing with a traffic light project.

This is my code:

```
int red = 10;
int yellow = 9;
int green = 8;

void setup() {
  pinMode(red,OUTPUT);
  pinMode(yellow,OUTPUT);
  pinMode(green,OUTPUT);
}

void loop() {
  changelights();
  delay (15000);
}

void changelights{
  // 1st action: green off to yellow
  digitalWrite(green, LOW);
  digitalWrite(yellow, HIGH);
  delay (3000)
  // 2nd action: tellow to red
  digitalWrite(yellow, LOW);
  digitalWrite(red, HIGH);
  //3rd action: caution light
  digitalWrite(yellow, HIGH);
  delay (3000)
  //4th action: caution to go
  digitalWrite(red,LOW);
  digitalWrite(yellow, LOW);
  digitalWrite(green, HIGH);
}

```

I tried compiling it and returned an error message that said that I did not declare my "changelights" function. What should I do to fix this?

Thank you very much

# Answer
You forgot to put the parenthenses `()` after the name of the function `changelights`. They are there to declare variables you can use later in the code like that:

```
void function(int a){
  a+=1;
  return a;
}

```

To fix your error just change

```
void changelights{

```

to

```
void changelights(){

```

Keep in mind if you want to program C++ (which would be Off-Topic here, but you mentioned it in your question) you have to declare the function in the beginning or mention it.
> 3 votes

---
Tags: arduino-uno
---


title: Arduino ADC converter calculation

text:
# Question
Title: Arduino ADC converter calculation
I am trying to choose a wire encoder for my project. So far, I found this wire encoder (see link). Assuming the measurement range of my cylinder is 1 m. Then, with a 10 bit ADC converter of my Arduino Mega2560, I would have a resolution of 0.09cm (= 100cm/1024). But, lets say some cylinder only have a measurement range of 0.5m. Then the resolution would be 0.048 (=50cm/1024).

I can see that I am missing something here, because the resolution of the later case should be worse than the case with the full measurement range 1m. I would be appreciate for any tipps.

---

Edit:

* Cylinder's movement range 0~1m
* Wire encoder's measurement range 0~1.25m
* Wire encoder's analog output 0~10v
* ADC resolution 10 bit

# Answer
Your calculation is not correct. The encoder has its 0 to 10V output voltage distributed over the whole distance, that the cable can reach, so 1.25m. And that gives you the resolution: `1.25m/1024 = 1.22mm`. The resolution doesn't change, if you use less than the maximum length. It's still the same resolution of about 1.22mm. The encoder doesn't care, if you are only using 1m of its range.
> 1 votes

---
Tags: arduino-mega, adc
---


# Question
Title: Simulate motor encoder quadrature signals using an Arduino UNO
I'm supposed to write a raspberry pi and arduino code to read the RPM of a motor with an encoder attached to it. However, I'm having weird numbers and I'm unsure about the specs on the motor and the encoder. So I thought it would be smart to use a second arduino to simulate the motor with encoder.

The simulator would need to produce a 2 signals representing the two signals from the encoder. I want to be able to set the frequency and phase shift of these signals in software to imitate changes in speed and direction of the motor rotation. Forward would have one signal 90 degrees ahead, and then reverse having that same signal to be 90 degrees behind. So phase difference of plus or minus 90 degrees.

I'd like to eventually have the simulator be able to simulate motor actions like oscillating between forward and reverse 5 seconds each, or forward for 5 seconds and then stop completely.

I found this code by bigjosh which is more or less what I want to do. However, that code doesn't allow for a shift of -90 deg by default. I know there's a comment there to change it, but I'm not knowledgeable enough to understand what's going on exactly. I'd like someone to help me with that.

# Answer
Wow, that turned out to be way harder than I expected. It is very hard to do cleanly on the AVR timer. But I was able to come up with this working function, which I think is what you are looking for...

```
// freq_hz is frequency in hertz from 122 to 4,000,000
// shift_deg is phase shift between output A and output B in degrees (values outside -180 to +180 are normalized)

// Note that at frequencies above 44KHz you will loose precision on phase shift. At 4Mhz, everything is rounded to just 0 or +/-90 degrees.
// Note that all timing happens in 1/16Mhz increments, so frequencies that do not land on integer multipules of that will be aproximiate.
// Use startWaveforms() directly for more precise control.

void startQuadrature( unsigned long freq_hz , int shift_deg  );

```

It can glitch at start-up, shutdown, and changes in speed and direction... but so can a motor encoder so I guess that is ok. It would be possible to create a glitch-free version but more work.

Github repo here... https://github.com/bigjosh/Quadrature

So, to simulate a motor going forward with 50KHz pulse rate, you would use something like...

`startQuadrature( 50000 , +90);`

...and the same pulse rate going backwards would be...

`startQuadrature( 50000 , -90);`

Do note that if you connect an Arduino UNO output pin to a Raspberry Pi input pin that it will likely damage the Pi. This is because the UNO outputs 5 volts for a "1" signal, but the Pi can only tolerate a maximum 3.3V on any pin. You can google "5V 3.3V level shifting" for solutions to this problem.
> 2 votes

---
Tags: motor
---


# Question
Title: unexpected behaviour of encoder with increasing rpm
I am using a DC motor with encoder, and I am trying to calculate how many pulses are recorded in every one second interval. (note that the power source is of 12V for the motor)

**Circuit and code:**

```
int encpin=3;
volatile long npc=0; //new pulse count
volatile long opc=0;  //original pulse count
volatile long pulsecount;
unsigned long int newtime;
unsigned long int prevtime=0;
unsigned long int time;
void setup()
{
  pinMode(encpin, INPUT_PULLUP);
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(encpin),function,RISING);
}
void function(){
  npc++;
}
void loop()
{
 newtime=millis();
 time=newtime-prevtime;
 pulsecount=npc-opc;
  if(time==1000){
    Serial.println(pulsecount);
    prevtime+=1000;
    opc=npc;
  }
}

```

It seems to be rather intuitive that increasing the rpm should increase the number of pulses recorded in one second. However, the results are rather erratic:

```
 RPM  PULSECOUNT
  26    2365
  32    2367
  38    2400
  44    2375
  52    2400
 116    2412
 142    2384
 195    2416
 280    2406
 350    3008
 416    1580
 520    1975
 624    2370
 730    2334
2737    2188

```

**Increasing RPM sometimes increases the pulsecount, but sometimes decreases it....what could be the reason for this behaviour?**

# Answer
> 1 votes
I think the problem is in the tinkercad simulation: The encoder is attached to the motor and the motor is always rotating at the same speed. Selecting a different RPM on the component changes the gear ratio and the RPM of the shaft, but not of the motor. That means that the number output after 1s should be always the same. Why it is not exactly the same, only the programmers of the simulation can tell. It might have to do with simulation speed, because I get totally different numbers there.

To tell exactly what is going on, a documentation of the components in the simulation and of the simulation would be necessary.

# Answer
> 1 votes
One important principle to learn when working with interrupts is that of *atomic operations*. It is vital, when working with any data that cannot be manipulated by one single assembly instruction, that you protect against that data being changed midway through any reading of that data.

In your situation you are working with 32-bit values. On an 8-bit microcontroller those take many many instructions to manipulate, and at any time during that manipulation the interrupt can be triggered and change the value, corrupting your readings.

There is a concept in programming called *critical sections*. These are "blocked off" bits of code where no interrupts are allowed to happen while you do whatever is needed to your shared variables. For obvious reasons you want to keep those sections as brief as possible.

Also you don't need to calculate the pulse count by comparing it to the previous count - just start from 0 each second. And on the topic of a second, it's best to check if *at least* a second has passed. There's always a chance you may see 1001ms instead of 1000ms. A slim chance, but best to be safe.

Here's an example, using your code as a base:

```
void loop() {

    if (millis() - prevtime >= 1000) { // you should check for more time passing than you expect
        prevtime += 1000; // Don't assume you always had 1 second, force it instead

        // This block is the "critical section". Keep it as short as possible
        // so just grab the data and reset the count.
        noInterrupts(); // Stop any interrupts happening
        uint32_t currentCount = npc; // Grab this second's count
        npc = 0; // And reset the count to zero
        interrupts(); // Release the block on interrupts

        // And output the results.
        Serial.println(currentCount);
    }

}

```

---
Tags: rotary-encoder
---


# Question
Title: What is difference between ATMEGA32 and ATMEGA328?
I'm new in electronics. Just playing with Arduino boards.I just wanted to program ATMEGA328 micro-controller and use it without Arduino for compact design for my personal hobby project. I found there are ATMEGA32 and ATMEGA328 micro controllers in my local store. So, I wanted to know can I use ATMEGA32 instead of ATMEGA328 ? Which one is latest and whats are benefits. Thanks in advance.

# Answer
> 1 votes
I cannot tell for sure, but from a cursory look at the datasheets, the ATmega32 *looks* older:

* 16 MHz maximum frequency v.s. 20 MHz for the ATmega328
* 4.5 V minimum supply voltage v.s; 1.8 V for the ATmega328
* only one PWN channel per 8-bit timer

From an Arduino-programming point of view, I would prefer the 328, as it would allow you to prototype your code on an Uno, and then move it to the bare MCU, knowing it would work identically. The ATmega32 would be worth consideration if you need more IO than the Uno can provide.

# Answer
> 3 votes
I can't post comments. One difference is that the ATmega32 has **JTAG**; ATmega328P has not.

# Answer
> 1 votes
To answer this you'd need to study the according data sheets:

ATmega32
ATmega32u4
ATmega328
ATmega328P
ATmega328PB

Despite a similar name, the chips are quite different.
32u4 for examle has USB built in.
328PB has more 16-bit Timer/Counters.
... and many more differences.

They only differ on the hardware features and can be programmed in more or less the same way. It is up to you to choose which one you want to use.

---
Tags: arduino-uno, atmega328, atmega32u4
---


# Question
Title: ESP8266: Interfacing MAX485 TTL-to-RS485 on serial port
I am using the ESP8266 NODEMCU. I am aware that the CH341 on the NodeMCU is bridged to the serial pins GPIO3(Rx) and GPIO1(Tx). Hence, any data send on Rx and Tx is also visible on the serial monitor.

I need to interface MAX485 TTL-to-RS485 to the ESP8266 on different serial pins (other than GPIO3 and GPIO1).

Is there a way to configure other pins as Rx and Tx?

Please suggest any other ways to achieve this.

EDIT-1: I need to use two serial ports at the same time (one with the CH341 and another with TTL-to-RS485). Please help with this.

# Answer
You can't redefine pins on the ESP8266. You can, though, use SoftwareSerial to emulate a serial port. There's plenty of examples.

Also you need to use the MAX**3**485 on 3.3V devices. The MAX485 is for 5V devices.
> 3 votes

# Answer
Regarding this:

> Please suggest any other ways to achieve this.

The `SoftwareSerial` mention in Majenko's answer is one of those other ways.

There's also a `.swap()` function on the Serial interface that will remap the UART from its normal position talking to the host to GPIO15 and GPIO13. If you only need to talk to one device at a time, that may also be an option.

There's also a second transmit-only UART (also mentioned in previous link), so if you only need to transmit on one of the interfaces, that is an option. And there's the possibility of using the transmit-only UART together with using `SoftwareSerial` (or something like it) to complete the receive half.

Another option might be interpose a SPI-interfaced UART chip, between the ESP8266 and the RS485 transceiver, so that it's just SPI from the ESP8266 side. It is also possible to find chips that are combined SPI-UART/RS485-transceiver, although the only one I've noticed thus far is a 5V part.
> 2 votes

---
Tags: esp8266, uart
---


title: Using millis() in unsynchronized manner

text:
# Question
Title: Using millis() in unsynchronized manner
I am assuming millis() is a Timer ISR function. If so : When using millis() as mentioned in Arduino Reference : unsigned long currentMillis = millis(); What would happen if the ISR asynchronously changes the value being read in a function. I mean if I have read one byte into currentMillis, but millis had changed the value before the remaining 7 bytes are read.

Cheers and TIA

# Answer
> 2 votes
> I am assuming millis() is a Timer ISR function.

It is a function that retrieves a value that is updated by and ISR.

> What would happen if the ISR asynchronously changes the value being read in a function.

Cannot happen: the value is read with interrupts disabled.

See for example, in the AVR core:

```
// disable interrupts while we read timer0_millis or we might get an
// inconsistent value (e.g. in the middle of a write to timer0_millis)
cli();
m = timer0_millis;
SREG = oldSREG;

```

> I mean if I have read one byte into currentMillis, but millis had changed the value before the remaining 7 bytes are read.

An `unsigned long` is only 4 bytes. That is, until someone comes with a 64-bit Arduino platform.

---
Tags: millis
---


title: Node MCU not functioning correctly

text:
# Question
Title: Node MCU not functioning correctly
i have a node mcu and i uploaded one example code to test it for rf signal decoding it worked. so after that i have written a code based on that and when i uploaded the code my node MCU suddenly isn't working as it should be. It is giving out some random things onto the serial monitor like this:

```
⸮L⸮⸮⸮ՋR(⸮⸮^⸮̓#⸮⸮;'⸮⸮(Zs"⸮⸮Z|⸮⸮⸮'⸮⸮⸮'⸮⸮⸮!#⸮⸮⸮G⸮⸮⸮⸮⸮h⸮y⸮⸮⸮⸮'⸮⸮LD⸮⸮J⸮*J⸮⸮⸮⸮⸮⸮⸮LD⸮⸮⸮⸮F(⸮y⸮⸮؁'1⸮L⸮⸮⸮

```

THE CODE:

```
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <RCSwitch.h>
BlynkTimer clocktime;

#define relayfan 5
#define relaylight 6
#define relaylightb 7
#define relayrandom 2

#define VPIN_BUTTON_1    V12
#define VPIN_BUTTON_2    V13
#define VPIN_BUTTON_3    V14
#define VPIN_BUTTON_4    V15

RCSwitch mySwitch = RCSwitch();

int relayfanstate = HIGH;
int relaylightstate = HIGH;
int relaylightbstate = HIGH;
int relayrandomstate = HIGH;
int mainstate = HIGH;
long code;

char auth[] = "rJUG7fhgXk9Y7OlowTontA1C2irfpgs2";

const char *ssid =  "Nag";
const char *pass =  "87654321";

BLYNK_CONNECTED()
{
  Serial.println("blynk connected first function");
  Blynk.syncVirtual(VPIN_BUTTON_1);
  Blynk.syncVirtual(VPIN_BUTTON_2);
  Blynk.syncVirtual(VPIN_BUTTON_3);
  Blynk.syncVirtual(VPIN_BUTTON_4);
}

BLYNK_WRITE(VPIN_BUTTON_1)
{
  Serial.println("blynk write");
  relayfanstate = param.asInt();
  digitalWrite(relayfan, relayfanstate);
}

BLYNK_WRITE(VPIN_BUTTON_2)
{
  Serial.println("blynk write");
  relaylightstate = param.asInt();
  digitalWrite(relaylight, relaylightstate);
}

BLYNK_WRITE(VPIN_BUTTON_3)
{
  Serial.println("blynk write");
  relaylightbstate = param.asInt();
  digitalWrite(relaylightb, relaylightbstate);
}

BLYNK_WRITE(VPIN_BUTTON_4)
{
  Serial.println("blynk write");
  relayrandomstate = param.asInt();
  digitalWrite(relayrandom, relayrandomstate);
}

void setup()
{
  Serial.begin(9600);
  mySwitch.enableReceive(0);
  pinMode(relayfan, OUTPUT);
  pinMode(relaylight, OUTPUT);
  pinMode(relaylightb, OUTPUT);
  pinMode(relayrandom, OUTPUT);
  digitalWrite(relayfan, HIGH);
  digitalWrite(relaylight, HIGH);
  digitalWrite(relaylightb, HIGH);
  digitalWrite(relayrandom, HIGH);
  Serial.println("Start");
  WiFi.begin(ssid, pass);
  Serial.println("wifi config done");
  Blynk.config(auth);//, ssid, pass);
  Serial.println("Blynk config done");
}

void loop()
{

  if (WiFi.status() != WL_CONNECTED)
  {
    Serial.println("Not Connected");
    Serial.println("Without internet rf code recieving started");
    delay(500);
    if (mySwitch.available())
    {
      Serial.println("Switch available");
      code = mySwitch.getReceivedValue();
      if (mySwitch.getReceivedValue() == 8594433)
      {
        Serial.println("code matched without internet");
        mainstate = !mainstate;
        digitalWrite(relayfan, mainstate);
        digitalWrite(relaylight, mainstate);
        digitalWrite(relaylightb, mainstate);
        digitalWrite(relayrandom, mainstate);
        delay(1000);
        mySwitch.resetAvailable();
      }
      else if(mySwitch.getReceivedValue() == 8594447)
      {
        digitalWrite(relayfan, LOW);
        delay(1000);
        mySwitch.resetAvailable();
      }
      else if(mySwitch.getReceivedValue() == 8594445)
      {
        digitalWrite(relayfan, HIGH);
        delay(1000);
        mySwitch.resetAvailable();
      }
      else if(mySwitch.getReceivedValue() == 8594436)
      {
        relaylightstate = !relaylightstate;
        digitalWrite(relaylight, relaylightstate);
        delay(1000);
        mySwitch.resetAvailable();
      }
      else if(mySwitch.getReceivedValue() == 8594437)
      {
        relaylightbstate = !relaylightbstate;
        digitalWrite(relaylightb, relaylightbstate);
        delay(1000);
        mySwitch.resetAvailable();
      }
      else if(mySwitch.getReceivedValue() == 8594439)
      {
        relayrandomstate = !relayrandomstate;
        digitalWrite(relayrandom, relayrandomstate);
        delay(1000);
        mySwitch.resetAvailable();
      }
    }
  }
  else
  {
    Serial.println(" Connected");
    Blynk.run();
    with_internet();
  }
  clocktime.run();
}

void with_internet()
{
  Serial.println("With internet rf code recieving started");
  delay(500);
  if (mySwitch.available())
  {
    Serial.println("Switch available");
    code = mySwitch.getReceivedValue();
    if (mySwitch.getReceivedValue() == 8594433)
      {
        Serial.println("code matched without internet");
        mainstate = !mainstate;
        digitalWrite(relayfan, mainstate);
        digitalWrite(relaylight, mainstate);
        digitalWrite(relaylightb, mainstate);
        digitalWrite(relayrandom, mainstate);
        Blynk.virtualWrite(VPIN_BUTTON_1, mainstate);
        Blynk.virtualWrite(VPIN_BUTTON_2, mainstate);
        Blynk.virtualWrite(VPIN_BUTTON_3, mainstate);
        Blynk.virtualWrite(VPIN_BUTTON_4, mainstate);
        delay(1000);
        mySwitch.resetAvailable();
      }
      else if(mySwitch.getReceivedValue() == 8594447)
      {
        digitalWrite(relayfan, LOW);
        Blynk.virtualWrite(VPIN_BUTTON_1, LOW);
        delay(1000);
        mySwitch.resetAvailable();
      }
      else if(mySwitch.getReceivedValue() == 8594445)
      {
        digitalWrite(relayfan, HIGH);
        Blynk.virtualWrite(VPIN_BUTTON_1, HIGH);
        delay(1000);
        mySwitch.resetAvailable();
      }
      else if(mySwitch.getReceivedValue() == 8594436)
      {
        relaylightstate = !relaylightstate;
        digitalWrite(relaylight, relaylightstate);
        Blynk.virtualWrite(VPIN_BUTTON_2, relaylightstate);
        delay(1000);
        mySwitch.resetAvailable();
      }
      else if(mySwitch.getReceivedValue() == 8594437)
      {
        relaylightbstate = !relaylightbstate;
        digitalWrite(relaylightb, relaylightbstate);
        Blynk.virtualWrite(VPIN_BUTTON_3, relaylightbstate);
        delay(1000);
        mySwitch.resetAvailable();
      }
      else if(mySwitch.getReceivedValue() == 8594439)
      {
        relayrandomstate = !relayrandomstate;
        digitalWrite(relayrandom, relayrandomstate);
        Blynk.virtualWrite(VPIN_BUTTON_4, relayrandomstate);
        delay(1000);
        mySwitch.resetAvailable();
      }
  }
}

```

can anyone tell me what is wrong with my code or my nodemcu module? Is it because i uploaded two codes one after the other and messed up the module?

# Answer
> Can anyone just try to upload this code to their node MCU with changing the WiFi credentials and the blynk Auth token to one of your own project by following the blynk guide and check if it is connecting to blynk and it's only a problem with my module or there is some problem in my code

This might be necessary to see more problems. But it isn't necessary to see at least one important one. Here's what I cut your code down to:

```
#define relayfan 5
#define relaylight 6
#define relaylightb 7
#define relayrandom 2

void setup() {
  Serial.begin(9600);
  pinMode(relayfan, OUTPUT);
  pinMode(relaylight, OUTPUT);
  pinMode(relaylightb, OUTPUT);
  pinMode(relayrandom, OUTPUT);
  digitalWrite(relayfan, HIGH);
  digitalWrite(relaylight, HIGH);
  digitalWrite(relaylightb, HIGH);
  digitalWrite(relayrandom, HIGH);
  Serial.println("Start");
}

void loop() {
  Serial.println("loop()");
}

```

So, you have:

```
#define relaylight 6

```

One thing to make clear about here is that this is **GPIO**6, and **not** `D6`, which would be mapped to GPIO12, which would make more sense. GPIO6 is actually used internally to the ESP8266 module to access the SPI flash chip that stores your code. Basically when you do this:

```
pinMode(relaylightb /* GPIO6 */, OUTPUT);

```

you're kind of ripping the rug out from underneath the the microcontroller inside the ESP8266 module. It's a bit like reaching into a computer and pulling out harddrive while it's running. It's trying to load code and data from the SPI flash, but you've reconfigured that pin.

The ESP8266 brings code from SPI flash into some smaller chunk of internal RAM that it executes the instructions from. So, I suppose it might be possible to get in the situation where you're continuing to run cached instructions while trying and failing to load data from the spi flash, which maybe could explain part of why the problem manifests the way it does for you.

In case you're wondering, it is possible to get the microchip used in the ESP8266 to load code from sources other than SPI flash, in which case GPIO6 might actually be available for your own general purposes, but not with the way most of modules are set up and used. If you look at the pinout for the common ESP8266 modules, the smaller board mounted to your NodeMCU board, you'll notice GPIO6 doesn't actually leave the module; it just goes from the microcontroller to the SPI flash chip, which is all hidden away under the RF shield on the NodeMCU.

There *may* be other problems here with pin selection. E.g., GPIO7 is not mentioned in the pin mapping, nor does it seem to leave common modules, so `#define relaylightb 7` is a bad sign. Have a look through this guide with regard what you can do with each pin and what sort of behaviours they have at boot. E.g. GPIO2 (your `relayrandom`) is "pin is high on BOOT, boot failure if pulled LOW" according to the guide. So perhaps it will pulse your relay which you might not like. And it may be that whatever circuit you have for the relay tugs GPIO2 toward LOW, which would also be bad. Do keep in mind that the D# labeling is different from the GPIO# labeling.

---

I just checked GPIO7 (`randomlightb`), and like GPIO6 (`randomlight`), it was sufficient to execute `pinMode` with `OUTPUT` on it cause a reset.
> 2 votes

---
Tags: nodemcu, rf, flash, error, blynk
---


# Question
Title: How do I get the size of my program at runtime?
(This question is specific for the Arduino Due, but maybe there's a general answer to the question)

I'm using DueFlashStorage to store application data in the flash memory of my Arduino Due. That works quite nicely. The Due has two flash blocks with 256k each. By default, the library writes data to the second flash block. The first flash block is used for the program. My program currently uses around 160k of flash (as the compiler tells me). That leaves about 96k of flash unused, which I could really use to store more application data. I managed to adjust DueFlashStorage to allow writing to the full memory range, but how do I detect where it is safe to write to? (Obviously, I must not overwrite any part of the program)

I have tried something like:

```
  // this returns the logical address of the first byte in flash (0x80000)
  byte* startAddr = dueFlashStorage.readAddress(0);
  Serial.println((unsigned int)startAddr, HEX);
  int bytes = 0;
  while (bytes < 512 * 1024) // That's the size of the flash
  {
    int* data = (int*)(startAddr + bytes);
    if (*data == 0xFFFFFFFF) // empty flash is initialized with FF's
     {
       Serial.print("Free block at 0x");
       Serial.println((unsigned int)data, HEX);
     }
     else
     {
       Serial.print("Used block at 0x");
       Serial.println((unsigned int)data, HEX);
     }
    bytes+=512;
  }

```

This seems to work, as the first block detected as "free" is just above the size of the program. However, this approach has some major drawbacks:

* It's slow. Running over the whole address space to find the end of the program uses time (and maybe I shouldn't just test the first word of each block)
* It's not reproducible. After I have written data to the detected first free block, it's no longer free, so I need another approach (like some magic number) to detect the first data block after the CPU is reset.

Is there a better way for this (like, in the ideal world, a constant I could use)? I don't want to hardcode the data start, because as the program grows (and it's still in development) I would forget to adjust that constant and booooommmm....

# Answer
> 4 votes
Just to warn you, I minimally tested this, but it seems to work.

In the Due's linker script there are these relevant lines, containing the named `rom` section.

```
MEMORY
{
    rom (rx)    : ORIGIN = 0x00080000, LENGTH = 0x00080000 /* Flash, 512K */

```

Below you'll see:

```
SECTIONS
{
    .text :
    {
        . = ALIGN(4);
        _sfixed = .;

```

`_sfixed` is a symbol they've created to mark the current location, which happens to be the start of the `rom` section in this case, `0x00080000`. At the bettom of the brace matching the one following `.text`, you'll see:

```
} > rom

```

showing that section goes into ROM, which is why `.` at the beginning of the .text section refers to the `rom` section start address.

If you look near the last thing placed in `rom`, you'll see:

```
    . = ALIGN(4);
    _etext = .;

```

So, they've set another symbol there, the one of interest, `_etext`, the address of which should be the byte of ROM not used, or so I thought the first time through this; turns out it isn't. I gather you have no use for start of ROM symbol, since it's a static value and at the beginning, so I'll ignore that, but if you cared to make use of it it could be done the same way as follows for `_etext`.

These symbols don't have any type, but you can make them whatever you want. If you want to perform arithmetic on a pointer that results, it makes sense to use a char type, so:

```
extern "C" unsigned char _etext;

```

I thought this was the end of the story, could just take the address of this symbol, but there is more to it. Following the regular code is this section:

```
    .relocate : AT (_etext)
    {
        . = ALIGN(4);
        _srelocate = .;
        *(.ramfunc .ramfunc.*);
        *(.data .data.*);
        . = ALIGN(4);
        _erelocate = .;
    } > ram

```

They're placing code for the `banzai` (reset) function (and perhaps other things), which goes into ram ultimately, at this location in ROM. So, presumably in the start code this is copied from the end of the normal program code into some place in ram.

So, there are two more symbols of interest here, `_srelocate` and `_erelocate`. Declarations for them:

```
extern "C" unsigned char _srelocate;
extern "C" unsigned char _erelocate;

```

These symbols resolve to addresses in RAM, so they can't be used directly, but can have their addresses subtracted to get the size of the image in ROM that gets relocated to RAM, leading to:

```
const unsigned char *rom_end = &_etext + (&_erelocate - &_srelocate);
Serial.print("The end of used ROM is : 0x");
Serial.println((uintptr_t)rom_end, HEX);

```

When I compile and run a simple test like this and check the serial monitor connection, I see output like:

```
The end of used ROM is : 0x82FF8

```

If look at the .bin file produced by the compiler:

```
$ wc --bytes  build/arduino.sam.arduino_due_x_dbg/efixed.ino.bin
12280 build/arduino.sam.arduino_due_x_dbg/efixed.ino.bin

```

And 0x82FF8 - 0x80000 == 12280.

When I hex dump flash around this address I can see what looks like it padding out the flash sector with 0x00 bytes before the next unprogrammed flash sector shows as 0xFF. So you would need to round this up yourself, and if you want be somewhat safer, maybe add some margin.

I don't know how common that configuration in the linker script is. It's likely that most linker scripts place a symbol there, if they've had some forethought. But I wouldn't necessarily expect it have the same name. It's possible they modify it to add more stuff after that symbol. But for now, for the Due, that would seem to work fine. It is a bit messy though.

---
Tags: arduino-due, memory-usage, flash
---


# Question
Title: using RTOS SDK - crashes when adding another task
(I hope this is the right place to ask questions about the ESP8266\_RTOS\_SDK)

I have a program that I've taken from the samples directory (protocols/tcp\_client) in the RTOS SDK and added code from the uart sample just so I can use the keyboard to tell the client when to start. The tcp\_client task simply does a socket send to & recv from the server (a simple sockets server running on a linux desktop). It runs great until I tried to add another sample task:

```
 static void test_task(void *pvParameters)
    {
        vTaskDelay(MYDELAY2);
        ESP_LOGI(TAG, "asdf 123");
    }

```

And then, in the app\_main(), I create the task:

```
xTaskCreate(test_task, "test", 2048, NULL, 10, NULL);

```

I try to run it and it either locks up and then crashes or just crashes as soon as it connects to the server. It usually crashes right after it prints out the message in the test\_task.

```
 #include <string.h>
    #include <sys/param.h>
    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    #include "esp_system.h"
    #include "esp_log.h"
    #include "esp_netif.h"
    #include "esp_event.h"
    #include "protocol_examples_common.h"
    #include "nvs.h"
    #include "nvs_flash.h"
    #include "lwip/err.h"
    #include "lwip/sockets.h"
    #include "lwip/sys.h"
    #include <lwip/netdb.h>
    #include "freertos/queue.h"
    #include "driver/uart.h"

    #define HOST_IP_ADDR CONFIG_EXAMPLE_IPV4_ADDR
    #define MYDELAY1 (75 / portTICK_PERIOD_MS)
    #define MYDELAY2 (125 / portTICK_PERIOD_MS)
    #define MYDELAY3 (250 / portTICK_PERIOD_MS)
    #define MYDELAY4 (500 / portTICK_PERIOD_MS)
    #define MYDELAY5 (1000 / portTICK_PERIOD_MS)
    #define MYDELAY6 (2000 / portTICK_PERIOD_MS)
    #define MYDELAY7 (5000 / portTICK_PERIOD_MS)
    #define PORT CONFIG_EXAMPLE_PORT

    static const char *TAG = "example";
    #define EX_UART_NUM UART_NUM_0
    #define BUF_SIZE (1024)
    #define RD_BUF_SIZE (BUF_SIZE)
    static QueueHandle_t uart0_queue;
    unsigned char state;
    int sock;

    static void test_task(void *pvParameters)
    {
        vTaskDelay(MYDELAY2);
        ESP_LOGI(TAG, "asdf 123");
    }

    static void tcp_client_task(void *pvParameters)
    {
        char rx_buffer[128];
        char send_buff[100];
        char addr_str[128];
        int addr_family;
        int ip_protocol;
        int i = 0;
        char xbyte = 0x21;
        int len, err;

        struct sockaddr_in destAddr;
    //  destAddr.sin_addr.s_addr = inet_addr(HOST_IP_ADDR);
    // can set ip address either explicitly or using 'make menuconfig' and go to 'example      configuration'
        destAddr.sin_addr.s_addr = inet_addr("192.168.88.103");
        inet_ntoa_r(((struct sockaddr_in *)&destAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) -     1);
        ESP_LOGI(TAG, "address : %s", addr_str);
        destAddr.sin_family = AF_INET;
        destAddr.sin_port = htons(PORT);
        addr_family = AF_INET;
        ip_protocol = IPPROTO_IP;
        inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1);

        sock =  socket(addr_family, SOCK_STREAM, ip_protocol);
        if (sock < 0)
        {
            ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
            state = 51;
        }
        ESP_LOGI(TAG, "Socket created %d",sock);

        memset(send_buff,0,sizeof(send_buff));
        for(i = 0;i < 99;i++)
        {
            send_buff[i] = xbyte;
            if(++xbyte > 0x7e)
                xbyte = 0x21;
        }
        send_buff[99] = 0;

        ESP_LOGI(TAG,"press '1' to connect, then press '2' to start client, '3' to shutdown");

        while (1)
        {
            switch(state)
            {
                case 0:
                vTaskDelay(MYDELAY3);
                break;
            case 49:
                err = connect(sock, (struct sockaddr *)&destAddr, sizeof(destAddr));
                if (err != 0)
                {
                    ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno);
                    close(sock);
                    vTaskDelay(MYDELAY1);
                    state = 0;
                }
                ESP_LOGI(TAG, "Successfully connected %d",err);
                state = 0;
                break;
            case 50:
                //ESP_LOGI(TAG, "starting...");

                err = send(sock, send_buff, 80, 0);
                if (err < 0)
                {
                    ESP_LOGE(TAG, "Error occured during sending: errno %d", errno);
                    state = 0;
                    break;
                }
                //ESP_LOGI(TAG,"send returned: %d",err);

                vTaskDelay(MYDELAY1);

                len = recv(sock, rx_buffer, 80, 0);
                // Error occured during receiving
                if (len < 0)
                {
                    ESP_LOGE(TAG, "recv failed: errno %d", errno);
                    state = 0;
                    break;
                }
                else
                {
                    rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
                    //ESP_LOGI(TAG, "Received %d bytes from %s:", len, addr_str);
                    ESP_LOGI(TAG, "%s", rx_buffer);
                }

                vTaskDelay(MYDELAY1);

                if (sock == -1)
                {
                    ESP_LOGE(TAG, "Shutting down socket, press '1' to restart...");
                    shutdown(sock, 0);
                    close(sock);
                    state = 0;
                }
                break;
            case 51:
                ESP_ERROR_CHECK(example_disconnect());
                break;
            case 52:
                shutdown(sock,0);
                close(sock);
                ESP_LOGI(TAG,"shutdown - deleting task");
                vTaskDelete(NULL);
                break;
            default:
                ESP_LOGI(TAG,"press '1' to connect, then press '2' to start client %d",state);
                vTaskDelay(MYDELAY3);
                state = 0;
                break;
        }
    }
}
//#if 0
static void uart_event_task(void *pvParameters)
{
    uart_event_t event;
    int i;
    uint8_t *dtmp = (uint8_t *) malloc(RD_BUF_SIZE);

    for (;;) {
        // Waiting for UART event.
        if (xQueueReceive(uart0_queue, (void *)&event, (portTickType)portMAX_DELAY)) {
            bzero(dtmp, RD_BUF_SIZE);
            //ESP_LOGI(TAG, "uart[%d] event:", EX_UART_NUM);

            switch (event.type) {
                // Event of UART receving data
                // We'd better handler data event fast, there would be much more data events than
                // other types of events. If we take too much time on data event, the queue might be full.
                case UART_DATA:
                    ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
                    uart_read_bytes(EX_UART_NUM, dtmp, event.size, portMAX_DELAY);
                    state = dtmp[0];
                    ESP_LOGI(TAG,"state: %d",state);
//                    uart_write_bytes(EX_UART_NUM, (const char *) dtmp, event.size);
                    break;

                // Event of HW FIFO overflow detected
                case UART_FIFO_OVF:
                    ESP_LOGI(TAG, "hw fifo overflow");
                    // If fifo overflow happened, you should consider adding flow control for your application.
                    // The ISR has already reset the rx FIFO,
                    // As an example, we directly flush the rx buffer here in order to read more data.
                    uart_flush_input(EX_UART_NUM);
                    xQueueReset(uart0_queue);
                    break;

                // Event of UART ring buffer full
                case UART_BUFFER_FULL:
                    ESP_LOGI(TAG, "ring buffer full");
                    // If buffer full happened, you should consider encreasing your buffer size
                    // As an example, we directly flush the rx buffer here in order to read more data.
                    uart_flush_input(EX_UART_NUM);
                    xQueueReset(uart0_queue);
                    break;

                case UART_PARITY_ERR:
                    ESP_LOGI(TAG, "uart parity error");
                    break;

                // Event of UART frame error
                case UART_FRAME_ERR:
                    ESP_LOGI(TAG, "uart frame error");
                    break;

                // Others
                default:
                    ESP_LOGI(TAG, "uart event type: %d", event.type);
                    break;
            }
        }
    }
    free(dtmp);
    dtmp = NULL;
    vTaskDelete(NULL);
}
//#endif

void app_main()
{
    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    ESP_ERROR_CHECK(example_connect());
        uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE
    };
    uart_param_config(EX_UART_NUM, &uart_config);

    // Install UART driver, and get the queue.

    uart_driver_install(EX_UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 100, &uart0_queue, 0);

    xTaskCreate(test_task, "test", 2048, NULL, 10, NULL);

    xTaskCreate(uart_event_task, "uart_event_task", 2048, NULL, 12, NULL);

    xTaskCreate(tcp_client_task, "tcp_client", 2048, NULL, 5, NULL);
}

```

When I added the task for the uart it works, but when I add the task to print the test message and do the time delay, it crashes.

# Answer
> 1 votes
I didn't have the task as an infinite loop. It should be:

```
static void test_task(void *pvParameters)
{
    while(1)
    {
        vTaskDelay(MYDELAY6);
        ESP_LOGI(TAG, "test 123");
     }
}

```

---
Tags: task
---


title: Simple LCD countdown timer

text:
# Question
Title: Simple LCD countdown timer
I tried to modify the basic "hello-world" sketch for the LCD that is a part of the examples section in the IDE. I intended to make a countdown timer using the LCD.

The original code simply prints "Hello World" in the first line, and then makes use of the `millis()` function to print the time elapsed in the next line.

So I tried a simple modification to make it count *down* from 20. Instead of printing `millis()/1000` , I printed `20-millis()/1000`, and also added a `while()` to only print till `millis()<=20,000`. (so that it does not go beyond `00)`

```
#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {

  lcd.begin(16, 2);

  lcd.print("time left");
}

void loop() {

  while(millis()<=20000){

    lcd.setCursor(0, 1);

    lcd.print(20- millis() / 1000);
  }

}

```

It seemed to work till `10`. but instead of `9`, it printed `90`, and likewise `80,70..` for `8,7...`etc till `00`.

**How can I get rid of these extra zeros?**

# Answer
> 6 votes
> instead of `9`, it printed `90`

No, it didn't: it printed “9”. However, it did not *erase* the previous value before printing “9”. Before printing the 9, the LCD had:

```
┌────────────────┐
│time left       │
│10              │
└────────────────┘
 ^cursor position

```

When you printed “9”, that character replaced the “1”, and you end up seeing “90”.

The fix, as pointed out by Juraj, is to add a space after printing the numbers.

An alternative is to prepend a space (or a zero), but only when the number to be displayed is less that 10:

```
int count = 20 - millis() / 1000;
if (count < 10)
    lcd.print(' ');  // alternatively: '0'
lcd.print(count);

```

---
Tags: lcd, debugging
---


# Question
Title: Why is my Arduino Nano's buzzer clicking?
EDIT: I'm so sorry but the clicking wasn't coming from the Arduino **but from the piezo buzzer!** I was wrong and I'm so sorry for misguiding you!

I recently bought an Arduino Nano so that I could downsize my arrangement with my Arduino Uno so I soldered everything together and when I plugged in the Nano I extra made sure that nothing was shorting each other out. But the buzzer attached to it kept making this clicking noise. Does anyone know why? Do I actually have a short-circuit?

Here is the code:

```

#define LED 1
#define twoLED 2
#define threeLED 4
#define fourLED 5
#define fiveLED 6
#define sixLED 7
#define sevenLED 8
#define eightLED 9
#define nineLED 10
#define tenLED 11

int state = 0;
int old = 0;
int buttonPoll = 0;

void setup() {
  pinMode (3,INPUT);
  pinMode (11,OUTPUT);
  pinMode(LED, OUTPUT);
  pinMode(twoLED, OUTPUT);
  pinMode(threeLED, OUTPUT);
  pinMode(fourLED, OUTPUT);
  pinMode(fiveLED, OUTPUT);
  pinMode(sixLED, OUTPUT);
  pinMode(sevenLED, OUTPUT);
  pinMode(eightLED, OUTPUT);
  pinMode(nineLED, OUTPUT);
  pinMode(tenLED, OUTPUT);

  digitalWrite(LED, LOW);
  digitalWrite(twoLED,LOW);
  digitalWrite(threeLED,LOW);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);

}

void loop() {

while (state == old)
{
  buttonPoll = digitalRead (3);
  if (buttonPoll ==1)
  {
    delay (50);
    buttonPoll = digitalRead (3);
    if (buttonPoll == 0)
    {
      state = old + 1;
    }
  }
  else
  {
    delay(100);
  }

  switch (state)
  {
    case 1:
  digitalWrite(LED, HIGH);
  digitalWrite(twoLED,LOW);
  digitalWrite(threeLED,LOW);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
    old = state;
    break;

    case 2:
      digitalWrite(LED, HIGH);
  digitalWrite(twoLED,LOW);
  digitalWrite(threeLED,LOW);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
    old = state;
    break;

    case 3:
  digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,LOW);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
    old = state;
    break;

case 4:
      digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,LOW);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
    old = state;
    break;

    case 5:
  digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
    old = state;
    break;

case 6:

  digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
    old = state;
    break;

    case 7:
  digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

case 8:
  digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

  case 9:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

case 10:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

  case 11:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

    case 12:
        digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

  case 13:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, HIGH);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;
case 14:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, HIGH);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

  case 15:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, HIGH);
  digitalWrite(eightLED, HIGH);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

case 16:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, HIGH);
  digitalWrite(eightLED, HIGH);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

  case 17:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, HIGH);
  digitalWrite(eightLED, HIGH);
  digitalWrite(nineLED, HIGH);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

case 18:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, HIGH);
  digitalWrite(eightLED, HIGH);
  digitalWrite(nineLED, HIGH);
  digitalWrite(tenLED, LOW);
   old = state;
    break;

  case 19:
    digitalWrite(LED, HIGH);
  digitalWrite(twoLED,HIGH);
  digitalWrite(threeLED,HIGH);
  digitalWrite(fourLED, HIGH);
  digitalWrite(fiveLED, HIGH);
  digitalWrite(sixLED, HIGH);
  digitalWrite(sevenLED, HIGH);
  digitalWrite(eightLED, HIGH);
  digitalWrite(nineLED, HIGH);
  digitalWrite(tenLED, HIGH);

      tone (11,493.88);
      delay(150);

      tone(11, 523.25);
      delay(150);

      tone(11,493.88);
      delay(150);

      tone(11,392.00);
      delay(150);

      tone(11,329.63);
      delay(150);

      tone(11, 261.63);
      delay(150);

      tone(11, 246.94);
      delay(150);

      tone (11,196.00);
      delay(150);

      tone(11, 246.94);
      delay(150);

      tone(11, 261.63);
      delay(150);

      tone(11,392.00);
      delay(150);

      tone(11,493.88);
      delay(150);

      tone(11, 523.25);
      delay(150);

      tone (11,493.88);
      delay(150);

      tone(11,493.88);
      delay(150);

      tone(11,392.00);
      delay(150);

      tone(11, 329.63);
      delay(150);

noTone(11);

old = state;
state = 0;
old = 0;

    break;

    default:
  digitalWrite(LED, LOW);
  digitalWrite(twoLED,LOW);
  digitalWrite(threeLED,LOW);
  digitalWrite(fourLED, LOW);
  digitalWrite(fiveLED, LOW);
  digitalWrite(sixLED, LOW);
  digitalWrite(sevenLED, LOW);
  digitalWrite(eightLED, LOW);
  digitalWrite(nineLED, LOW);
  digitalWrite(tenLED, LOW);

    old = 0;

    break;
}

}

  }

```

Here is a video of the clicking: https://drive.google.com/file/d/1TprL56p2YyJ3j8cq43U2LYzaWofZpJM7/view?usp=sharing

# Answer
The simpler piezos click when a voltage is applied, and again when it is removed. To make it buzz, it needs a pulse-train: many clicks makes a buzz. There are piezos that have that feature built-in, but I'm guessing yours hasn't. That's actually a Good Thing in disguise: it allows you to make tones by making pulse-trains at different frequencies. The easiest way to do that is to connect it to one of the PWM pins (5, 6, 9, 10, or 11) and use the `tone()` library-function (look it up if you need to). Of course, you can do it "manually", too, on any output pin, just by switching it HIGH and LOW at rates that you choose, but that will pretty much tie up your processor, at least for higher frequencies.

Update:

> Just why wasn't it clicking when I connected it to the Arduino Uno?

I can't tell without seeing the two sketches but in your video, it sounds like it is being turned on or off, or pulsed, once per second.

Please add your code (both of them, if they're different) to your question. Wiring diagram(s) of the piezo connection to the Arduino boards would help, too.
> 1 votes

---
Tags: arduino-nano
---


title: Float switch is not detected

text:
# Question
Title: Float switch is not detected
Good day everyone, forgive me for the shabby drawing I am just panicking, why my float switches are suddenly undetected by my Arduino mega. I've tested all the float switches one by one to confirm if everything is working just before installing it..

i have 18 sets of float switches, 5 pumps being controlled by the relay, my main PSU is 12V 20A. The yellow rectangle stands for the float switch, the purple line is connected to digital pins from between and 10k ohm resistor and the switch. the green line is a common ground connection from the 5.2V buck (psu for devices that need 5 to 5.5v) to the Arduino mega's gnd.

here's my code, and its not the project code, just a simple test sketch because my float switches are suddenly acting weird:

```
#include <OneWire.h>
#include "OneButton.h"
#include <DallasTemperature.h>
#include "GravityTDS.h"
#include <EEPROM.h>
#include "Wire.h" // Include the I2C Wire Library
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,4);

#define bp1 (uint8_t) 10 /*Button 1*/
#define bp2 (uint8_t) 11 /*Button 2*/
#define bp3 (uint8_t) 12 /*Button 3*/

OneButton btn1 = OneButton(bp1,false,false); uint8_t bx1 = 0;
OneButton btn2 = OneButton(bp2,false,false); uint8_t bx2 = 0;
OneButton btn3 = OneButton(bp3,false,false); uint8_t bx3 = 0;

//Float Switches...........
/*Collector Float Switch*/
#define CT_Fs2 (uint8_t) 9

/*Sieve & Cloth*/
#define SC_Fs1 (uint8_t) 8

/*Primary Test Tank*/
#define PT_Fs1 (uint8_t) 7
#define PT_Fs2 (uint8_t) 6

/*Grease Trap*/
#define GT_Fs1 (uint8_t) 5

/*First Filtration*/
#define FFP_Fs1 (uint8_t) 4
#define FFP_Fs2 (uint8_t) 3

/*Sediment Filter*/
#define SD_Fs1 (uint8_t) 2

/*Second Filtration Passed*/
#define SP_Fs1 (uint8_t) 24
#define SP_Fs2 (uint8_t) 25

/*Final Test Tank*/
#define FT_Fs1 (uint8_t) A7
#define FT_Fs2 (uint8_t) A8

/*Tank A*/
#define TA_Fs1 (uint8_t) 45
#define TA_Fs2 (uint8_t) 47

/*Tank B*/
#define TB_Fs1 (uint8_t) 42
#define TB_Fs2 (uint8_t) 43

/*Tank C*/
#define TC_Fs1 (uint8_t) 40
#define TC_Fs2 (uint8_t) 41

void setup()
{
  Serial.begin(9600); /* Show Serial Monitor */
  lcd.begin(); /* LCD Screen Set Up */

//---------------------------------------------------------------------dont forget to set up the pins
//ALL DIGITAL PINS ARE INPUT AS DEFAULT, DECLARE ONLY IF MODE IS OUTPUT:
  pinMode(FT_Fs1,INPUT);
  pinMode(FT_Fs2,INPUT);

//----------------------------------------------------------------------One Button Single Click event attachment
  btn1.attachClick(handleClick1);
  btn2.attachClick(handleClick2);
  btn3.attachClick(handleClick3);

}

//simple show txt on LCD Screen
void lcd_print(String txt ,uint8_t a, uint8_t b)
{ lcd.setCursor(a,b); lcd.print(txt);}

void loop()
{
  FSTester();
}

void FSTester() // to check FLOAT SWITCH
{
  if (digitalRead(CT_Fs2) == 1)
  {
    lcd.clear();
    lcd_print("CT_Fs2 Detected",0,1);
    delay(5000);
  }
  else if (digitalRead(SC_Fs1) == 1)
  {
    lcd.clear();
    lcd_print("SC_Fs1 Detected",0,1);
    delay(5000);
  }
  else if (digitalRead(PT_Fs1) == 1)
  {
    lcd.clear();
    lcd_print("PT_Fs1 Detected",0,1);
    delay(5000);
  }
  else if (digitalRead(PT_Fs2) == 1)
  {
    lcd.clear();
    lcd_print("PT_Fs2 Detected",0,1);
    delay(5000);
  }
  else if (digitalRead(GT_Fs1) == 1)
  {
    lcd.clear();
    lcd_print("GT_Fs1 Detected",0,1);
    delay(5000);
  }
  else if (digitalRead(FFP_Fs1) == 1)
  {
    lcd.clear();
    lcd_print("FFP_Fs1 Detected",0,1);
    delay(5000);
  }
  else if (digitalRead(FFP_Fs2) == 1)
  {
    lcd.clear();
    lcd_print("FFP_Fs2 Detected",0,1);
    delay(5000);
  }
  else if (digitalRead(SD_Fs1) == 1)
  {
    lcd.clear();
    lcd_print("SD_Fs1 Detected",0,1);
    delay(5000);
  }
  else if (digitalRead(SP_Fs1) == 1)
  {
    lcd.clear();
    lcd_print("SP_Fs1 Detected",0,1);
    delay(5000);
  }
  else if (digitalRead(SP_Fs2) == 1)
  {
    lcd.clear();
    lcd_print("SP_Fs2 Detected",0,1);
    delay(5000);
  }
  else if (digitalRead(FT_Fs1) == 1)
  {
    lcd.clear();
    lcd_print("FT_Fs1 Detected",0,1);
    delay(5000);
  }
  else if (digitalRead(FT_Fs2) == 1)
  {
    lcd.clear();
    lcd_print("FT_Fs2 Detected",0,1);
    delay(5000);
  }
  else if (digitalRead(TA_Fs1) == 1)
  {
    lcd.clear();
    lcd_print("TA_Fs1 Detected",0,1);
    delay(5000);
  }
  else if (digitalRead(TA_Fs2) == 1)
  {
    lcd.clear();
    lcd_print("TA_Fs2 Detected",0,1);
    delay(5000);
  }
  else if (digitalRead(TB_Fs1) == 1)
  {
    lcd.clear();
    lcd_print("TB_Fs1 Detected",0,1);
    delay(5000);
  }
  else if (digitalRead(TB_Fs2) == 1)
  {
    lcd.clear();
    lcd_print("TB_Fs2 Detected",0,1);
    delay(5000);
  }
  else if (digitalRead(TC_Fs1) == 1)
  {
    lcd.clear();
    lcd_print("TC_Fs1 Detected",0,1);
    delay(5000);
  }
  else if (digitalRead(TC_Fs2) == 1)
  {
    lcd.clear();
    lcd_print("TC_Fs2 Detected",0,1);
    delay(5000);
  }
  else
  {
    lcd.clear();
    lcd_print("NOTHING",0,1);
  }
}

```

I've checked for continuity and everything is fine. why is it weird?

somebody please correct my mistakes

# Answer
> 1 votes
It is difficult to determine from the diagram if the green wire is at the same voltage as the black wire supplying power to the Arduino board. Even if they are connected, it is difficult to say if the current is nominal. As there is a power supply of unknown design involved for both the Arduino and the float switch.

This could cause unexpected results and may even permanently damage sensitive parts. Consider using a design with only one power supply thereby mitigating the risk of unexpected results.

---
Tags: arduino-mega, switch, float
---


# Question
Title: Servo noise during program flash on Arduino
I'm running serveral servos using a driver A4988 and external power supply. Everything works fine. I've just noticed one issue that I can't explain. As soon as I upload a new program version on my arduino uno, while the external power supply is one, the servo makes some strange noises. After the upload has finished, the noise disappears.

Without any further details, can you explain this behavior? Does the arduino set some Pins to HIGH during flashing?

Thanks!

# Answer
> 2 votes
It would depend on which Arduino and what bootloader it's running. Generally MCUs have their pins in INPUT mode when they reset. Sometimes the bootloader will leave some pins configured for a particular mode by the some the sketch runs. E.g. the Leonardo seems to leave pin 13 set to OUTPUT mode.

You usually want devices connected to your Arduino to have stable signals when the Arduino MCU is in reset, or in the bootloader, so it makes sense to pull the signal pins, that will later be output from the Arduino sketch, to known levels. So maybe pulling your servo driver enable signal to inactive (HIGH) is appropriate.

Looking at the A4988, it has an EN (enable) pin, which seems to be active low. So putting a high(ish) value resistor, say 5k or 10k, on it to VDD/HIGH (to inactive) is probably the thing to do. When the Arduino is not driving the enable line to its low (active) state, that is when it's in the bootloader or being held in reset, the A4988 should stop its activity.

---
Tags: arduino-uno, power, servo
---


# Question
Title: How to calculate required amperage of multiple motors?
I a very simple question about calculating the amperage I need to run 5 stepper motors from my Arduino Uno.

If I have **5 28BYJ-48 stepper motors**(which are **5V** and are said to require about **240mA** each) all plugged into **5 separate ULN2003 driving boards**, and I wire 4 signal wires from the boards to the Arduino, and connect the two power wires for the board to 5V and GND on the Arduino. **What voltage and amperage I need to supply to my Arduino for everything to run properly?**

I'm worried because I read that the Arduino cannot handle over one amp but 0.24\*5\>1, although I don't know if the amperage is additive with each additional motor.

Thanks for any answers!

# Answer
> 4 votes
> I don't know if the amperage is additive with each additional motor

Yes, amperage is additive.

> the Arduino cannot handle over one amp but 0.24\*5\>1

That is correct. But the stepper motors should never be powered through the Arduino. You should connect a fitting power supply directly to the stepper drivers. That way the needed current flows past the Arduino, not through it.

> What voltage and amperage I need to supply to my Arduino for everything to run properly?

The Arduino runs at 5V, though you can provide 7-12V to Vin/barrel jack. When your motors are rated for 5V, you should provide them with 5V. So it would be fitting to buy one 5V power source to power the Arduino (through the 5V pin or USB) and the stepper drivers.

For the current: A good measure is the stall current of a motor, so the current, that flows, when the motor is driven, but cannot move (due to being physically stuck). Add a bit headroom to this. The mentioned motors are often badly documented, so that you might not be able to find a stall current value. Add more headroom in that case. So I would suggest adding up all the amps and then multiply this value with 1.5 or even 2. Let's take 250mA per motor (for ease of calculation) with 5 motors gives 1.25A. Take at least a 2A power supply. When you want to make sure go directly to 3A. The price difference in that range isn't that much anyway.

---
Tags: arduino-uno, voltage-level, electronics, voltage, stepper-motor
---


# Question
Title: How to transmit Float sensor values via NRF24L01 module?
I'm trying to figure out a way to transmit four sensor values: Voltage, Current, Power and consumption but I'm unable to do that. Yet, my syntax is correct... what am I missing?

```
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include <RF24.h>

#define ACS712 A0

int lastData = 0;
int dataSum = 0;
int Count = 0;

float Voltage;
float Current;
float Power;
float kWh;
float Consumption;
String Data;

float vpc = 4.882813; // approx. voltage per count

RF24 radio(9, 10); // CE, CSN
const byte addresses[][6] = {"00001", "00002"};

void setup() {
  Serial.begin(115200);
  pinMode(13, OUTPUT);
  radio.begin();
  radio.openWritingPipe(addresses[1]); // 00001
  radio.openReadingPipe(1, addresses[0]); // 00002
  radio.setPALevel(RF24_PA_MIN);
  radio.startListening();
}

void loop() {

  radio.stopListening();

  if (millis() > lastData + 1) {
    dataSum += sq(analogRead(ACS712) - 512);
    Count++;

    lastData = millis();
  }
  // If statement to make calculations.
  if (Count == 1000) {

    // To get the RMS of the data.
    float mean = dataSum / Count;
    float value = sqrt(mean);

    // To get the Voltage (in volts) consumed.
    float Voltage = value * vpc;

    // To get the Current (in amps) consumed.
    float Current = Voltage / 66;

    // To get the Power (in watts) consumed.
    float Power = Current * 240;

    float kWh = Power / 1000;
    float Consumption = kWh;

    dataSum = 0;
    Count = 0;

    Data += F("\nVoltage: ");
    Data += String(Voltage, 3);
    Data += F("\nCurrent: ");
    Data += String(Current, 3);
    Data += F("\nPower: ");
    Data += String(Power, 3);
    Data += F("\nConsumption: ");
    Data += String(Consumption, 3);
    //Serial.println(Data);

    radio.write(&Data, sizeof(Data));
    if (radio.write(&Data, sizeof(Data)) && true) {
      Serial.println("Sent!");
    } else {
      Serial.println("Failed!");
    };
    delay(10);
  }
}

```

# Answer
Simple float transmission:

For TX use

```
float payload = 0.12345;
radio.write(&payload, sizeof(payload));

```

For RX use

```
float payload = 0;
radio.read(&payload, sizeof(payload));

```
> 2 votes

---
Tags: sensors, nrf24l01+, float
---