title: I2C cabling rules for 2+ devices

text:
# Question
Title: I2C cabling rules for 2+ devices
I'm attempting to wire two breakout boards with i2c devices to a Mega2560:

* a HD44280 LCD with PCF8574 i2c backpack
* a combo board with DS1307 + AT24C32

There are two obvious possibilities for cabling:

* two 10-inch ribbon cables that come together right before connecting to the Arduino's SDA and SCL pins. Technically, one could be 6 inches... but I know that with RS485, you're asking for trouble if you do a star with branches of unequal length. The cables can't really be any shorter without seriously impairing my ability to debug it while partially disassembled (the LCD is mounted to the lid, and the cables are long enough to allow me to lay the lid on the desk next to the enclosure and power everything up without putting stress on the cables).
* Same 10-inch segments of ribbon cable, but daisy-chained... Arduino to LCD, LCD to RTC. In this case, the second one really needs to be 10", because it's mounted to the only clear spot inside the case I have.

Is one likely to be better or worse than the other?

Are there any rules about WHERE the pullup resistors have to go? The DS1307 module has built-in pullup resistors. Do I have to somehow disable them & use resistors right at the point where the bus connects to the Arduino's SDA & SCL pins, or can the pullups go pretty much anywhere on the bus (including at one end of a star, or at the far end of a daisy chain)?

# Answer
> 1 votes
I2C is generally slow. You don't have to worry about how to route the device connection. Because propagation delay won't be a matter. The main goal should be to minimize the capacitance of the wiring, which means minimizing the total wire length. But as you mentioned one of the cable lengths is fixed, then keep the other one to a minimum. The star topology will work if you keep the wire lengths within 10 inches.

---
Tags: i2c
---


# Question
Title: Why is the serial monitor not printing a variable?
I connected an Adafruit color sensor to my Arduino and am having it make calculations. However, when the calculations are done and sent to the serial monitor, it says "NDVI: " without printing the value. The code is attached below. Thanks!

Code:

```
/* TSL2591 Digital Light Sensor */
/* Dynamic Range: 600M:1 */
/* Maximum Lux: 88K */

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_TSL2591.h"

#define IR850 5
#define IR940 6
#define BLUE 9
#define GREEN 10
#define RED 11

// Example for demonstrating the TSL2591 library - public domain!

// connect SCL to I2C Clock
// connect SDA to I2C Data
// connect Vin to 3.3-5V DC
// connect GROUND to common ground

Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591); // pass in a number for the sensor identifier (for your use later)

/**************************************************************************/
/*
    Displays some basic information on this sensor from the unified
    sensor API sensor_t type (see Adafruit_Sensor for more information)
*/
/**************************************************************************/
void displaySensorDetails(void)
{
  sensor_t sensor;
  tsl.getSensor(&sensor);
  Serial.println(F("------------------------------------"));
  Serial.print  (F("Sensor:       ")); Serial.println(sensor.name);
  Serial.print  (F("Driver Ver:   ")); Serial.println(sensor.version);
  Serial.print  (F("Unique ID:    ")); Serial.println(sensor.sensor_id);
  Serial.print  (F("Max Value:    ")); Serial.print(sensor.max_value); Serial.println(F(" lux"));
  Serial.print  (F("Min Value:    ")); Serial.print(sensor.min_value); Serial.println(F(" lux"));
  Serial.print  (F("Resolution:   ")); Serial.print(sensor.resolution, 4); Serial.println(F(" lux"));
  Serial.println(F("------------------------------------"));
  Serial.println(F(""));
  delay(500);
}

/**************************************************************************/
/*
    Configures the gain and integration time for the TSL2591
*/
/**************************************************************************/
void configureSensor(void)
{
  // You can change the gain on the fly, to adapt to brighter/dimmer light situations
  //tsl.setGain(TSL2591_GAIN_LOW);    // 1x gain (bright light)
  //tsl.setGain(TSL2591_GAIN_MED);      // 25x gain
  tsl.setGain(TSL2591_GAIN_HIGH);   // 428x gain

  // Changing the integration time gives you a longer time over which to sense light
  // longer timelines are slower, but are good in very low light situtations!
  //tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS);  // shortest integration time (bright light)
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_200MS);
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_400MS);
  // tsl.setTiming(TSL2591_INTEGRATIONTIME_500MS);
  tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS);  // longest integration time (dim light)

  /* Display the gain and integration time for reference sake */
  Serial.println(F("------------------------------------"));
  Serial.print  (F("Gain:         "));
  tsl2591Gain_t gain = tsl.getGain();
  switch(gain)
  {
    case TSL2591_GAIN_LOW:
      Serial.println(F("1x (Low)"));
      break;
    case TSL2591_GAIN_MED:
      Serial.println(F("25x (Medium)"));
      break;
    case TSL2591_GAIN_HIGH:
      Serial.println(F("428x (High)"));
      break;
    case TSL2591_GAIN_MAX:
      Serial.println(F("9876x (Max)"));
      break;
  }
  Serial.print  (F("Timing:       "));
  Serial.print((tsl.getTiming() + 1) * 100, DEC);
  Serial.println(F(" ms"));
  Serial.println(F("------------------------------------"));
  Serial.println(F(""));
}

/**************************************************************************/
/*
    Program entry point for the Arduino sketch
*/
/**************************************************************************/
void setup(void)
{
  pinMode(IR850, OUTPUT);
  pinMode(IR940, OUTPUT);
  pinMode(RED, OUTPUT);
  pinMode(GREEN, OUTPUT);
  pinMode(BLUE, OUTPUT);
  digitalWrite(IR850, LOW);
  digitalWrite(IR940, LOW);
  digitalWrite(RED, LOW);
  digitalWrite(GREEN, LOW);
  digitalWrite(BLUE, LOW);
  Serial.begin(9600);

  Serial.println(F("Starting Adafruit TSL2591 Test!"));

  if (tsl.begin())
  {
    Serial.println(F("Found a TSL2591 sensor"));
  }
  else
  {
    Serial.println(F("No sensor found ... check your wiring?"));
    while (1);
  }

  /* Display some basic information on this sensor */
  displaySensorDetails();

  /* Configure the sensor */
  configureSensor();

  // Now we're ready to get readings ... move on to loop()!
}

/**************************************************************************/
/*
    Shows how to perform a basic read on visible, full spectrum or
    infrared light (returns raw 16-bit ADC values)
*/
/**************************************************************************/
void simpleRead(void)
{
  // Simple data read example. Just read the infrared, fullspecrtrum diode
  // or 'visible' (difference between the two) channels.
  // This can take 100-600 milliseconds! Uncomment whichever of the following you want to read
  uint16_t x = tsl.getLuminosity(TSL2591_VISIBLE);
  //uint16_t x = tsl.getLuminosity(TSL2591_FULLSPECTRUM);
  //uint16_t x = tsl.getLuminosity(TSL2591_INFRARED);

  Serial.print(F("[ ")); Serial.print(millis()); Serial.print(F(" ms ] "));
  Serial.print(F("Luminosity: "));
  Serial.println(x, DEC);
}

/**************************************************************************/
/*
    Show how to read IR and Full Spectrum at once and convert to lux
*/
/**************************************************************************/
uint16_t ir, full;
void advancedRead(void)
{
  // More advanced data read example. Read 32 bits with top 16 bits IR, bottom 16 bits full spectrum
  // That way you can do whatever math and comparisons you want!
  uint32_t lum = tsl.getFullLuminosity();
  uint16_t ir, full;
  ir = lum >> 16;
  full = lum & 0xFFFF;
  Serial.print(F("[ ")); Serial.print(millis()); Serial.print(F(" ms ] "));
  Serial.print(F("IR: ")); Serial.print(ir);  Serial.print(F("  "));
  Serial.print(F("Full: ")); Serial.print(full); Serial.print(F("  "));
  Serial.print(F("Visible: ")); Serial.print(full - ir); Serial.print(F("  "));
  Serial.print(F("Lux: ")); Serial.println(tsl.calculateLux(full, ir), 6);
}

/**************************************************************************/
/*
    Performs a read using the Adafruit Unified Sensor API.
*/
/**************************************************************************/
void unifiedSensorAPIRead(void)
{
  /* Get a new sensor event */
  sensors_event_t event;
  tsl.getEvent(&event);

  /* Display the results (light is measured in lux) */
  Serial.print(F("[ ")); Serial.print(event.timestamp); Serial.print(F(" ms ] "));
  if ((event.light == 0) |
      (event.light > 4294966000.0) |
      (event.light <-4294966000.0))
  {
    /* If event.light = 0 lux the sensor is probably saturated */
    /* and no reliable data could be generated! */
    /* if event.light is +/- 4294967040 there was a float over/underflow */
    Serial.println(F("Invalid data (adjust gain or timing)"));
  }
  else
  {
    Serial.print(event.light); Serial.println(F(" lux"));
  }
}

int lightvalue;
int NDVIred;
int NDVIinfrared;
int NDVI;
boolean (hasrun) = false;

/**************************************************************************/
/*
    Arduino loop function, called once 'setup' is complete (your own code
    should go here)
*/
/**************************************************************************/
void loop(void)
{
  lightvalue = 255;
  //simpleRead();
  //advancedRead();
  //unifiedSensorAPIRead();
  if(hasrun==false){
  analogWrite(RED, lightvalue);
  advancedRead();
  NDVIred = full;
  delay(5000);
  analogWrite(IR940,lightvalue);
  advancedRead();
  NDVIinfrared=full;
  NDVI=(NDVIinfrared-NDVIred)/(NDVIinfrared+NDVIred);
  Serial.print("NDVI: "); Serial.write(NDVIred);
  delay(1000);
  exit(0);
  }
}

```

# Answer
You wrote:

> ```
> Serial.print("NDVI: "); Serial.write(NDVIred);
>
> ```

You are misusing here the `Serial.write()` method. This method is meant for sending raw bytes through the serial port. Since you are printing text, you probably want the numeric value `NDVIred` to be printed out as text, as a decimal number.

For printing text, use `Serial.print()` and `Serial.println()`:

```
Serial.print("NDVI: "); Serial.println(NDVIred);

```
> 1 votes

---
Tags: serial
---


title: Arduino uno R4 vs ESP32 Dev board

text:
# Question
Title: Arduino uno R4 vs ESP32 Dev board
I was wondering what product would work best for my application. I need a web server interface to control several digital outputs connected to my board, and it needs to be as polished as it can be.

In the past I have extensively used ESP32 Dev boards with async web server and often used the integrated memory to save both html and image files to make the web server interface nicer. I was going to buy an ESP32 Dev board once again but then the uno R4 came out and now I am a bit confused on what to choose. In short, my questions are:

* can I load a source file alongside images and html files on the new uno like I did with the ESP32 (since from what I understand you could not do that in previous revisions of the uno)?
* can I use the uno R4's ESP32 GPIO pins alongside the ones already provided on the uno?
* is there any real advantage of the uno R4 over the ESP32 Dev board for the application I described? Thanks in advance and sorry if the question is ill posed, I am not really practical with some of the hardware concepts involved!

# Answer
> 1 votes
I did not test the UNO R4 yet, so this is completely based on the technical documents.

For a polished web interface, you will need some space to save all the data. Remember you need some space for the code, too, so these numbers are an upper bound and free space for HTML, CSS and images is a good portion less.

* Standard ESP32 Dev Board: mostly 4 MB flash ROM (but can be 8 or 16).
* UNO R4: 256 kB Flash ROM on the main chip, 384 kB ROM on the ESP32-S3-Mini-1-N8 that is used for WiFi.

This suggests that you do have way more space on the ESP32 DevBoard, making it more future-proof.

Another point that may be of interest is interrupts. WiFi does not like to be blocked by interrupt handlers, so if your code relies on interrupts, you may like multiple cores: That way, your code is not hampered by transferring the website.

* The ESP32 has two cores, but you may need to keep an eye on which threads run on which cores. (I sometimes do have problems with time-critical applications like updating a string of WS2812b LEDs while loading the control website.)
* The UNO R4 has completely separate chips for your sketch and the WiFi stack, but to run the web interface completely from its ESP32-S3-Mini-1-N8, I assume that you have to re-flash it with your own sketch. This probably (again, I'm interpolating from datasheets) means that you have program the UNO R4 as if it has two completely separate chips on it; and you'd have to create their communication protocol by yourself.

For your needs, this sounds as if you're better off using ESP32 DevBoards; maybe two if you run into the same problem as me.

Now, to directly answer your questions:

* For serving files via webserver from Arduino UNO R4, I did not find much. Presumably the LittleFS filesystem works on Arduino UNO; and "just serving files" on ESP8266/ESP32 requires them to be in SPIFFS or LittleFS (to my knowledge). It may be that library support for this use case will improve with the release of the UNO R4, but for now, it looks like ESP32 is your best bet.
* You may be able to use the GPIOs of the ESP on the UNO R4, but I'd assume that you will have to provide your own sketch/firmware for the ESP. Also, keep in mind that the UNO itself has 5V GPIOs, while the ESP has 3.3V GPIOs *and you must not mix those voltages*.
* The only advantage of the UNO R4 over a ESP32 that I can see for you is: The GPIOs have 5V and you can run the board on 7-24V or USB. This makes the board more compatible with a lot of modules sold "for Arduino".

In the end, I probably would go for ESP32 and design every periphery on 3.3V or with level shifters; and add a second ESP32 if you run into the problem of the web interface interfering with your basic operation.

---
Tags: arduino-uno, esp32, web-server
---


# Question
Title: Errors when trying to connect esp8266 to firebase
hello guys i was trying to connect my project to firebase but got this erorrs:

```
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\Firebase.cpp: In member function 'int FirebaseRequest::sendRequest(const string&, const string&, char*, const string&, const string&)':
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\Firebase.cpp:78:1: error: no return statement in function returning non-void [-Werror=return-type]
   78 | }
      | ^
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\Firebase.cpp: In member function 'void FirebaseStream::startStreaming(const string&, const string&, const string&)':
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\Firebase.cpp:91:16: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
   91 |   analyzeError("STREAM", status, path_with_auth);
      |                ^~~~~~~~
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\FirebaseHttpClient_Esp8266.cpp: In member function 'virtual void FirebaseHttpClientEsp8266::begin(const string&)':
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\FirebaseHttpClient_Esp8266.cpp:47:50: error: no matching function for call to 'begin(const char*, const char [60])'
   47 |     http_.begin(url.c_str(), kFirebaseFingerprint);
      |                                                  ^
In file included from d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\FirebaseHttpClient_Esp8266.cpp:9:
C:\Users\NyK\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266HTTPClient\src/ESP8266HTTPClient.h:166:10: note: candidate: 'bool HTTPClient::begin(String, uint16_t, String)' (near match)
  166 |     bool begin(String host, uint16_t port, String uri = "/")  __attribute__ ((error("obsolete API, use ::begin(WiFiClient, host, port, uri)")));
      |          ^~~~~
C:\Users\NyK\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266HTTPClient\src/ESP8266HTTPClient.h:166:10: note:   conversion of argument 2 would be ill-formed:
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\FirebaseHttpClient_Esp8266.cpp:47:30: error: invalid conversion from 'const char*' to 'uint16_t' {aka 'short unsigned int'} [-fpermissive]
   47 |     http_.begin(url.c_str(), kFirebaseFingerprint);
      |                              ^~~~~~~~~~~~~~~~~~~~
      |                              |
      |                              const char*
In file included from d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\FirebaseHttpClient_Esp8266.cpp:9:
C:\Users\NyK\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266HTTPClient\src/ESP8266HTTPClient.h:167:10: note: candidate: 'bool HTTPClient::begin(String, const uint8_t*)' (near match)
  167 |     bool begin(String url, const uint8_t httpsFingerprint[20])  __attribute__ ((error("obsolete API, use ::begin(WiFiClientSecure, ...)")));
      |          ^~~~~
C:\Users\NyK\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266HTTPClient\src/ESP8266HTTPClient.h:167:10: note:   conversion of argument 2 would be ill-formed:
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\FirebaseHttpClient_Esp8266.cpp:47:30: error: invalid conversion from 'const char*' to 'const uint8_t*' {aka 'const unsigned char*'} [-fpermissive]
   47 |     http_.begin(url.c_str(), kFirebaseFingerprint);
      |                              ^~~~~~~~~~~~~~~~~~~~
      |                              |
      |                              const char*
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\FirebaseHttpClient_Esp8266.cpp: In member function 'virtual void FirebaseHttpClientEsp8266::begin(const string&, const string&)':
d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\FirebaseHttpClient_Esp8266.cpp:51:60: error: invalid conversion from 'const char*' to 'const uint8_t*' {aka 'const unsigned char*'} [-fpermissive]
   51 |     http_.begin(host.c_str(), kFirebasePort, path.c_str(), kFirebaseFingerprint);
      |                                                            ^~~~~~~~~~~~~~~~~~~~
      |                                                            |
      |                                                            const char*
In file included from d:\Kuliah\Mata Kuliah\Internet of Things\Arduino\libraries\FirebaseArduino\src\FirebaseHttpClient_Esp8266.cpp:9:
C:\Users\NyK\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.1.2\libraries\ESP8266HTTPClient\src/ESP8266HTTPClient.h:168:70: note:   initializing argument 4 of 'bool HTTPClient::begin(String, uint16_t, String, const uint8_t*)'
  168 |     bool begin(String host, uint16_t port, String uri, const uint8_t httpsFingerprint[20])  __attribute__ ((error("obsolete API, use ::begin(WiFiClientSecure, ...)")));
      |                                                        ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
cc1plus.exe: some warnings being treated as errors

exit status 1

Compilation error: exit status 1

```

i've installed the latest version of esp8266 and **"Firebase Arduino Client Library for ESP8266 By Mobitz"** but the error still occured. please help

here's my full code:

```

#include <ESP8266WiFi.h>
#include <SoftwareSerial.h>
#include <FirebaseArduino.h>
#include <ArduinoJson.h>
#include <ESP8266HTTPClient.h>
#include<DHT.h>

#define FIREBASE_HOST "*****firebaseio.com"
#define FIREBASE_AUTH "*****UKBpSMo07nUT8ZWYS9"

#define WIFI_SSID "******"
#define WIFI_PASSWORD "******"

#define DHTPIN D5
#define DHTTYPE DHT11

DHT dht(DHTPIN, DHTTYPE);

bool light;
bool fan;

unsigned long previousMillis = 0;
const long interval = 10000;

void setup() {
  pinMode(D1, OUTPUT);
  Serial.begin(115200);
  delay(500);
  WiFi.begin(WIFI_SSID,WIFI_PASSWORD);
  Serial.println("Connecting..");

  while (WiFi.status() != WL_CONNECTED){
    Serial.print(".");
    delay(500);
  }
  Serial.println();
  Serial.print("Connected");
  Serial.println(WiFi.localIP());

  Firebase.begin(FIREBASE_HOST,FIREBASE_AUTH);
  dht.begin();

  delay(2000);
  // put your setup code here, to run once:
}

void readDatas(){
  float h=dht.readHumidity();
  float t=dht.readTemperature();

  Firebase.setFloat("Data/Temperature:",t);
  Firebase.setFloat("Data/Humidity:",h);
}

void loop() {
  light = Firebase.getBool("LightStates/switch");
  Serial.println(light);
  if(light==true){
    digitalWrite(D6, HIGH);
  }
  if(light==false){
    digitalWrite(D6, LOW);
  }

  fan = Firebase.getBool("FanStates/switch");
  Serial.println(fan);
  if(fan==true){
    digitalWrite(D7, HIGH);
  }
  if(fan==false){
    digitalWrite(D7, LOW);
  }

  unsigned long currentMillis = millis();
  if(currentMillis-previousMillis>=interval){
    readDatas();
    previousMillis=currentMillis;
  }

}

```

# Answer
> 1 votes
fixed by downgrading my esp8266 version to 2.7

---
Tags: esp8266, arduino-ide
---


# Question
Title: Run Arduino Uno with battery AND use 5V output
Newbie here: I built a working binary clock with my Arduino UNO R3, see Picture 1. From my understanding the power supply for the Arduino itself is via USB, and I use the 5V output to supply power to the switch. Now, **I would like the Arduino to run on battery and keep using its 5V power output** \- instead of only when it is connected to the PC.

From what I gathered on the internet, e.g. this page, I can simply connect the + end of my battery to the Vin port and the - end to GND. However, none of the pages I found deal with what to do with the "surrounding power infrastructure". Can I just keep it as is and use the wiring as in Picture 2 (USB is disconnected), i.e. is it safe to connect my 9V battery now? Or is there a better alternative?

Sorry for the beginner question. I am having so much fun learning with the Arduino (blasted through half the starter kit project handbook in just two days -\> this is my variant of the digital hourglass) and don't want it to go up in flames already.

UPDATE: After the answers suggested that my idea should work, I tried it and, indeed, it works OK. I am getting a lot of Arduino resets/restarts though. Thanks for the replies!

# Answer
> 1 votes
It is almost always better to add a schematic to your question. Backwards engineering from a picture can be confusing at times and lead to incorrect assumptions.

What you want to do appears to be possible. It looks like you are injecting 9 Volts positive at VIN (Pin 8 of the POWER header). Examining the Arduino Uno R3 schematic here we see the VIN net connected to the input Pin 8 of the POWER header and also to the input side of the 5 Volt regulator (NCP1117ST50T3G). This distributes the 5 Volts to the Atmel processor (appears to power the LED directly) and to the external switch which is assumed to be normally open but when closed connects to a 10Kohm resistor to ground.

The total current needed by external devices connected to the Arduino Uno R3 5 Volt regulator should be considered in such a design. The NCP1117ST50T3G data sheet here state the regulator can handle in excess of 1 Amp (or 1000mA).

Assuming the LEDs take at most 20mA each and a worse case of all LED in the on state, that is 6 x 20mA or 120mA. Also, when the switch is closed there is a current path from 5 Volts to ground through a 10Kohm resistor. Using V = A x R we see that A = V / R = 5 / 10000 = 0.5mA when the switch is closed. So the total current the external devices might use is likely no more than 120.5mA. This is far less than 1000mA (the upper limit of the Arduino's 5 Volt regulator) so appears well withing safety margins.

However, an Alkaline 9 Volt battery only contains about 550mAh. Ignoring the current it takes to run the Arduino Uno R3, we see that dividing the worst case external current demand of 120.5mAh into 550mAh we get 4.6 hours of use. An Alkaline AA 1.5 Volt battery contains about 2000mAh.. You would need 6 AA 1.5 Volt batteries in series to generate 9 Volts. But they should last about 4 times longer.

# Answer
> 1 votes
Yes, that should work, albeit inefficiently: for every milliwatt of power consumed by an LED, you will have roughly 0.7 mW dissipated in the series resistor, and 1.3 mW dissipated in the Arduino's voltage regulator. Given the low capacity of 9 V batteries, I doubt your clock will run for very long.

# Answer
> 1 votes
You could certainly use a 9V battery into the VIN port on your Arduino, but the built-in power supply uses a "linear voltage regulator", which is quite inefficient. If your goal is long battery life you'd be much better off with a buck style power supply or a switching power supply. Those are a LOT more efficient.

You should be able to find modestly priced power supplies built for Adruino online that are a lot more efficient than the built-in supply.

(And as mentioned, 9V batteries have a very small capacity. 6 AA or even C batteries would last a lot longer.)

---
Tags: power, battery
---


# Question
Title: Arduino Uno WiFi Rev2 is sending serial data to IDE, but not to C# program
I have an Arduino Uno WiFi Rev2 which I am trying to read data over the serial port from (using C#). The Arduino program periodically emits data to the serial port (for testing purposes). Whenever the Arduino writes to the serial, it also toggles the onboard LED to prove it is still running.

Everything seems to run fine. The LED periodically blinks and thus proves the loop runs as expected. Using the Serial Monitor on the Arduino IDE also correctly echoes the data that the Arduino emits.

Here is the program:

```
int keepAlive = 500;
unsigned long lastKeepAlive = 0;
char ledState = 0;

void setup() {
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  if (millis() > lastKeepAlive + keepAlive) {
    lastKeepAlive = millis();
    Serial.println("Alive");
    if (ledState == 0) ledState = 1; else ledState = 0;
    digitalWrite(LED_BUILTIN, ledState);
  }
  delay(5);
}

```

Another reason why I know it works is because the TX LED on the Arduino blinks whenever it writes on the port.

However, once I close the IDE, the Arduino "stops" writing to the serial port. Maybe because it doesn't have to - there is no connection. Fine with me. Also: the TX-LED stops blinking while the onboard-LED keeps toggling on and off. So the loop still runs fine.

Now I'd like to read out the serial data via C#. For that I've written a simple program like so:

```
var port = new SerialPort("COM6", 115200, Parity.None, 8, StopBits.One);
port.Open();
port.Write("123");
while (true)
{
  Console.WriteLine(port.BytesToRead);
  await Task.Delay(1000);
}

```

I expect this program to tell me how many bytes are waiting to be read. But it keeps printing `0` endlessly. Also: the TX-LED does not light up on the Arduino. On the other hand, note that little `port.Write` in the program - it's a test to verify the communication between the Arduino and C#. In fact: I can briefly see the RX-LED on the Arduino light up when my program sends the `123`. I reckon the port and it's settings are correct then.

When I close my program, and the open up the IDE again, the Arduino starts to emit serial data again, the TX-LED starts blinking again and data arrives in the Serial Monitor.

All the while the onboard-LED keeps toggling on and off merrily.

What am I doing wrong? Why is the Arduino talking to the IDE but not to my program? Do I have to initiate some kind of handshake?

# Answer
I have solved the issue and @jsotola was correct in pointing out the problem lay with the C# program.

What mislead me was the fact that the TX and RX leds apparently only blink when data is *read* from the respective buffer, not when it is *written* to. In other words: the Arduino kept happily writing to the serial port (as expected) but the TX led did not light up because no one was reading what it wrote. I dind't know that.

For anyone else having this issue: I had to set `DtrEnable` to true. This is still a little confusing to me though. I am not new to programming in C# and with serial ports at all. Yet, I have never had to do this. Also, according to documentation this flag is used when using XOn/XOff or RTS handshake. None of which I am using.

I also tried with PuTTY. I did not configure anything aside from the port name and the baud rate and it worked right away. Investigating, I found that PuTTY apparently defaults to XOn/XOff.

So I'm guessing it really is XOn/XOff then ...

I updated my program like this:

```
var port = new SerialPort("COM6", 115200, Parity.None, 8, StopBits.One);
port.DtrEnable = true;
port.Open();
...

```
> 0 votes

---
Tags: arduino-uno, serial, c#
---


# Question
Title: How to configure I2S with ESP32 and MAX98357A to reproduce wav files?
I have configured I2S to reproduce files with an ESP32 and a MAX98357A from and SD card. The problem is that it reproduces the files way too fast, like they are sped up * 100. Here is my (simplified) code:

```
#define I2S_DOUT 25
#define I2S_BCLK 27
#define I2S_LRC 26

void setup() {
// Start SD card and sqlite
  SPI.begin();
  if (!SD.begin()) {
    Serial.println("SD card not found");
    while (1) {};
  }
// Configure I2S
  i2s_config_t i2s_config = {
      .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
      .sample_rate = 44100,
      .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
      .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
      .communication_format = I2S_COMM_FORMAT_I2S_MSB,
      .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
      .dma_buf_count = 2,
      .dma_buf_len = 1024,
      .tx_desc_auto_clear = true,
  };

  i2s_pin_config_t pin_config = {
      .bck_io_num = I2S_BCLK,
      .ws_io_num = I2S_LRC,
      .data_out_num = I2S_DOUT,
      .data_in_num = -1,
  };

  i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
  i2s_set_pin(I2S_NUM_0, &pin_config);
  i2s_set_dac_mode(I2S_DAC_CHANNEL_RIGHT_EN);
  i2s_set_sample_rates(I2S_NUM_0, 44100);
}

void loop() {
// Play the audio file
  string filename = "/audios/" + text + ".wav";
  File file = SD.open(filename.c_str());
  if (!file) {
    Serial.println("Failed to open file for reading");
    return;
  }

  const size_t buffer_size = 512;
  uint8_t buffer[buffer_size];
  size_t bytes_read;
  size_t bytes_written;
  while (file.available() && (bytes_read = file.read(buffer, buffer_size)) > 0) {
    i2s_write(I2S_NUM_0, buffer, bytes_read, &bytes_written, portMAX_DELAY);
    if (bytes_read == 0) break;
  }
  file.close();
}

```

How do I configure it correctly?

# Answer
So I figured it out (a somewhat long time ago) but forgot to post here hahaha.

Basically, the `i2s_config_t` was not properly configured. Here's a corrected version:

```
i2s_config_t i2s_config = {
      .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
      .sample_rate = 44100,
      .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
      .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
      .communication_format = I2S_COMM_FORMAT_I2S_MSB,
      .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
      .dma_buf_count = 8,
      .dma_buf_len = 1024,
      .use_apll = false,
      .tx_desc_auto_clear = true,
  };

```

If you compare, the `.channel_format` configuration changes from `I2S_CHANNEL_FMT_RIGHT_LEFT` to `I2S_CHANNEL_FMT_ONLY_LEFT`. This is important because when using `RIGHT_LEFT` and only using one amplifier, 2 sound outputs were sent but only one amp was receiving them, causing the sound to play at twice the speed. Now, the `.dma_buf_count` was increased to 8, and added the `.use_apll` config, because I saw it somewhere else, I don't really know what it does hahaha.

There are other things.
In the setup for the i2s communication, I didn't include

```
i2s_set_dac_mode(I2S_DAC_CHANNEL_RIGHT_EN);
i2s_set_sample_rates(I2S_NUM_0, 44100);

```

And created a new function, `play_sound`.

Here's the complete code:

```
// sound.cpp

#include <sound.h>

bool parseWavHeader(File &file, WavHeader &header) {
  if (file.read() != 'R' || file.read() != 'I' || file.read() != 'F' || file.read() != 'F') {
    Serial.println("Invalid WAV file");
    return false;
  }

  file.seek(22);
  header.num_channels = file.read() | (file.read() << 8);
  header.sample_rate = file.read() | (file.read() << 8) | (file.read() << 16) | (file.read() << 24);
  file.seek(34);
  header.bits_per_sample = file.read() | (file.read() << 8);
  file.seek(44);  // Skip to the audio data
  return true;
}

void setup_sound() {
  i2s_config_t i2s_config = {
      .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
      .sample_rate = 44100,
      .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
      .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
      .communication_format = I2S_COMM_FORMAT_I2S_MSB,
      .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
      .dma_buf_count = 8,
      .dma_buf_len = 1024,
      .use_apll = false,
      .tx_desc_auto_clear = true,
  };

  i2s_pin_config_t pin_config = {
      .bck_io_num = I2S_BCLK,
      .ws_io_num = I2S_LRC,
      .data_out_num = I2S_DOUT,
      .data_in_num = -1,
  };

  i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
  i2s_set_pin(I2S_NUM_0, &pin_config);
}

void play_sound(std::string text, fs::FS &SD) {
  std::string filename = "/audios/" + text + ".wav";
  File file = SD.open(filename.c_str());
  if (!file) {
    Serial.println("Failed to open file for reading");
    while (1) delay(1);
  }

  WavHeader header;
  if (!parseWavHeader(file, header)) {
    Serial.println("Invalid WAV file");
    return;
  }

  i2s_set_sample_rates(I2S_NUM_0, header.sample_rate);

  const size_t buffer_size = 512;
  uint8_t buffer[buffer_size];
  size_t bytes_read;
  size_t bytes_written;
  while (file.available() && (bytes_read = file.read(buffer, buffer_size)) > 0) {
    i2s_write(I2S_NUM_0, buffer, bytes_read, &bytes_written, portMAX_DELAY);
    if (bytes_read == 0) break;
  }

  file.close();
}

```

```
// sound.h

#ifndef SOUND_H
#define SOUND_H

#include <SD.h>
#include <driver/i2s.h>

#define I2S_DOUT 25
#define I2S_BCLK 33
#define I2S_LRC 26

struct WavHeader {
  uint32_t sample_rate;
  uint16_t bits_per_sample;
  uint16_t num_channels;
};

bool parseWavHeader(File &file, WavHeader &header);
void setup_sound();
void play_sound(std::string text, fs::FS &SD);

#endif  // SOUND_H

```

Hope it helps you not go through the struggle I went through!
> 2 votes

---
Tags: esp32, sound
---


# Question
Title: How to optimize checking for specific string in a UART stream
I want to check for specific string (like "RecordStart") in a UART stream (115 200 baud 8N1) from a camera, to know when it is recording or not/if there is an SD. I am using an ESP32-WROOM-32UE with 16MB flash. I wired the Tx from the camera to one of the pin of the ESP. The ESP32 is programmed with VsCode (platformIO) through Arduino framework. I am using freeRTOS.

The thing is, "RecordStart" or "RecordStop" or other strings, appear just one time. Sometimes (when the camera is powering on), there are many many strings sended, very fast. So, from time to time, I lose some bytes and I can't find the strings I am looking for. I would like to optimize my code to never miss a string.

*How the code works ?* If there is at least 1 byte in the serial buffer, the *taskUART* priority is set to 2 (while other tasks are priority 1. If a null character is detected, the *message\_UARTcam* buffer starts to be filled. Then, each time a byte enters the buffer, I am checking if the buffer contains the strings I am looking for. It is working quite well but sometimes, I lose some bytes and the strings are not detected. I think It is because many other tasks are running and the serial buffer fills up faster than it empties. Increase temporarily the priority of the UART task improves the detection but I am still missing some bytes.

*The code:*

```
void taskUART(void *parameter)
{
  while (1)
  {
    if (SerialPortCam.available() > 0)
    {
      vTaskPrioritySet(nullptr, 2);
      char incomingChar = SerialPortCam.read();
      // Serial.write(incomingChar);

      if (flagNullChar == 1 || bufferIndex_UARTcam > 0 && bufferIndex_UARTcam < BUFFER_LEN_UART_CAM)
      {
        message_UARTcam += incomingChar;
        // Serial.println(message);

        if (message_UARTcam.indexOf(stringStart_app) != -1 || message_UARTcam.indexOf(stringStart_button) != -1)
        {
          // Serial.println("Start recording");
          SD_UARTcam = 1;
          record_UARTcam = 1;
          bufferIndex_UARTcam = 0;
          message_UARTcam = "";
        }
        else if (message_UARTcam.indexOf(stringStop) != -1)
        {
          // Serial.println("Stop recording");
          record_UARTcam = 0;
          bufferIndex_UARTcam = 0;
          message_UARTcam = "";
        }
        else if (message_UARTcam.indexOf(stringSdError) != -1)
        {
          // Serial.println("SD error");
          SD_UARTcam = 0;
          record_UARTcam = 0;
          bufferIndex_UARTcam = 0;
          message_UARTcam = "";
        }
        else if (message_UARTcam.indexOf(stringSdInitOk) != -1)
        {
          // Serial.println("SD init OK");
          SD_UARTcam = 1;
          bufferIndex_UARTcam = 0;
          message_UARTcam = "";
        }
        else if (message_UARTcam.indexOf(stringSdRemoved) != -1)
        {
          // Serial.println("SD removed");
          SD_UARTcam = 0;
          record_UARTcam = 0;
          bufferIndex_UARTcam = 0;
          message_UARTcam = "";
        }

        bufferIndex_UARTcam++;
        flagNullChar = 0;
      }

      if (incomingChar == 0x00)
      {
        flagNullChar = 1;
        message_UARTcam = "";
        bufferIndex_UARTcam = 0;
      }
    }
    else
    {
      vTaskPrioritySet(nullptr, 1);
    }
  }
}

```

*Camera output example:*

```
␛[0;36m[00105849][CA9] ␀[App - Connected] <OnMessage> Received msg: 0xE001000C (param1 = 0x0 / param2 = 0x0)␛[0m
␛[0m[00105849][CA9] ␀RecCapState:0 RecCurrMode:0 RecNextMode:0 GFlags:0X7 Flags:0 StreamType:0␛[0m
␛[0m[00105849][CA9] ␀[App - Widget] <Off> widgetId: -1␛[0m
␛[0;33m[00105849][CA9] ␀[App_Glob_PWM_Buzzer] PWM Buzzer : 2␛[0m
␛[0m[00105849][CA9] ␀[App - ButtonOp] <MgrTask> Received msg: 0x0 (Param1 = 0x0 / Param2 = 0x0)␛[0m
␛[0m[00105849][CA9] ␀[App - ButtonOp] <MgrTask> Received msg: 0x1 (Param1 = 0x0 / Param2 = 0x0)␛[0m
␛[0m[00105899][CA9] ␀[rec_connected_cam_record_start] Start␛[0m
␛[0m[00105899][CA9] ␀[App - Connected] <RecordStart> REC_CONNECTED_CAM_RECORD_START␛[0m
␛[0m[00105899][CA9] ␀Dechi.motion_detec: 0␛[0m
␛[0m[00105899][CA9] ␀[Applib - ExtendEnc] <_ExtendEnc_SetEnableStatus> Enable flag: 0␛[0m
␛[0m[00105899][CA9] ␀[AppLib - MuxMp4] <SetTrickRecDivisor> Cur TrickRecDivisor: 1, New TrickRecDivisor: 1␛[0m
␛[0;34m[00105899][CA9] ␀[App - Sensor] <GetVinMode> Vin Mode = 11␛[0m

```

# Answer
> 1 votes
Here is an idea that *may* work: instead of buffering the input stream and comparing the buffer with the search string, you could do the comparison on the fly, as you receive the characters. Then you have no buffering at all, and no time spent in scanning through the buffer.

Below is a function that searches for the `"RecordStart"` marker, while being fed one character at a time. This function remembers how many correct characters it has received so far (this is the static variable `pos`), and updates this count on each received character. It returns `true` when it has just detected the marker, and `false` otherwise:

```
bool marker_found(int c) {
    const char marker[] = "RecordStart";  // search string
    static int pos = 0;  // correct characters received so far
    if (c == -1) return false;  // shortcut for a common case
    if (c == marker[pos]) {
        pos++;                      // count a correct character
        if (marker[pos] == '\0') {  // we got the complete string
            pos = 0;                // reset for next time
            return true;            // report success
        }
    } else if (c == marker[0]) {
        pos = 1;        // we have the initial character again
    } else {
        pos = 0;        // we received a wrong character
    }
    return false;
}

```

You would use it like this:

```
if (marker_found(SerialPortCam.read())) {
    // handle the incoming record
}

```

Note that you do not need to test for `SerialPortCam.available() > 0`, as this is already handled by `marker_found()`.

---
Tags: esp32, uart, code-optimization, platformio, buffer
---


# Question
Title: Are variables declared in main.cpp static, instance, or...?
Let's suppose you've just created a new Arduino project using PlatformIO, or an IDE like Sloeber. You now have a file named "main.cpp" with two functions (methods?):

* void setup()
* void loop()

Now, suppose you follow Arduino coding norms, and stick something at the top like:

```
hd44780_I2Cexp lcd(0x27);

```

Is the hd44780\_I2Cexp object instantiated by it static? Or is main.cpp #include'd into some class in a way that makes everything in it private or public members of that class?

If they're instance methods, is it absolutely 100% guaranteed that the instance is, and forever shall be, a singleton? Or is there any conceivable scenario where there could be two simultaneous instances of it (say, if you were using both cores of an ESP32)?

If it's an instance, but guaranteed to forever be singleton on any future platform that calls itself "Arduino", is there any *need* to care about the distinction between "instance member" and "static variable" (in the context of main.cpp)?

Should main.cpp "really" have a separate main.h file, and "official" `public:` and `private:` blocks for the sake of C++ linguistic purity, or would I just be creating real or potential problems for the sake of intellectual exercise and ideology?

# Answer
In the Arduino IDE, `setup` and `loop` are functions, not instances of anything.

There is a file included in the compilation sequence, main.cpp, which has the following code (slightly simplified here):

```
#include <Arduino.h>

int main(void)
{
    init();

    setup();

    for (;;) {
        loop();
    }

    return 0;
}

```

So you can see that this bit of "sugar" basically calls `setup` once and `loop` repeatedly.

The other function, `init`, initialises some hardware, like the timers, so that `millis()` and `delay()` work as documented.

I can't speak for other IDEs but I assume they do similar things, in order to be compatible.
> 0 votes

# Answer
Whatever you define outside of any function will be global, which is static - it lives for the duration of program execution - and visible to all compilation units that are bound into the eventual execution unit.

If you also include the 'static' declaration ahead of the type, the variable will be file-level static, meaning it will be visibile only within the current file.

This is standard C/C++ behavior for any data type - scalars; vectors, structs & arrays; and objects (C++ only, of course).
> 0 votes

---
Tags: c++
---


# Question
Title: MHZ19B Sensor - Library not found- Please Help!
I can't seem to figure out what the problem is here. I am trying to upload this code to Arduino Uno but it keeps telling me that the library is not found. I did download the library for the MHZ sensors but it doesn't like it. I am somewhat new to Arduino. Please help! This is the code:

```
// Libraries
#include <DHT.h>
#include <SD.h>
#include <SoftwareSerial.h>
#include <MHZ19B.h>

// Constants
const int chipSelect = 10;   // SD card chip select pin
#define DHTPIN 7             // DHT sensor pin
#define DHTTYPE DHT22        // DHT sensor type
#define MHZ19B_TX_PIN 8      // MHZ19B sensor TX pin
#define MHZ19B_RX_PIN 9      // MHZ19B sensor RX pin

// Variables
DHT dht(DHTPIN, DHTTYPE);
File dataFile;

MHZ19B mhz19b;
float hum;      // Humidity value
float temp;     // Temperature value
int lightVal;   // Light sensor value
int co2;        // CO2 concentration

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

  Serial.print("Initializing SD card...");
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    while (1);
  }
  Serial.println("card initialized.");

  Serial.print("Initializing MHZ19B sensor...");
  mhz19b.begin(MHZ19B_TX_PIN, MHZ19B_RX_PIN);
  Serial.println("MHZ19B sensor initialized.");
}

void loop()
{
  lightVal = analogRead(A1);
  Serial.print("Light Value: ");
  Serial.println(lightVal);
  delay(50);

  hum = dht.readHumidity();
  temp = dht.readTemperature();
  Serial.print("Humidity: ");
  Serial.print(hum);
  Serial.print(" %, Temp: ");
  Serial.print(temp);
  Serial.println(" Celsius");
  delay(5);

  co2 = mhz19b.getCO2();
  Serial.print("CO2 Concentration: ");
  Serial.print(co2);
  Serial.println(" ppm");

  dataFile = SD.open("datalog.txt", FILE_WRITE);

  if (dataFile) {
    dataFile.println("Light Value: ");
    dataFile.println(lightVal);
    delay(50);

    hum = dht.readHumidity();
    temp = dht.readTemperature();
    dataFile.print("Humidity: ");
    dataFile.println(hum);
    dataFile.print(" %, Temp: ");
    dataFile.println(temp);
    dataFile.println(" Celsius");

    co2 = mhz19b.getCO2();
    dataFile.print("CO2 Concentration: ");
    dataFile.print(co2);
    dataFile.println(" ppm");

    delay(5000);
    dataFile.close();
  }
  else {
    Serial.println("Error opening datalog.txt");
  }

  delay(1000);
}

```

# Answer
That's because it should be either `#include <MHZ.h>` for the MH-Z CO2 Sensors library or `#include <MHZCO2.h>` for the MHZCO2 one.

How do you typically include the libraries you download? Thru the library manager? The way you can do it in Arduino IDE 2.0 is going thru *Sketch* -\> *Include Library* -\> the library you want to include -- that should include the correct header.
> 1 votes

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


# Question
Title: How to remember variable values after rebooting an Arduino Uno R3 board?
Is there any way to store the values of necessary variables somewhere (may be in a file that gets updated by the program at various events), which can be read back when program starts after rebooting the Arduino board?

I am trying to control my AC appliances using IR remote control. Where I want Arduino to remember what was on and what was off in my room after a power failure.

Using EEPROM looks like a fairly good solution, though it has a limitation of 100,000 writes which is making me try to find another way out.

Using an external EEPROM which doesn't have that limitation or is fairly big, is a really good idea I got from fuenfundachtzig, thanks for this great idea. But I don't know how to implement this in my project. Any resource to gather knowledge on using external EEPROM, will be much appreciated.

# Answer
The internal RAM of the Arduino will be reset when you repower the chip, so if you want to keep your data, you need to store it in EEPROM.

If you are worried about the limited write/erase cycles, you should estimate how often the data would be updated (i.e. written to EEPROM) and how long you plan the lifetime of the device you build. If 100,000 cycles then still is an issue, you have several options:

* Keep the variables in RAM and only write them to EEPROM say every 5 minutes (100,000 cycles then makes about one year of continuous usage until the EEPROM might fail).
* Use an external EEPROM (in a socket) that could be easily replaced if needed.
* If replacing it is not an option, consider using an FRAM instead (advantage vs EEPROM: *much* more erase/write cycles but also very expensive, so not an option for large amounts of data but certainly for a few variables).

Note, however, that your description sounds like a typical use-case for user settings that you don't want to get lost on reboot. For those the internal EEPROM is the right place: only store them when they're changed and you're golden -- the user won't change them a 100,000 times easily...
> 7 votes

# Answer
EEPROM space, as already mentioned, will work if non-volatile is required. However, you have not qualified if it needs to be non-volatile or not. If not then you can use an \__attribute\__ to define the variable space not to be initialized. As the SRAM on the ATmega's are not cleared by reset or power cycle. The Compiler defaults to initializing them. Where this can be turned off per variable as in the below example:

```
//non-initialized value
union configUnion{
  uint8_t    byte[6]; // match the below struct...
  struct {
    uint16_t value1;
    uint16_t value2;
    uint16_t chksum;
  } val ;
} config  __attribute__ ((section (".noinit")));

void setup() {
  uint16_t sum;
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // prints title with ending line break
  Serial.print("Out of Reset -");
  sum = getchksum();
  printValues();

  if (sum != config.val.chksum) {
    config.val.chksum = sum;
    Serial.print("chksum is incorrect setting config.val.chksum = 0x"); Serial.println(config.val.chksum, HEX);
  }

  config.val.value1++;
  config.val.value2++;
  Serial.print("setup new values - ");
  printValues();
  config.val.chksum = getchksum();
  Serial.print("updating chksum config.val.chksum = 0x"); Serial.println(config.val.chksum, HEX);
}

int counter = 0;

void loop() {
  if (counter < 200) {
    Serial.print("after a while - ");
    printValues();
    Serial.println();
    while (true) {
      continue;
    }
  }
  counter++;
}

void printValues() {
  Serial.print(" value1 = 0x"); Serial.print(config.val.value1, HEX);
  Serial.print(", value2 = 0x"); Serial.print(config.val.value2, HEX);
  Serial.print(", sum = 0x"); Serial.print(getchksum(), HEX);
  Serial.print(", chksum = 0x"); Serial.println(config.val.chksum, HEX);
}

uint16_t getchksum() {
  int sum = 0;
  for (int position = 0; position < (sizeof(config) - sizeof(config.val.chksum)); position++) {
    sum = sum + config.byte[position];
  }
  return sum;
}

```

Output of above code is below. Note that the first output was the result of powering the UNO up with the Reset button depressed and then released after the Monitor window was started. Otherwise the "incorrect setting" print would have been missed, before the monitor window can be started.

```
Out of Reset - value1 = 0xBFED, value2 = 0xD2F9, sum = 0x377, chksum = 0xF457
chksum is incorrect setting config.val.chksum = 0x377
setup new values -  value1 = 0xBFEE, value2 = 0xD2FA, sum = 0x379, chksum = 0x377
updating chksum config.val.chksum = 0x379
after a while -  value1 = 0xBFEE, value2 = 0xD2FA, sum = 0x379, chksum = 0x379

Out of Reset - value1 = 0xBFEE, value2 = 0xD2FA, sum = 0x379, chksum = 0x379
setup new values -  value1 = 0xBFEF, value2 = 0xD2FB, sum = 0x37B, chksum = 0x379
updating chksum config.val.chksum = 0x37B
after a while -  value1 = 0xBFEF, value2 = 0xD2FB, sum = 0x37B, chksum = 0x37B

Out of Reset - value1 = 0xBFEF, value2 = 0xD2FB, sum = 0x37B, chksum = 0x37B
setup new values -  value1 = 0xBFF0, value2 = 0xD2FC, sum = 0x37D, chksum = 0x37B
updating chksum config.val.chksum = 0x37D
after a while -  value1 = 0xBFF0, value2 = 0xD2FC, sum = 0x37D, chksum = 0x37D

```

With this your variables will persist resets. As long as the power is not lost. Noting the above where you will get random data, to start.

Using either EEPROM or .noinit I would recommend that you checksum your persistent variable space during setup and if incorrect you can initialize or issue a warning.
> 3 votes

# Answer
If you really need to update your NVRAM frequently, look into FRAM (Ferroelectric Random Access Memory) which claims a write life of 10^13 cycles (that's ~ 318,000 years if you write once/sec!). They're 8KB, and faster than Flash or EEPROM at 20MHz (SPI).

Adafruit (in the US) sells them on a breakout board for about US$6 in onesies. Or you can buy the bare chips from the usual suppliers for around US$1.30, but not DIP, only SOP8 packages.
> 3 votes

# Answer
Store them in the on-chip EEPROM.
> 2 votes

# Answer
If you're open to a off-chip solution, it isn't too difficult to buy/build an SD card reader.
> 0 votes

# Answer
I am very late to this party ... I just bought an UNO WiFi and I am looking at creating a simple protocol to persist data with a data store on another device connected to the WiFi. Probably will use HTTP with simple end points, treat the remote storage as a contiguous memory block:

```
GET IP:port/addr/len
PUT IP:port/addr data

```

I could also create named blocks (think files):

```
GET IP:port/name
PUT IP:port/name data

```

The actual remote storage could be anything, memory mapped disk file, SQLite3 database, etc.

There are many drawbacks, such as reliance on the external service, connectivity issues, error handling, etc. I could run out of code space just supporting the protocol.

EDIT: I got a little flack for my answer, including downvotes, however, read the OP - he stated "somewhere" for retrieving variable data; a LAN device certainly falls in the category of "somewhere", especially when the UNO has WiFi. My answer might not be suitable for the OP, however, after reading my answer, the OP *might* opt to get a WiFi enabled device. I do not believe in "keyhole" solutions, but rather to provide options that fit the general tone of the question even if it means getting out of its box.
> 0 votes

# Answer
This was puzzling me too. I just wanted to use the onboard button to trigger a "count up an integer" regardless any setup routines. For me, mpflaga's answer gave me the right direction. But the given example was far too complicated for my needs. So here's the bare minimum example for an integer value that survives a reset, counting up. (But NOT a power loss, as it's in RAM!) Enjoy!

```
uint8_t c __attribute__ ((section (".noinit")));

void setup() {
  Serial.begin(9600);
  Serial.print("Just startet. c = ");
  Serial.print(c);
  if(c>7){c=0;}else{c++;}
  Serial.println(" - Waiting for RESET.");
}

void loop() {
  // Do more stuff.
}

```
> 0 votes

---
Tags: power, system-design, eeprom, home-automation
---


title: problem conversion value

text:
# Question
Title: problem conversion value
I have two functions that return an int16\_t but I need to convert the ints to char\* is for an attiny13

It would be something like this

```
const char* msg = "value1()"+','+"value2()"+','+"value3()"

```

like example

```
#include "TinyRF_TX.h"

void setup(){
  // transmitter default pin is pin #2. You can change it by editing Settings.h
  setupTransmitter();
}

void loop(){

  const char* msg = "Hello from far away!";

  //send function accepts an array of bytes as first argument
  //second argument is the length of the array
  send((byte*)msg, strlen(msg));

  //make sure there's at least a TX_DELAY_MICROS delay between transmissions
  //otherwise the receiver's behavior will be undefined
  delayMicroseconds(TX_DELAY_MICROS);

```

# Answer
You will need to build the string yourself. Probably the easiest way is using the `sprintf()` function which will take a bunch of arguments and convert them to a string based on formatting instructions you give it.

An apropos article here... https://www.programmingelectronics.com/sprintf-arduino/
> 3 votes

---
Tags: attiny, attiny85, attiny13
---


# Question
Title: How to divide high input frequency by 1.25 like old-school TTL logic by Arduino?
In modern timekeeping, there is a 10 MHz reference frequency (or any power of 10). The digital clock takes 32768 Hz frequency only (or some other power of 2 possible).

The problem is how to convert power of 10 to power of 2 nicely. It is done by a series of 1.25 (every 5 inputs output 4) and 2.5 dividers (every 5 inputs output 2).

I am interested in how this can be done by Arduino. I have a high input frequency, say 1 MHz, therefore i have to use registers directly. Then I have output frequency 1/2 (counter of 2) of the input and 1/4 of the input frequency and I would like to have output 4/5 of the input (divide by 1.25 counter). So, do I need 3 output pins, 1 for counting twos, one for fours, and one for fives? Or can this be done somehow just by 1 input pin and 1 output pin with 4/5 input frequency?

I tried to modify the code but I can not tell how to skip every 5th cycle. Let's say in the chaining of these counters I can get from 1 000 000 Hz frequency: 1000000 Hz - 800000 Hz - 640000 Hz - 512000 Hz - 409600 Hz - 327680 Hz - 2262144 Hz so input = power of ten, then output = power of two My question is how high could be the maximal input frequency to this code? and can you please help me to modify that code?

```
/*
 * From one square wave generate 3 waves 1/2, 1/4 and 4/5 of the original frequency.
 *
 * Original sketch tried to be modified from here:
 *
 * https://arduino.stackexchange.com/questions/63202
 *                               _   _   _   _   _   _   _   _   _   _
 *  input:  digital 13 = PB7    / \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/  1 000 000 Hz
 *                              R1F0R1F0R1F0R1F0R1F0R1F0R1F0R1F0R1F0R1F0R
 *                               ___     ___     ___     ___     ___
 *  output: digital 10 = PB4    /   \___/   \___/   \___/   \___/   \___/    500 000 Hz
 *                              R 1 F 0 R 1 F 0 R 1 F 0 R 1 F 0 R 1 F 0 R
 *                               _______         _______         _______
 *  output: digital 11 = PB5    /       \_______/       \_______/       \    250 000 Hz
 *                              R   1   F   0   R   1   F   0   R   1   F
 *                               _   _   _   _       _   _   _   _
 *  output: digital 12 = PB6    / \_/ \_/ \_/ \_____/ \_/ \_/ \_/ \_____/    800 000 Hz
 *                              R1F0R1F0R1F0R1F00000R1F0R1F0R1F0R1F00000R
 */

int main(void)
{
    DDRB = _BV(PB4) | _BV(PB5) | _BV(PB6) | ~_BV(PB7);  // PB4 PB5 PB6 as outputs and PB7 as input
    for (;;) {
        loop_until_bit_is_clear(PINB, PB7);             // wait for rising input
        loop_until_bit_is_set(PINB, PB7);
        PORTB |= _BV(PB4);                              // rise PB4

        loop_until_bit_is_clear(PINB, PB4);             // wait for rising input
        loop_until_bit_is_set(PINB, PB4);
        PORTB |= _BV(PB5);                              // rise PB5

        loop_until_bit_is_clear(PINB, PB5);             // wait for rising input
        loop_until_bit_is_set(PINB, PB5);
        PORTB |= _BV(PB6);                              // rise PB6

        loop_until_bit_is_clear(PINB, PB7);             // wait for rising input
        loop_until_bit_is_set(PINB, PB7);
        PORTB &= ~_BV(PB4);                             // fall PB4

        loop_until_bit_is_clear(PINB, PB7);             // wait for rising input
        loop_until_bit_is_set(PINB, PB7);
        PORTB |= _BV(PB4);                              // rise PB4

        loop_until_bit_is_clear(PINB, PB4);             // wait for rising input
        loop_until_bit_is_set(PINB, PB4);
        PORTB |= ~_BV(PB5);                             // fall PB5

        loop_until_bit_is_clear(PINB, PB7);             // wait for rising input
        loop_until_bit_is_set(PINB, PB7);
        PORTB &= ~_BV(PB4);                             // fall PB4

        loop_until_bit_is_clear(PINB, PB7);             // wait for rising input
        loop_until_bit_is_set(PINB, PB7);
        PORTB |= _BV(PB4);                              // rise PB4

        loop_until_bit_is_clear(PINB, PB4);             // wait for rising input
        loop_until_bit_is_set(PINB, PB4);
        PORTB |= _BV(PB5);                              // rise PB5

        loop_until_bit_is_clear(PINB, PB5);             // wait for rising input
        loop_until_bit_is_set(PINB, PB5);
        PORTB |= ~_BV(PB6);                             // fall PB6

        loop_until_bit_is_clear(PINB, PB7);             // wait for rising input
        loop_until_bit_is_set(PINB, PB7);
        PORTB &= ~_BV(PB4);                             // fall PB4

        loop_until_bit_is_clear(PINB, PB7);             // wait for rising input
        loop_until_bit_is_set(PINB, PB7);
        PORTB |= _BV(PB4);                              // rise PB4

        loop_until_bit_is_clear(PINB, PB4);             // wait for rising input
        loop_until_bit_is_set(PINB, PB4);
        PORTB |= ~_BV(PB5);                             // fall PB5

        loop_until_bit_is_clear(PINB, PB7);             // wait for rising input
        loop_until_bit_is_set(PINB, PB7);
        PORTB &= ~_BV(PB4);                             // fall PB4
    }
}

```

---

Nick Gamon personally :D I saw you so many times here. what an honour. I do need a source clock for multiplanetary clock, without fractions. The least common multiple for periods of second for: Earth, Mars, Titan.

If I will keep the ratio between planets exactly, then even if the Earth clock using Arduino resonator will drift by a few tens of seconds per day, Mars clock and Titan clock will drift the same amount of time.

This does not matter to me because if I stop the clock and wait then All 3 planets will be aligned again. But if I would not keep the ratio between planets exactly, for Example Earth would drift 30 seconds per day, Mars would drift 31 seconds per day, and Titan would drift 29 seconds per day- it depends on how close approximation I will take. So, by stopping the clock for 30 seconds to set it correctly, Earth would go back to 0 seconds, but Titan would be 1 second behind and Mars would be 1 second before. I would not correct all 3 just by stopping the clock. I would have to stop the clocks 3 times individually (once for each planet, if not, the error for the 2 remaining planets would accumulate over time, even if correcting Earth) And trust me, it's not easy to calculate Mars time (ok it is because NASA application already exists) but Titan Time I have only in my Excel, and that one I have to recalculate when setting the clock.

Periods for Earth: 1 s, Mars 1.027 491 251 7 s, Titan 0.998 068 437 5 s,

Obviously, Arduino math is not exact to the 10 decimal places, maximally 32 bytes which is 0.000 000 000 2 and something ... that is 2 to -32nd power.

The options for least common multiple:
Earth:Mars = 291/299, Earth:Titan = 3624/3617
Earth:Mars:Titan = integer:integer:1 054 584 (that is 291 x 3624)

so 1st option, is to generate 1 054 584 Hz (I call it golden Megahertz) which is slightly more than 15 Arduino clock cycles = to be exact 15 and 16 cycles would have to alternate with some leap cycle rule (analogous to our leap year rule) to get this frequency.

Find another, decimal frequency slightly off.

Option 1:
Earth:Mars = 812993/800000 and Titan could be 1/4 cycle off, so 800 kHz

Option 2:
Earth:Mars:Titan = integer:integer:3200000 so 3.2 MHz (5 clock cycles) and Mars, Titan, Earth are better aligned,

Option 3: 9600000 Hz frequency (5 clock cycles on 48 MHz Arduino Zero exactly, or 10 cycles on overclocked 96 MHz Arduino Due), and perfect planet alignment.

These options need to have 24 bit counter, up to 16777216 not just 16 bytes. If I don't keep the ratio exactly, the clock would drift at different speeds and to correct the clock to stop all 3 clocks at once would not be enough.

Each one would have to be corrected individually (even though Earth would have the biggest error from Arduino resonator, some residual errors from not exact ratios will accumulate over time, and once in a while, additional 2 clocks would have to be stopped and set individually)

---

Also, i would like to have something like calendar for each planet, what would the fastest and shortest way to configure it? Earth: 365.2425 days, Mars 668.592 days and Titan 673.54388 days. For Earth we have 365 plus every 4th leap but every 100th not leap but every 400th leap. Days in month are 31,28/29,31,30,31,30,31,31,30,31,30,31. For Mars we would have: 56,56,55,56,56,55,56,56,55,56,56,55/56, and every odd and every 10th leap (thats .6) but not every 100 (thats .59 )but every 500 leap (thats .592). Leap month would be 12-th month. For Titan we would have 56,56,56,56,56,57,56,56,56,56,56,56/57, and every odd and every 20th leap (thats .55) but not every 160 th leap (thats .54388). Also, that lenghth mentioned is not 1 Titan day, but 1/16th Titan day, yes Titan day is almost 16 days long. So, i would like to have something like "days in a day" = 8 days week of 24 hours of 60 minutes of 60 seconds of 0.98 above mentioned earth seconds, and AM and PM week. The 8th day would be called "Earthday and would be between Sunday and Monday". For Mars we would have 7 day weeks as on Earth, and in a similar way, Monday 1st, Tuesday 2nd, .... But for Titan we would have 16 times 1st: AM Monday 1st, AM Tuesday 1st, ... AM Sunday 1st, AM Earthday 1st, PM Monday 1st, PM Tuesday 1st, ... PM Sunday 1st, PM Earthday 1st, and then 16 times 2nd, ... again from AM Monday till PM Earthday. So we can divide terribly long 16 day day into weeks and days. do we have some reasonable function like RTC where i in/out put (year, month, day, week, weekday, hour, minute, second) when i in/out put "unix time" for Earth, Mars and Titan based on different length of seconds? We would have Unix Earth, Unix Mars and unix Titan. Obviously for Earth and Mars, the weekday and date would advance simultaneously and we dont need "week" for Earth and Mars (that would be dislabled) and for Titan there are 8 weekdays and then 2 weeks and then 1 titan day (2 weeks long) so yes 16 days day and 673.54 of them thats almost 30 years long year. the formulas among Earth Mars and Titan Unix time have to be ready yet, but how to break that unsigned long unix time for each planet into the components, and one more (week) component for Titan, an titan day is awfully long, do weekday (and week) here is time, not day, but day within a day, and week within a day.

---

Nick Gamon, i dont want to be disrespectful, this is my very first question after several years of reading these forums.

There is indeed a capability of Arduino Uno r4 generating 1/256 sec interrupt directly, as there is dedicated library for that, using its bult in RTC clock, which are already part of that Arduino.

Unfortunately, the nice round multiple for Earth, Mars, Titan would be 3.2 million Hz. As Arduino 4 is 32 bit processor 48 MHz, it does math up to 32 bits within one or two clock cycles. and 3.2 million Hz would be exactly 15 clock cycles, however that not much cycles for interrupt. But 256 Hz is plenty of time for 48 MHz 32 bit processor right? im not sure how exact are that RTC clock, need to find out as soon as ill get it. That Arduino uno R4 appeared just few days ago in the shop and its totally new and different. (32 bit, 48 MHz)

1/256 th of second is 12500 / 3200000 second. so Thank god 3.2 million is divisible by 256 without any fraction.

I am enclosing the example for Arduino r4 documentation:

https://docs.arduino.cc/tutorials/uno-r4-wifi/rtc#unix

```
#include "RTC.h"

const int LED_ON_INTERRUPT  = 22;

void setup(){
  RTC.begin();
  if (!RTC.setPeriodicCallback(periodic_cbk, Period::ONCE_EVERY_2_SEC)) {
    Serial.println("ERROR: periodic callback not set");
  }
}

void loop() {
}

void periodic_cbk() {
  static bool clb_st = false;
  if(clb_st) {
    digitalWrite(LED_ON_INTERRUPT,HIGH);
  }
  else {
    digitalWrite(LED_ON_INTERRUPT,LOW);
  }
  clb_st = !clb_st;

  Serial.println("PERIODIC INTERRUPT");
}

```

The period can be specified using the following enumerations:

```
ONCE_EVERY_2_SEC
ONCE_EVERY_1_SEC
N2_TIMES_EVERY_SEC
N4_TIMES_EVERY_SEC
N8_TIMES_EVERY_SEC
N16_TIMES_EVERY_SEC
N32_TIMES_EVERY_SEC
N64_TIMES_EVERY_SEC
N128_TIMES_EVERY_SEC
N256_TIMES_EVERY_SEC

```

---

Now, I am also strugglling with how to incorporate that calendar from Unix time, to break it into individual components for Earth, Mars and Titan. Unix time began on 01/01/1970 00:00:00, unix Mars would began on 01/01/192 00:00:00 and Titan Unix would began on 01/01/13 AM Monday 00:00:00, but i would like to have the initial years adjustable because. It will eventually run out of range after 136 earth years, 72 Mars years and some 4.6 Titan years so we could re-use it by shifting initial year, and also, i would like to have it valid at least till 2323, so, only with resolution 4 second, because 300 years has less than 2 to the 32th 4-second intervals. But that calendar is giving me a headache. I saw RTC library but i cant just change numbers to get Mars, and Titan calendar.

The reason i would like to have it, is because in some point in the future, the human colonisation of Mars will begin, and in more distant future, the human colonisation of Titan (Saturns moon) will begin (there is already a nuclear powered helicopter which will operate in Titan high density atmosphere and low gravity and very cold environment, in 2034 (the date is already approved by NASA, it will lift off in 2027, but as u can suppose the flight takes 7 years to cover one billion miles, or 1.6 billion kilometers to Saturn), and plan for nuclear powered submarine which will swim in its liquid methane seas, not sure when, but the concept already exists, its close to liquid nitrogen temperature, liquid methane has temperature of minus 180 degrees Celsius or like minus 300 degrees of Farenheit, so heating by and insulation have to be perfect) and for enery planet we do need different calendar

---

If i would have to be capable to construct PLL (phase-locked-loop) then i would have to be able to go from 32768 Hz exactly to 3.2 MHz (as exactly as the 32768 Hz crystal is exact), by 5 times multiplying it by 2.5 that is (multiply by 5 and divide by 2). Lol I could not do 5 times multiply by five because i would get 102.4 MHz (and then divide it 5 times by 2) and not even Arduino due is that fast enough to catch that interrupt. But pure TTL logic is capable to to do it (assuming it can multiply by fractions, that is 2.5 to the 5th power)

---

Hi guys, the lcd keypad shield 1602 A is compatible with which library and which arduino? how the pins have to be set? I just cant make it working

# Answer
Your question is a perfect example of an XY problem: you are asking something that has little to do with your actual problem, but is rather about your misguided idea of a solution. Counting Mars seconds or Titan seconds is an easy problem. Dividing the frequency of a 1 MHz signal by successive powers of 1.25 is a hard problem. There is little value in turning an easy problem into a hard one.

I suggest a solution inspired by Bresenham's algorithm for drawing slanted lines:

* configure a timer to deliver a periodic interrupt to your program, with a period shorter than your shortest relevant second
* compute the ratio of your favorite planet's second to the interrupt period
* approximate this ratio by a rational number *p*/*q*

In the interrupt service routine:

* increment a counter by *q*
* when the counter reaches *p*, decrement it by *p* and note that one second has elapsed.

The lazy way of getting a periodic interrupt is to simply enable the TIMER0\_COMPA interrupt. Timer 0 is already configured by the Arduino core to count full cycle every 1,024 µs. You may want to set OCR0A to something near 128 in order to prevent the overflow interrupt (used by Arduino for timing) and your interrupt from getting too close.

For the Earth, the ratio is

1 s / 1,024 µs = 1,000,000 / 1,024 = 976.5625 = 15625 / 16

For Mars and Titan, they can be approximated by 22,075/22 and 33,139/34 respectively, to within a fraction of a ppm.

Here is the interrupt service routine:

```
// Count of elapsed seconds on each planet.
volatile uint32_t earth_secs, mars_secs, titan_secs;

// Executed every 1,024 us on a timer interrupt.
ISR(TIMER0_COMPA_vect) {
    static uint16_t earth_ticks, mars_ticks, titan_ticks;
    earth_ticks += 16;
    if (earth_ticks >= 15625) {
        earth_ticks -= 15625;
        earth_secs++;
    }
    mars_ticks += 22;
    if (mars_ticks >= 22075) {
        mars_ticks -= 22075;
        mars_secs++;
    }
    titan_ticks += 34;
    if (titan_ticks >= 33139) {
        titan_ticks -= 33139;
        titan_secs++;
    }
}

```

Note that you can build better approximations of Mars and Titan seconds by using rational numbers with larger *p* and *q*, but then you would have to do 32-bit arithmetics in the ISR. You could also configure another timer to deliver an interrupt with a longer period: you would then be able to achieve better accuracy with 16-bit arithmetics, at the cost of increased jitter.

---

**Edit**: Here is a variation on this idea that uses `millis()` instead of interrupts. Of course, Nick Gammon is right: you do not need interrupts for a clock that updates its display a few times per second. It was just a bit easier to write an interrupt-based code, as the time between successive calls of the function is a known constant.

Given that you are going to use a 32-bit processor, I wrote this using 32-bit arithmetic. The ratios should be a little bit more accurate.

```
uint32_t earth_seconds, mars_seconds, titan_seconds;

void update_planet_times() {
    // Compute number of elapsed milliseconds since last update.
    static uint32_t last_update;
    uint32_t now = millis();
    uint32_t elapsed_millis = now - last_update;
    last_update = now;

    // Update Earth time. 1 Earth second = 1000 / 1 ms.
    static uint32_t earth_ticks;
    earth_ticks += elapsed_millis * 1;
    uint32_t elapsed_earth_seconds = elapsed_earth_ticks / 1000;
    earth_ticks -= elapsed_earth_seconds * 1000;
    earth_seconds += elapsed_earth_seconds;

    // Update Mars time. 1 Mars second = 763426 / 743 ms.
    static uint32_t mars_ticks;
    mars_ticks += elapsed_millis * 743;
    uint32_t elapsed_mars_seconds = elapsed_mars_ticks / 763426;
    mars_ticks -= elapsed_mars_seconds * 763426;
    mars_seconds += elapsed_mars_seconds;

    // Update Titan time. 1 Titan second = 3193819 / 3200 ms.
    static uint32_t titan_ticks;
    titan_ticks += elapsed_millis * 3200;
    uint32_t elapsed_titan_seconds = elapsed_titan_ticks / 3193819;
    titan_ticks -= elapsed_titan_seconds * 3193819;
    titan_seconds += elapsed_titan_seconds;
}

```

Note that using this technique for the Earth may seem superfluous: one may count seconds by simply computing `millis()/1000`. This, however, would fail when `millis()` rolls over in 49.7 days. The code above is immune to this rollover, and should count Earth seconds reliably for the next 136.1 years.
> 4 votes

# Answer
What you are suggesting is far too complex. Use the internal timers, say timer 0, 1 or 2 on the Atmega328P (Arduino Uno) with a prescaler of 64 (which gives you 4 µs per timer tick) and then count up to 250, giving you a period of 1 ms.

The timer can be configured to toggle an output pin, giving you this frequency as an output. If you are toggling you may want to halve what you count to (one count for the leading edge and the second count for the trailing edge). Or use PWM mode with a duty cycle of 50%.

---

From a comment to a different answer:

> I am planning to get Arduino Uno R4 which is capable to generate - fastest - 1/256 s interrupts using its in-built RTC - Clock

Not at all. The Uno timers can be configured to interrupt at practically any rate (the limit being how fast the interrupt routine can execute).

The software from the IDE configures Timer 0 to interrupt once every 1.024 ms, which is a lot more often than 1/256 s. However you can reconfigure that, or indeed the other timers, to interrupt at virtually any interval, within reason.

See my page about timers for more information.

I could easily give you code that would generate an interrupt every 1/256s or indeed 1/32768s but I don't see how those rather unusual numbers, from the point of view of the planets, would help you.

In fact, probably better from your point of view is to simply keep track of elapsed time and do your calculations from that. For example, `millis()` tells you elapsed time since startup in milliseconds and will wrap around every 49.710 days. Or `micros()` which tells you the elapsed time in microseconds, and will wrap around every 71.58 minutes.

Now, you would need to handle wrap-around in any case, so that is no big deal.

It seems to me that your calculations for the planets' positions would simply be to take the current time (eg. using `millis()`) and then apply some arithmetic for each planet to work out where it must be.

Your desire to get interrupts, and your focus on 32768 as an interrupt interval seems to me to be be an XY problem. You know what they say, "if the only tool you have is a hammer, everything looks like a nail". Well, you have more tools than a hammer here.
> 0 votes

---
Tags: oscillator-clock
---


# Question
Title: Functions delaying gesture sensor recognition
I am working on a simple little robot to cure my boredom and all it has is a 64 x 32 OLED for the eyes, and a PAJ7620 Gesture recognition sensor with a Seeeduino Xiao as the main board.

Basically, when people swipe above the head where the sensor is, the robot will show the heart eyes. There are different reactions for different actions and all this is controlled through functions. When the sensor does not detect anything, the robot is supposed to cycle through a certain void which is determined based on how much it 'likes' the person.

Right now though, it just cycles through the function and does not respond to the sensor. My code is *very* inefficient because of all the functions, but it makes it more readable and more easily editable. With all my functions, the gesture sensor takes too long to respond to the actions.

What can I do to fix this? Can someone please help or give advice on how I can improve my code?

```
    #include <Arduino.h>
    #include <U8g2lib.h>
    #include <Wire.h>
    #include <DFRobot_PAJ7620U2.h>

    int like_score = 3;//Score for how much the bot likes you: this will impact which voids are used.
    int max_like_score = 17;
    char buffer[9];

    unsigned long previousMillis = 0;
    const long interval = 1000;

    DFRobot_PAJ7620U2 paj;

    U8G2_SSD1306_64X32_1F_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE);

    // fonts https://github.com/olikraus/u8g2/wiki/fntlistall#4-pixel-height
    void setup(void) {
      u8g2.begin();
      Serial.begin(115200);
      delay(300);
      u8g2.clearBuffer();
      Serial.println("Gesture recognition system base on PAJ7620U2");
      while (paj.begin() != 0) {
        Serial.println("initial PAJ7620U2 failure! Please check if all the connections are fine, or if the wire sequence is correct?");
        delay(500);
      }
      Serial.println("PAJ7620U2 init completed, start to test the gesture recognition function");
      paj.setGestureHighRate(true);
    }

    void normalL() {       //normal forward expression
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, normal);
      u8g2.sendBuffer();
    }
    void blinkL() {        //blinks
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, blink);
      u8g2.sendBuffer();
    }
    void left() {          //looks left
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, blinkleft);
      u8g2.sendBuffer();
    }
    void right() {         //looks right
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, blinkright);
      u8g2.sendBuffer();
    }
    void angryL() {        //angry
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, angry);
      u8g2.sendBuffer();
    }
    void loveL() {         //in love
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, love);
      u8g2.sendBuffer();
    }
    void sleepL() {        //sleeping
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, sleep);
      u8g2.sendBuffer();
    }
    void susL() {          //suspicious
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, sus);
      u8g2.sendBuffer();
    }
    void stunL() {         //looks stunned
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, stun);
      u8g2.sendBuffer();
    }
    void upL() {           //Looks up
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, up);
      u8g2.sendBuffer();
    }
    void gleeL() {
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, glee);
      u8g2.sendBuffer();
    }
    void randomEx() {
      int rand = random(1, 8);
      if (rand == 1) {
        normalL();
      } else if (rand == 2) {
        left();
      } else if (rand == 3) {
        right();
      } else if (rand == 4) {
        angryL();
      } else if (rand == 5) {
        loveL();
      } else if (rand == 6) {
        susL();
      } else if (rand == 7) {
        upL();
      } else if (rand == 8) {
        gleeL();
      }
    }

    void likeRoutine() {
      normalL();
      delay(random(1000, 6500));
      blinkL();
      delay(90);
      normalL();
      delay(random(1000, 4500));
      randomEx();
      delay(random(1000, 4500));
      blinkL();
      delay(90);
      loveL();
      delay(random(2500, 4000));
      blinkL();
      delay(90);
    }
    void kindofLikeRoutine() {
      normalL();
      delay(random(1000, 7000));
      blinkL();
      delay(90);
      normalL();
      delay(random(1000, 4500));
      randomEx();
      delay(random(1000, 4500));
      blinkL();
      delay(90);
      loveL();
      delay(random(1000, 3000));
      blinkL();
      delay(90);
    }
    void dislikeRoutine() {
      normalL();
      delay(random(1000, 7000));
      blinkL();
      delay(90);
      normalL();
      delay(random(1000, 6500));
      randomEx();
      delay(random(1000, 4000));
      blinkL();
      delay(90);
      angryL();
      delay(random(1000, 3000));
      blinkL();
      delay(90);
    }
    void hateRoutine() {
      angryL();
      delay(random(1000, 5000));
      blinkL();
      delay(90);
      normalL();
      delay(random(1000, 6500));
      randomEx();
      delay(random(1000, 4000));
      blinkL();
      delay(90);
      angryL();
      delay(random(1000, 3000));
      blinkL();
      delay(90);
    }

    void loop(void) {
      DFRobot_PAJ7620U2::eGesture_t gesture = paj.getGesture();
      if (gesture != paj.eGestureNone) {
        String description = paj.gestureDescription(gesture);  //Convert gesture number into     string description
        if (gesture == 256) {                                  //wave
          gleeL();
          delay(random(1000, 4500));
        } else if (gesture == 2 && like_score < max_like_score) {  //pet
          blinkL();
          delay(90);
          loveL();
          like_score++;
          Serial.println(like_score);
          delay(random(1000, 3000));
          if (like_score == max_like_score) {
            blinkL();
            delay(90);
            loveL();
            delay(random(1000, 3000));
          }
        } else if (gesture == 16 && like_score <= max_like_score) {  //thump
          stunL();
          like_score--;
          Serial.println(like_score);
          delay(random(1000, 4000));
          angryL();
          delay(random(1000, 3000));
        } else if (gesture == 128) {
          u8g2.clearBuffer();
          u8g2.setFont(u8g2_font_t0_11_tf);  // choose a suitable font
          dtostrf(like_score, 6, 0, buffer);
          String scoreStr = String(buffer);
          u8g2.drawStr(0, 20, scoreStr.c_str());
          u8g2.sendBuffer();
          delay(random(2000, 3500));
        }
      } else {
        if (like_score >= 11) {
          likeRoutine();
        } else if (like_score > 7 && like_score < 11) {
          kindofLikeRoutine();
        } else if (like_score > 0 && like_score < 7) {
          dislikeRoutine();
        } else if (like_score < 0) {
          hateRoutine();
        }
      }
    }

```

# Answer
The code is being slowed down by the `delay()` function because it is a `blocking` function.

The delay function does not exit until delay time passes, so no other functions can run, such as sensor reading.

The simplest solution for your code may be an FSM library (finite state machine). It would look after all of the timing for you.

You could also replace the `delay()` functions with your own delay function, something like

```

void myDelay(int totalDelay) {

   for (i = 0; i < totalDelay/100; i++) {

                           // do some housekeeping here, like reading sensors

      delay(100);          // this blocks for only 1/10 of a second
   }                       // adjust the delay value if housekeeping takes a lot of time
}

```

The delay gets broken into a lot of small delays with time to do other things in between.

Another way is to check at the begining of `loop()` to see how much time has elapsed. See blinkWithoutDelay example code in the Arduino IDE.

Here is an example in a simulator that may help you.

https://wokwi.com/projects/362275278547275777
> 3 votes

---
Tags: programming, time, oled, delay, seeeduino-xiao
---


# Question
Title: Can I program ATTINY using Arduino as ISP whilst having other I2C devices connected?
I have an SMD ATTINY that I'm using for a project. Attached to it are 3 I2C devices. When programming it using an Arduino as an ISP, can I have those devices attached? Ie, do I have to program the ATTINY and then solder it on my board or can I solder it and the program (and re-program if necessary).

# Answer
Yes, the slave devices shouldn't respond unless addressed. When programming, data will obviously be on the lines however the probability of this data accidentally containing the right sequence to correctly query a slave is minimal.
> 0 votes

---
Tags: i2c, attiny85, arduinoisp
---


# Question
Title: Digispark: check if the USB host is connected
I am trying to detect if the digispark device is actually connected to a host (i.e. the USB line is "active") vs. just powered. The issue: if I send a keypress while the data line is disconnected, the code hangs perpetually in `sendKeyPress`. My theory is that it keeps looping in while waiting for USB to be ready, which makes sense.

```
    while (!usbInterruptIsReady()) {
      // Note: We wait until we can send keyPress
      //       so we know the previous keyPress was
      //       sent.
        usbPoll();
        _delay_ms(5);
    }

```

I tried to use the macro `usbInterruptIsReady()` before calling `sendKeyStroke` in the `main`, but with no success. I would expect to see a function that keeps track of this state, but apparently there is none.

Also: it doesn't seem like what I am trying to accomplish being extremely weird, so my expectation is that someone else could have stumbled upon this and figured out a reasonable workaround. I would like to avoid setting up a watchdog timer.

Code below for example hangs when the device is powered but not connected to a PC. Thanks

Background: https://hackaday.io/project/191762-automatic-workstation-locker

```
#include "DigiKeyboard.h"
#include "Arduino.h"

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  DigiKeyboard.update();

  DigiKeyboard.sendKeyStroke(0);
}

void loop() {
  static uint8_t bit = 0;
  bit = 1 - bit;
  digitalWrite(LED_BUILTIN, bit);
  DigiKeyboard.update();
  DigiKeyboard.sendKeyStroke(KEY_Q);
  delay(2000);
}

```

# Answer
The Digispark does not have a proper hardware USB implementation. It is possible that you simply can't do what you are attempting to do. A search I did indicated you are not the only person attempting to do this.

You may want to switch to one of the Arduinos that have a hardware USB interface like the Leonardo or Micro.

I should point out that the Digispark is not an Arduino, and it has its own forum where you may possibly get an answer from their own community.
> 0 votes

---
Tags: digispark
---


# Question
Title: NodeMCU code that both display OLED and control WS2812 LED Ring
I'm trying to make a project using NodeMCU that show pictures in small OLED screen and also controlling WS2812 LED Ring.

I manage to do each of them separately but I'm not sure how to mix them together. The problem lies in the fact that most code examples for both the screen and the LED use sleep and that will of course only work for one of the other but not both.

This is the first project I've looked at to display bitmaps with SSD1306 screen and nodemcu.

This is the second project I've looked at to control NeoPixel WS2812 ring.

The main project was that both of them use `delay` as a way to wait for some amount of time to "progress". But, I couldn't just wait because then it will mess up both the screen and the NeoPixel.

One more thing is I have to also take reading input into account. I still not 100% sure about the input but it will probably be potentiometer and maybe a button.

I think I have found the solution which is to break the large "tasks" of reading input, controlling screen and controlling leds into smaller parts and do the waiting in a cooperative way.

I've found this instructable which both explain how to do it and also provide code example.

I'll be glad to know if people how other ways to implement this.

# Answer
You need to stop using `delay` and instead keep track of elapsed time. One of the comments under your question suggests looking at the BlinkWithoutDelay example, which is part of the Arduino IDE.

The jocular comment "how do you drink some water while eating dinner" suggests the solution. You do one thing for a moment, and then do another thing. When eating dinner you don't wait for the entire meal to be consumed before you can drink a glass of water.

Here's some example code that blinks two LEDs at different rates:

```
// Which pins are connected to which LED
const byte greenLED = 12;
const byte redLED = 13;

// Time periods of blinks in milliseconds (1000 to a second).
const unsigned long greenLEDinterval = 500;
const unsigned long redLEDinterval = 1000;

// Variable holding the timer value so far. One for each "Timer"
unsigned long greenLEDtimer;
unsigned long redLEDtimer;

void setup ()
  {
  pinMode (greenLED, OUTPUT);
  pinMode (redLED, OUTPUT);
  greenLEDtimer = millis ();
  redLEDtimer = millis ();
  }  // end of setup

void toggleGreenLED ()
  {
   if (digitalRead (greenLED) == LOW)
      digitalWrite (greenLED, HIGH);
   else
      digitalWrite (greenLED, LOW);

  // remember when we toggled it
  greenLEDtimer = millis ();
  }  // end of toggleGreenLED

void toggleRedLED ()
  {
   if (digitalRead (redLED) == LOW)
      digitalWrite (redLED, HIGH);
   else
      digitalWrite (redLED, LOW);

  // remember when we toggled it
  redLEDtimer = millis ();
  }  // end of toggleRedLED

void loop ()
  {

  // Handling the blink of one LED.
  if ( (millis () - greenLEDtimer) >= greenLEDinterval)
     toggleGreenLED ();

  // The other LED is controlled the same way. Repeat for more LEDs
  if ( (millis () - redLEDtimer) >= redLEDinterval)
    toggleRedLED ();

/* Other code that needs to execute goes here.
   It will be called many thousand times per second because the above code
   does not wait for the LED blink interval to finish. */

}  // end of loop

```
> 1 votes

---
Tags: arduino-ide, nodemcu, ws2812, oled
---


# Question
Title: Greyed out port for Raspberry pico in Arduino IDE - Ubuntu 20.04
I'm trying to figure out how to program my new Raspberry Pico with Arduino, but don't see a port to select so I can't upload the blink sketch.

Here's what I've done:

* The Pico is working, I can program it with micro Python.
* Just in case, I brought the Pico back to factory settings with the nuke file.
* Installed support for the Pico in Arduino IDE. Version 2.1.0 of Arduino MBed RP2040 is installed.
* While keeping BOOTSEL pressed, I plug in the Pico to my laptop (Ubuntu 20.04)
* The board selected is "Raspberry Pi Pico"
* But the option to select a port is greyed out :-(

It seems that I am omitting some step during the installation, but can't figure out what it is.

Any ideas?

Thanks!

# Answer
I've come across this and this is how I worked around it (on Windows, but I suspect the problem and solution is the same).

A brand new Pico or one not programmed by the Arduino IDE does not have a serial port, which is why you can't see one. Arduino sketches are compiled with a serial port automatically, so once a serial port exists, it can be used for future uploads.

The Arduino solution is to use the 'Export compiled binary' option (for any sketch) and upload the UF2 file (which should be generated into the sketch folder) using virtual USB drive interface. When the sketch starts, the serial port will be available and can be used for future sketch uploads.

Another solution is to use an alternative Pico core. This one does not need the port selected, but will find and upload to a Pico in bootloader mode via the virtual USB drive.
> 5 votes

# Answer
Had this issue and tried everything that was described on forums.

The thing that worked for me was: I held the bootsel button until it opened pico folder, then port button activated in the IDE and I chose UF2 port and then after upload, pico showed at COM7
> 0 votes

---
Tags: arduino-ide, raspberrypi
---


title: LCD I2C connection problems

text:
# Question
Title: LCD I2C connection problems
I am hoping there is a simple fix to this problem.

I am playing around with a 16x2 lcd with a I2C connector attached. I wired it up to an elegoo uno R3.

I started with some code I've used before and ended up with one row of the LCD fully lit and the other dark.

After a ton of trouble shooting, I can not get the LCD to show anything but one lit and one dark row.

In this image:

Power: 5V, 1.5A

| Pin | LCD | Uno |
| --- | --- | --- |
| SCL | SCL | SCL |
| SCA | SDA | SDA |
| + | VCC | 5V |
| gnd | gnd | gnd |

I've also tried:

* putting the SDA to A4 and the SCL to A5
* Using different power supplies
* Powering from the USB connector

And I've tried several of the libraries available

They are all variations of the following from the Adafruit\_LiquidCrystal library:

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

// Set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup()
{
    // initialize the LCD
    lcd.begin();

    // Turn on the blacklight and print a message.
    lcd.backlight();
    lcd.print("Hello, world!");
}

void loop()
{
    // Do nothing here...
}

```

No matter what I do the display does not change.

# Answer
> 4 votes
Some common problems with LCD displays which incorporate an I2C backpack include:

1. Not using the correct I2C address for the I2C backpack. Use an I2C scanner to discover the correct address.
2. Mixing voltages without proper level shifting, say using a 5v display with a 3.3v MCU
3. Failing to adjust the contrast potentiometer
4. Some I2C backpacks may use a non-standard pin allocation which may be corrected by specifying a pin mapping in the constructor to the display library. Fortunately, this is rare.
5. Using code samples intended for a different variant of the library supporting the display. Always use a basic test sketch which is packaged with the chosen library to verify the performance of the display.

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


title: Arduino Nano uploading problems

text:
# Question
Title: Arduino Nano uploading problems
I am having trouble uploading code to my Arduino Nano. It has been very trusty in the past, but I am getting this new error when uploading any code to it: `avrdude: ser_open(): can't set com-state for "\\.\COM15"`

This happened a while ago on my Windows 11 Laptop, and I was unable to resolve it, and now it has just started on my Windows 10 desktop.

I tried disabling and re-enabling the CH340 in device manager, restarted my computer, and uninstalled the CH340. After uninstalling it, it has dissapeared and does not even show up in Device Manager at all.

If anybody could provide some help explaining how to make it show up in Device Manager again, and also make it uploadable, I would greatly appreciate it!

Thank you in advance

# Answer
> 1 votes
Apparently there was an update in ch340 drivers early in 2023 and it broke something for counterfeit ch340. Solution is using older version of the driver (and possibly disabling automatic updates for the drivers in the Windows).

Issue description and solution found on github:

> Rollback to an older driver manually :
>
> Unfortunately since the incompatible driver is delivered through windows update it is harder to keep an older driver installed :
>
> Recommended : Block windows drivers update so the newest driver won't get installed automatically: https://www.makeuseof.com/windows-stop-automatic-driver-updates (note: while this is required to be able to install and keep the older ch340g driver but this will affect any of your future devices)
>
> Reinstall an older driver here : 01/30/2019, 3.5.2019.1 CH341SER driver

---
Tags: arduino-nano, uploading, avrdude, ch340
---


# Question
Title: Intercepting Keyboard Data on a Micro Controller
Recently I have purchased male and female USB-C breakout boards. I intend to connect the male breakout to a keyboard and the female end to my computer using a USB-C cable and wire the breakouts together using a breadboard. I was wondering if it is possible to read the keystrokes being sent across the D- and D+ lines with a micro-controller.

Here is an image of how I currently have the breakout boards setup

# Answer
> 1 votes
It would be far far easier to interface an Arduino to an old PS2 keyboard.

USB is complex. You would have to understand USB protocol, then understand the HID (Human Interface Device) protocol inside of the USB protocol. As HID can interface a number of devices like mice and keyboards, you might have to then understand the keyboard portion of the HID protocol.

As a point of reference, commercial USB analyzers cost hundreds of dollars. This USB analyzer cost about $500.

As an alternative, have you considered an all software USB monitor? These normally reside on the same computer as the USB Device is attached to. Wireshark should be able to do this.

Also, assuming that is a Pro Micro used on the keyboard, consider adding code to its Atmel processor to send out keyboard activity on an unused pin. This approach might proved much easier then monitoring the keyboard after its data has been incorporated into the USB protocol.

---
Tags: usb, keyboard
---