# Question
Title: How much readable text can fit inside an ATTINY85? Feasibility of scrolling a booklet on a 0.91-inch OLED display
I'm a total beginner, so I've been talking with Chatgpt regarding the capabilities of the **Attiny85** microcontroller. But the AI would hallucinate a lot and give only partially right answers (because it relies on patterns and knowledge from its training data or something). So I came here to ask for some guidance and insights on the following questions:

1. How much readable text can the Attiny85 accommodate considering variables such as the programs, libraries, and fonts?
2. Is it possible to create a mini text reader using an Attiny85 and a 0.91-inch OLED display, where the text can be scrolled and read like a booklet?

I understand that the Attiny85 has 8kb of flash memory, but I'm unsure about the actual capacity for storing and displaying text, especially considering the potential impact of the compression of the code.

Any advice, experiences, or suggestions on how to optimize the usage of the Attiny85 and the OLED display for this purpose would be greatly appreciated.

Note: Feel free to correct any misconceptions or assumptions I may have made in my questions due to my limited knowledge in this field.

# Answer
I will take a SWAG, the approach I would use would be to add external memory such as I2C FRAM. It is not expensive and will work just fine with the I2C bus. I use the 32K x 8 devices. You could connect 8 of them. FRAM can be acquired in SPI as well. I have assumed you are using the I2C for the display so no additional pins on the processor will be needed.
> 1 votes

# Answer
The AtTiny85 has 8KB of program memory, which you could store strings in. The more data you store, the less room you have for program code and vice-versa.

For only slightly more money you could use an Atmega328P which has 32KB of program memory, giving you somewhat more scope for storing data.

For some kind of text reader you might want to consider an external disk (like, a micro-SD card) which can be easily attached with a modest amount of extra hardware. The hardware might be a couple of voltage-level converters, if you are going to run the processor at 5V rather than 3.3V.

The code to interface to the SD card might be too large to fit into 8KB of memory (I'm not sure about that) but certainly would fit into 32KB.

You also need the code to interface with the OLED — I'm not sure how much program space that would take up.

You might do it with the AtTiny85, with no external disk, but you would probably only get a couple of K of text, once you had your code and your OLED interface. You could compress the text, but then you need code to decompress it, which might outweigh the advantage of compressing it.

For some sort of "booklet" I think the external disk is the most practical solution. This is what one looks like, with its voltage-level converter, hooked up to my Uno:
> 0 votes

---
Tags: arduino-uno, programming, c++, i2c, attiny85
---


# Question
Title: Read one byte from file and convert to decimal
Ok, I'm fairly new to Arduino and I'm trying to read bytes from a file in an SD card and convert to integer values (0-255).

I have a file, with 1 byte on it (128 int value, created in Python, can provide the code if necessary) and the hex dump (binary mode) is:

```
xxd -b single_byte.dat
00000000: 10000000

```

So far so good, right? So I was expecting to read this byte from the file (SD card) and then convert back to 128 value. This is my Arduino code:

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

// set up variables using the SD utility library functions:
Sd2Card card;
SdVolume volume;
SdFile root;
const int chipSelect = 4;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ;
  }

  delay(100);
  Serial.print("\nInitializing SD card...");

  if (!card.init(SPI_HALF_SPEED, chipSelect)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card inserted?");
    Serial.println("* is your wiring correct?");
    Serial.println("* did you change the chipSelect pin to match your shield or module?");
    while (1);
  } else {
    Serial.println("Wiring is correct and a card is present.");
  }

  // print the type of card
  Serial.println();
  Serial.print("Card type:         ");
  switch (card.type()) {
    case SD_CARD_TYPE_SD1:
      Serial.println("SD1");
      break;
    case SD_CARD_TYPE_SD2:
      Serial.println("SD2");
      break;
    case SD_CARD_TYPE_SDHC:
      Serial.println("SDHC");
      break;
    default:
      Serial.println("Unknown");
  }

  // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
  if (!volume.init(card)) {
    while (1);
  }

  File file;
  byte one_byte;
  int dec_value;

  file = SD.open("single_byte.dat", FILE_READ);
  one_byte = file.read();
  file.close();

  dec_value = int(one_byte);

  Serial.println(dec_value, DEC);

}

void loop(void) {
}

```

I was expecting the output to be 128.

However I get:

What am I missing? (yes, I tried generating the .dat file with big-endian encoding, same result)

# Answer
> 5 votes
Ok, I got it working now, here's what was happening:

Turns out the file wasn't being opened. Why? seems like there's a limitation on the filename length, I noticed this after adding the lines:

```
root.openRoot(volume);
// list all files in the card with date and size
root.ls(LS_R | LS_DATE | LS_SIZE)

```

And sure enough my file was not detected as **single\_byte.dat** but it was something like: **single\_~.dat** so I renamed the file to **test.dat** and tada! code now works like a charm.

I guess I overlooked this restriction on the documentation, so keep this in mind when you use an SD card.

Also, make sure to check if you are really opening your file because no exception will be thrown if you reference an uninitialized file pointer I guess.

Just make sure to have:

```
file = SD.open(filename, FILE_READ);
if(file){
    // Do things here.
}
else{
    Serial.println("You're out of luck: Can't open file");
}

```

Ok, there goes my Sunday. Thanks all for reading!!!

# Answer
> 1 votes
Consider adding a call to SD.begin() as is done in the example found on this arduino.cc web page.

Here's the section of the example code where SD.begin() is used:

```
  Serial.print("Initializing SD card...");

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    while (1);
  }

```

---
Tags: sd-card, data-type
---


# Question
Title: ST7920 and u8g2 only using some of a 128x64 display
I am trying to use the *u8g2* library and an Arduino Mega to control an LCD display. Adapting `HelloWorld` from the examples included in the library to use the SPI ports of the Mega (50-52), I have the code below.

This gives a bit of a disappointing greeting as in the picture below. It seems that the Arduino is not accessing all the pixels, and only able to change the states of three blocks (the top one with "Hello V", and the two darker regions at the bottom).

The display is a `128X64ZW-10` salvaged from a 3D printer which was working when connected to the printer's motherboard. Pin-out deduced by some kind folk here and here (translation). I briefly saw random Pinyin characters flash across the whole display while I was switching wires. These two facts, and the fact that the regions of pixels that are working are not arranged at random, makes me suspect it is a wiring or coding issue, and that the pixels are not dead.

Here is the code:

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

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

int LCD_CLK_PIN = 52; //Clock (white)
int LCD_RW_PIN = 50; //Read-Write (blue)
int LCD_RS_PIN = 51;  //Register Select (green)
U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, LCD_CLK_PIN, LCD_RW_PIN, LCD_RS_PIN,U8X8_PIN_NONE);

void setup(void) {

  /* U8g2 Project: SSD1306 Test Board */
  //pinMode(10, OUTPUT);
  //pinMode(9, OUTPUT);
  //digitalWrite(10, 0);
  //digitalWrite(9, 0);

  /* U8g2 Project: T6963 Test Board */
  //pinMode(18, OUTPUT);
  //digitalWrite(18, 1);

  /* U8g2 Project: KS0108 Test Board */
  //pinMode(16, OUTPUT);
  //digitalWrite(16, 0);

  /* U8g2 Project: LC7981 Test Board, connect RW to GND */
  //pinMode(17, OUTPUT);
  //digitalWrite(17, 0);

  /* U8g2 Project: Pax Instruments Shield: Enable Backlight */
  //pinMode(6, OUTPUT);
  //digitalWrite(6, 0);

  u8g2.begin();
}

void loop(void) {
  u8g2.firstPage();
  do {
    u8g2.setFont(u8g2_font_ncenB10_tr);
    u8g2.drawStr(1,18,"Hello World!");
  } while ( u8g2.nextPage() );
  //delay(1000);
}

```

I have spent a couple of days on this, but no luck. Any ideas?

# Answer
> 1 votes
Many thanks for your photos.

Test carried out with the motherboard of an Ender3 V1.1.3

PIN configuration: U8g2lib library

```
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

int LCD_CLK_PIN = 30; //Clock (white)
int LCD_RW_PIN = 17; //Read-Write (blue)
int LCD_RS_PIN = 28;  //Register Select (green)
U8G2_ST7920_128X64_F_SW_SPI u8g2(U8G2_R0, LCD_CLK_PIN, LCD_RW_PIN, LCD_RS_PIN,U8X8_PIN_NONE);

```

configuration PIN: library U8glib

```
#include "U8glib.h"
U8GLIB_ST7920_128X64_1X u8g(30, 17, 28);  // SPI Com: SCK = en = 18, MOSI = rw = 16, CS = di = 17

```

Your program is working properly.

---
Tags: arduino-mega, lcd, u8glib, st7920
---


# Question
Title: Make a code loop 100 times with a text on Serial Monitor
Ok, this is my code:

```
int rosso = 13;
int verde = 12;
int blu = 11;
int count = 0;
String command_on, command_off;
String s;
String enough = "stop";

void setup(){
  pinMode(rosso, OUTPUT);
  pinMode(verde, OUTPUT);
  pinMode(blu, OUTPUT);
  Serial.begin(9600);
  command_on = String("on");
  command_off = String("off");
}

void redToBlue(){
  if(count < 100) {
  rgb(0,255,0);
  delay(100);
  rgb(0,0,0);
  delay(100);
  rgb(255,0,0);
  delay(100);
  rgb(0,0,0);
  count = count+1;
  }
}

void switchOff(){
  rgb(0,0,0);
  delay(100);
}

boolean wait_command(){
  if(s == command_on){
    redToBlue();
  }
  if(s == command_off){
  switchOff();
  }
}

void accendi(){
  if(s == command_on){
  redToBlue();
  }

  if(s == command_off){
  switchOff();
  }
}

void rgb(int r, int g, int b){
  analogWrite(rosso, r);
  analogWrite(blu, b);
  analogWrite(verde, g);
}

void loop(){
 s = Serial.readString();
 Serial.println("What I have to do? ");
 wait_command();
}

```

When I open the Serial Monitor and type "on" there, the redToblue() function must loop 100 times. But in my case loops only one time then it stops. I think I have to change something inside loop() function and on redToBlue()...

# Answer
> 1 votes
You `loop()` function is the one that will be called when the program runs and it will keep looping around until you stop it. So at the moment you have `loop()` doing the following:

1. Reading a string from the serial connection
2. Displaying a message to the serial connection
3. Parsing the string that was read and acting upon it.

So when your code runs you see it print the message and maybe do something with the light and then it stops/freezes. Its not really frozen, its waiting for you to enter an answer.

So if you really want it to ask what to do and then then loop 100 times you need to do this:

1. Display the message.
2. Read the data.
3. Call `wait_command()` (after you have modified it)

void redToBlue(){ for (int count = 0; count \< 100; ++count) { rgb(0,255,0); delay(100); rgb(0,0,0); delay(100); rgb(255,0,0); delay(100); rgb(0,0,0);
} } ***// Sorry I can't get the code to format.***

I think you could also refactor the function to loop over an array of 4 rgb values. I don't now if that would be better for the processor, it would look nicer :)

# Answer
> 0 votes
I'm not sure exactly what you want, but if you expect after a single command `on` to have it looped 100 times, you need to call the `redToBlue` function in every loop (within `wait_command`, that checks for a boolean if the `on` command has been requested, and when so, call the `redToBlue` function. When the `off` command is set, you reset the boolean.

Also `wait_command` is not a good name, as it does not wait for a command, but processes it.

---
Tags: led, loop
---


# Question
Title: HardwareSerial and SoftwareSerial not compatible
The HardwareSerial requires to run an interrupt to store received bytes in the buffer. Look at this file from the Arduino Core. If I am now constantly receiving and writing on the Software Serial, the data from the HardwareSerial cannot be buffered, since external interrupts are higher priority.

In my application, I need to constantly listen to the SoftwareSerial and respond immediately to incoming data (actually inside the receive interrupt of the SoftwareSerial, so its modified), so the SoftwareSerial has higher priority. But when I do this, I lose data on the HardwareSerial.

Is there any way to circumvent this limitation, without disabling any interrupts or getting a chip with more UART ports?

EDIT: the actual interrupt vector is here

EDIT2: This is question is not answered by the answers in my previous question. It is clearly a fact that HardwareSerial needs its receive interrupt to store data in a buffer. My question now is how I can still use the SoftwareSerial while it is constantly receiving.

# Answer
> 1 votes
If you are sending something in SoftwareSerial ISR handler that means ISRs are disabled and you are blocking other ISRs being called (if needed).

If you're using some crazy slow baudrate like 9600 then it means over 1 millisecond per character sent and during that time you might be missing other interrupts calls (millis, HW serials). If there is only one character, it's not problem, it'll be handled after interrupts are enabled again, but if there will be second or more character, previous are lost, as the've never been readed out from the UDR register (that should set flag for buffer overrun or how it's called).

If your Hw serial has some nice speed like 115200, you can lose up to 12 characters during sending single characted on software serial with speed 9600

The cli() in software serial library but as you wrote it's called from ISR handler and the ISRs are disabled anyway already during whole ISR handler

---
Tags: serial, softwareserial, serial-data
---


# Question
Title: Inconsistent results when reading input looking for spike patterns
I'm writing a library that will interface with a control unit on a refrigerator compressor pump (QDZH35G). One of the features of the control unit is that it can detect what problems it's encountering and report them via a flashing LED. Operational errors will cause the LED to flash a number of times. The number of flashes depends on what kind of operational error was recorded. Each flash will last 1/4 of a second. After the actual number of flashes, there will be a delay with no flashes, so that the sequence for each error recording is repeated every 4 seconds.

My goal (as it relates to this post) is to monitor the signal from the diagnostic lead and report what error the control unit has detected. I used my oscilloscope to monitor the diagnostic port, here are some pictures of that (fault codes 1 and 4):

(more photos here)

So the signal looked simple and clean enough. But just to be sure, I wanted to make sure Arduino was seeing it as my Oscilloscope was. I hooked the diagnostic port up to my Arduino digital port 8 and analog pin A0 (I wanted to monitor both to decide what would be the best to use for this) and uploaded the following sketch:

```
#define DIGITAL_DIAGNOSTIC_PIN 8
#define ANALOG_DIAGNOSTIC_PIN A0

void setup() {
  Serial.begin(9600);
  pinMode(DIGITAL_DIAGNOSTIC_PIN, INPUT);

  Serial.println("millis,analogRead,digitalRead");
}

void loop() {
  Serial.print(millis());
  Serial.print(",");
  int currentAnalogValue = analogRead(ANALOG_DIAGNOSTIC_PIN);
  int currentDigitalValue = digitalRead(DIGITAL_DIAGNOSTIC_PIN);

  Serial.print(currentAnalogValue);
  Serial.print(",");
  // Bump binary 1 to int 1023, to make it easier to see in the logs
  Serial.print(currentDigitalValue == 0 ? 0 : 1023);

  Serial.println();
}

```

And oddly enough, the signal Arduino was giving back seemed to be all over the place for both the digital and analog pins. While there was some pattern visible it's a pretty big mess.

Then I used `CoolTerm` to monitor and export the serial data into a CSV file which I then imported into a Google Docs spreadsheet (here) to create some graphs. I captured 10+ seconds in each of the following scenarios:

1. No fault/control (zero blinks)
2. Fault #1 (1 blink then 4-second pause)
3. Fault #3 (3x 0.25 second blinks separated by 0.25 seconds, then 4-second pause)

Here are the screenshots of the graphs (also in the Google spreadsheet doc and imgur gallery):

***Finally* \- The question..** Why is the data seen by Arduino seem considerably less stable than that seen by my oscilloscope? I know that when reading a signal from some sensors (pressure transducer, thermocouple, etc) you get much more accurate and consistent results by averaging the last *n* readings, but the diagnostic voltage port isn't really a "sensor", it's just a voltage reading.

Additionally, it's reading from a pump powered by a DC desktop power unit, which has very stable voltages (I only say this because I know the voltage affects the level of the peaks from the diagnostic port).

# Answer
Where to start? Your O'scope photo shows about 3 vertical divisions when the fault line is 'high'. The labelling at the bottom shows '5.00V', which I'm going to assume means '5V per vertical division'. This would mean your 'high' voltage is about 15V, **much** too high for the 5V max input either analog or digital input on the Mega.

So, you need something like a 3:1 voltage divider just to start with. The 'bottom' resistor on the divider will set the output impedance driving your analog (and digital) inputs, so this needs to be reasonably low (10K or so).

Before connecting the voltage divider to the Mega, look at the voltage divider output with your O'scope to verify the 'high' voltages are \<= 5V. Then, and only then, connect the voltage divider output to the Mega **with the O'scope still connected**. If you see a big drop in the 'high' voltage, it means the Mega input impedance is loading down the voltage divider output, which means the voltage divider resistor values are too high - choose lower values (same ratio of course).

The specs for the Arduino Mega show a top speed of about 10,000 readings per sec, so your loop speed should be OK as long as adjacent millisec printouts are different.

I suspect you will find that the Mega analog input is loading down the signal.
> 1 votes

---
Tags: analogread, voltage-level, serial-data, digital, datalogging
---


# Question
Title: SoftwareSerial and HardwareSerial lost data
I need two Serial ports. One port is some sort of modified Software Serial, where I have to be listening constantly and send responses immediately if the port requires it. There is no XY problem hidden here, promise.

On the other hand I have a device on the hardware serial.

If I'm listening on the Software Serial, sometimes I lose data on the hardware serial. How can this be? Isn't the Hardware Serial "hardware", meaning independent of the CPU?

# Answer
Software Serial turns off interrupts. Depending on the baud rate, they may be off for so long that the interrupt generated by the hardware serial is not serviced in time. Depending on the chip, the hardware serial may only have a buffer of a couple of bytes. Turn off interrupts long enough and one will be lost.

The external interrupts are higher priority than the UART interrupts, which won't help. I am referring to the Uno here.

**It would help** in future if you provide code to reproduce the situation, and also state what Arduino you are using. The lack of information about that in the question would be why you were downvoted.
> 1 votes

---
Tags: serial, softwareserial, serial-data
---


title: Quadcopter oscillation using PID

text:
# Question
Title: Quadcopter oscillation using PID
I am building an Arduino based flight controller for a quadcopter and have got it flying but it is not performing how I want it to. The drone is flying but when I release the sticks the drone does not stay perfectly still. There is some random and small oscillations that occur when it is just hovering.

Right now I am using a single PID controller for each axis though functions like this.

```
dt=0.005;
error = *in - *set;

P = (error * kp);
I = I + (error * ki)*dt;
D_M = ((*in - in1)*kd)/dt;
D_E = ((error - error1)*kd)/dt;
D=D_M*(1-jerk) + D_E*(jerk);

I = constrain(I, LOWER_BOUND*0.75, UPPER_BOUND*0.75);
in1 = *in;
error1 = error;
pid = P + I + D;

pid = constrain(pid, LOWER_BOUND, UPPER_BOUND);
*out = pid;

```

The error is the Euler angle and the setpoint is the angle I want it to go to.

I then output the PID controller values to the motors using the Arudino Servo library.

```
  motor1 = throttle;
  motor2 = throttle;
  motor3 = throttle;
  motor4 = throttle;

  motor1 += rollOUT;
  motor2 += rollOUT;
  motor3 -= rollOUT;
  motor4 -= rollOUT;

  motor1 -= pitchOUT;
  motor2 += pitchOUT;
  motor3 -= pitchOUT;
  motor4 += pitchOUT;

  motor1 += yawOUT;
  motor2 -= yawOUT;
  motor3 -= yawOUT;
  motor4 += yawOUT;

```

Is there something I am missing about quadcopter PID controllers? Thank you for the help!

# Answer
I'd suggest setting Kd to zero, Kp to a minimal value and letting the integral alone function as the controller. Any response to an error might be slow but the integrator alone will control a process with zero error. After observing the response of the integral for a period of time, hopefully without the problem you referenced, gradually introduce proportional control and watch for the periodic instability. If increasing the proportional gain results in oscillation, reduce the proportional back to a stable value and gradually introduce more derivative gain. I have worked with PID throughout my career and the instability you described sounds like something I'd expect to see originating from the derivative control action. No sensor is perfectly noise free and even if the noise is low amplitude, the rate of change may still be fairly large which will result in a very obvious periodic instability in the flight of your drone.

If this is the case, finding the source of the induced noise may not be easy. Perhaps reducing the derivative gain and using mostly proportional and integral control will effectively filter and attenuate the instability you're noticing. Good luck.
> 2 votes

---
Tags: pid, drone
---


# Question
Title: Connecting pressure sensor to Arduino to collect pressure and time data
I'm trying to build a pressure data logger using an Arduino and Mindman MP47P-03-F1 (https://www.mindman.com.tw/proimages/pdf/E\_MP47\_S.pdf) pressure sensor, the sensor is connected to an outer 12-24 VDC power source. I've connected the analog wire to the the Arduino's A0 and added another wire from the GND to the sensor. I get a stable voltage (~1V) reading but the pressure is wrong and it doesn't respond to pressure changes. Can someone tell me what I'm doing wrong? this is the sample code:

```
const int analogPin = A0;
const float slope = -0.1;
const float intercept = 0.6;
const unsigned long startTime = millis();

void setup() {
  Serial.begin(9600);
  Serial.println("Time (s)\t\tPressure (MPa)");
}

void loop() {
  unsigned long elapsedTime = millis() - startTime;
  int sensorValue = analogRead(analogPin);
  float voltage = sensorValue * (5.0 / 1023.0);
  float pressure = slope * (voltage - intercept);

  Serial.println(sensorValue);
  Serial.print(elapsedTime / 1000.0);
  Serial.print("\t\t");
  Serial.println(pressure);

  delay(1000);
}

```

edit: i've changed the code to as suggested by some on the arduino forum:

```
const int sensorPin = A0;
const int offset = 201; // zero pressure adjust
const int fullScale = 1023; // max pressure adjust
float sensorType = 1000.0; // kPa
float pressure; // final pressure
const unsigned long startTime = millis();

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

void loop() {
  unsigned long elapsedTime = millis() - startTime;
  pressure = (analogRead(sensorPin) - offset) * sensorType / (fullScale - offset);

  Serial.print(analogRead(sensorPin));
  Serial.print("\t\t");
  Serial.print(elapsedTime / 1000.0);
  Serial.print("\t\t");
  Serial.println(pressure, 4);
  delay(1000);
}

```

the pressure is 0 but i keep getting jumps in the readings of the pressure when no pressure is applied. here is the picture of the wiring.

# Answer
> 1 votes
As jsotola mentions in the comments, you should definitely verify that the pressure sensor works with a multimeter first, preferably on a bench that has a variable power supply from which you can power your sensor. Make sure that you can measure the pressure you are putting into the sensor by some other means; a simple pressure gauge could work.

Then, you'll have to correct your equation - it is flipped, since the graphs show the pressure as an input and an output as a voltage, but when you're converting a voltage to a pressure, the process is flipped, so we calculate the slope as follows: take the pressure range (output) and divide it by the voltage range (input) -\> 1.1 MPA / 4.4 V = 0.25 V\_in. Now, we know that at 0.6V, the pressure output is -0.1 MPA, so we set up a linear equation of the form that you did -\> y = mx + b and plug in the values: -0.1 MPA = 0.25 MPA/V * (0.6V) + b. If you solve for b, you'll get -0.25.

Therefore, pressure = 0.25X - 0.25 should be the equation that you check the pressure you're putting into the sensor against the voltage that you are measuring.

If you discover that with this equation you're measuring the right pressure, but once you re-implement your Arduino program you still have no luck, I'd check that the grounds are wired together correctly - it's crucial to have all of the involved grounds at the same 'level'. As a bonus, depending on the Arduino, you could utilize the chip's differential ADC channels, but as far I know, you'd have to write directly to registers to do that.

---
Tags: arduino-uno, sensors, datalogging, pressure
---


# Question
Title: ESP8266 seems to be killing a while loop
When i was testing out a program I found a strange behavior of esp8266

It seems to get out of a while loop even when there's no option of getting out on code

I don't know if these are related but here's the code (the program is just two different visual patterns of leds toggled by a button)

```
#define led1 D0
#define led2 D1
#define led3 D2
#define led4 D3
#define button D7

unsigned long pressedButton;
bool change = 0;
unsigned long previousTime;
unsigned int difference;

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(button, INPUT_PULLUP);
}

void loop(){
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);
  digitalWrite(led3, LOW);         //when the while loop change, this should delete interference
  digitalWrite(led4, LOW);
  previousTime = millis();

  while (!change){                                      //default visual pattern of leds
    difference = millis()-previousTime;

    if (!digitalRead(led1) && difference>=200){
      digitalWrite(led1, HIGH);
    }
    if (!digitalRead(led2) && difference>=400){
      digitalWrite(led2, HIGH);
    }
    if (!digitalRead(led3) && difference>=600){
      digitalWrite(led3, HIGH);
    }
    if (!digitalRead(led4) && difference>=800){         //after here, all the leds should be HIGH
      digitalWrite(led4, HIGH);
    }
    if (digitalRead(led4) && difference>=1000){
      digitalWrite(led4, LOW);
    }
    if (digitalRead(led3) && difference>=1200){
      digitalWrite(led3, LOW);
    }
    if (digitalRead(led2) && difference>=1400){
      digitalWrite(led2, LOW);
    }
    if (digitalRead(led1) && difference>=1600){        //after here, all the leds should be LOW
      digitalWrite(led1, LOW);
      previousTime = millis();
    }

    if (!digitalRead(button) && millis()-pressedButton>200){       //check if button was pressed to break while loop
      pressedButton = millis();
      break;
    }
  }

  while (change){                                         //alternative of visual pattern of leds
    difference = millis()-previousTime;

    if (!digitalRead(led1) && difference>=200){
      digitalWrite(led1, HIGH);
      digitalWrite(led4, HIGH);
      digitalWrite(led2, LOW);
      digitalWrite(led3, LOW);
    }
    if (digitalRead(led1) && difference>=400){
      digitalWrite(led1, LOW);
      digitalWrite(led4, LOW);
      digitalWrite(led2, HIGH);
      digitalWrite(led3, HIGH);
      previousTime = millis();
    }

    //if (!digitalRead(button) && millis()-pressedButton>=200){     //check if button was pressed to break while loop
    //  pressedButton = millis();
    //  break;
    //}
  }

  change = !change;         //after a break in one of the while loops, this will make the program go to the other while loop
 }

```

Is there something wrong with the code? Here is a link of a video of the behavior for more details https://drive.google.com/file/d/1822MHNGQn-A2-HGHhRXz\_8xydz-wM4Ha/view?usp=sharing

# Answer
You can't trap an ESP in a while loop like that. There are things it needs to get back to main and do between loops. Instead, let the loop function be your loop. Make the while statements if statements and where you have break, that's where you change the change variable. Put the code at the top in an if statement that checks to see if change has changed.

```
#define led1 D0
#define led2 D1
#define led3 D2
#define led4 D3
#define button D7

unsigned long pressedButton;
bool change = 0;
bool oldChange = 1;
unsigned long previousTime;
unsigned int difference;

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(button, INPUT_PULLUP);
}

void loop() {
  if (change != oldChange) {
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);  //when the while loop change, this should delete interference
    digitalWrite(led4, LOW);
    previousTime = millis();
    oldChange = change;
  }

  if (!change) {  //default visual pattern of leds
    difference = millis() - previousTime;

    if (!digitalRead(led1) && difference >= 200) {
      digitalWrite(led1, HIGH);
    }
    if (!digitalRead(led2) && difference >= 400) {
      digitalWrite(led2, HIGH);
    }
    if (!digitalRead(led3) && difference >= 600) {
      digitalWrite(led3, HIGH);
    }
    if (!digitalRead(led4) && difference >= 800) {  //after here, all the leds should be HIGH
      digitalWrite(led4, HIGH);
    }
    if (digitalRead(led4) && difference >= 1000) {
      digitalWrite(led4, LOW);
    }
    if (digitalRead(led3) && difference >= 1200) {
      digitalWrite(led3, LOW);
    }
    if (digitalRead(led2) && difference >= 1400) {
      digitalWrite(led2, LOW);
    }
    if (digitalRead(led1) && difference >= 1600) {  //after here, all the leds should be LOW
      digitalWrite(led1, LOW);
      previousTime = millis();
    }

    if (!digitalRead(button) && millis() - pressedButton > 200) {  //check if button was pressed to break while loop
      pressedButton = millis();
      change = true;
    }
  }

  if (change) {  //alternative of visual pattern of leds
    difference = millis() - previousTime;

    if (!digitalRead(led1) && difference >= 200) {
      digitalWrite(led1, HIGH);
      digitalWrite(led4, HIGH);
      digitalWrite(led2, LOW);
      digitalWrite(led3, LOW);
    }
    if (digitalRead(led1) && difference >= 400) {
      digitalWrite(led1, LOW);
      digitalWrite(led4, LOW);
      digitalWrite(led2, HIGH);
      digitalWrite(led3, HIGH);
      previousTime = millis();
    }
  }

  change = false
}

```
> 2 votes

---
Tags: esp8266, arduino-ide, led, nodemcu, button
---


title: Arduino Servo MG90S not moving

text:
# Question
Title: Arduino Servo MG90S not moving
I'm new with arduino (nano). I am having problems with Servo MG90S, I cant make it move. Im doing the easiest test, Servo cables connected:

Brown -\> gnd
Red -\> 5v
Orange -\> pin 9

my arduino code is:

```
#include <Servo.h>
Servo servo;

const int servoPin = 9;

void setup()
{
  servo.attach(servoPin);
  Serial.begin(9600);
}

void loop()
{
  servo.write(40);
  delay(2000);
  servo.write(0);
  delay(2000);
}

```

As you see its a super simple example, but the result is the servo vibrating slightly.

Extra data: the servo start vibrating with the `servo.attach(servoPin);` it doesnt matters if I set the `servo.write(40);`

# Answer
Okay, so here is the deal: I have looked up the datasheet for the Arduino Nano and the MG90S. The problem is: you may have killed your Arduino Nano. As the datasheet for the Arduino Nano says, "Max DC Current per I/O Pin... 40 mA." (The Datasheet for Arduino Nano). I am not sure if that's 100% of the issue, so, then I looked up the MG90S and it says "Current (typical during movement)... 120-250mA" (Also, another datasheet). Basically, all that means is that you *MAY* have to buy another Arduino because you may have used a servo that requires to much (for lack of a better term) "power." Using some math we see that you went approximately: 210 milli-amps over. Sorry.
> 0 votes

# Answer
Okay, so my first answer is WRONG. The reason being is because the MG90S and the SG90 (which are very similar servos, except the gearing and some others) **CAN** run off that Arduino. As this article shows: How to control the MG90S with the Nano. However, it *IS* best to run that servo off a separate power supply (5V). The issue lies within your wiring. Somehow, there is some miscommunication between us, you, and the Arduino.
> 0 votes

---
Tags: arduino-nano, servo
---


# Question
Title: How to estimate the storage room for txt file when writing data to SD card module?
I'm planning to use Arduino UNO to do some measurements and record it in a SD card module. The measurements is going to last for a year or 20 month. I need some advice on how to estimate how long can the SD card storage last without overflow. Right now I'm doing measurements every second, each second contains 13 lines of data, each line is roughly 30 characters. How big is the txt file gonna be if I left the Arduino unit recording for a year?

# Answer
This is just a multiplication problem.

13 lines times 30 characters is 390 bytes per measurement.

There are 86400 seconds in one day.

86400 * 390 = 33,696,000

So that's around 34 megabytes per day.

After 1 year it would be:

365 * 33.696 = 12299 MB or a little more than 12 GB.
> 1 votes

# Answer
What type of SD card are you using? Based on the capacity, you can calculate SD card storage time to overflow with data/second. Since a character has a size of one byte, the amount of data used per day should be 30 * 13 * 86400 (sec/day) = 33696000 bytes or 0.033696 gb per day.
> 0 votes

---
Tags: sd-card
---


title: Stack Mega Shield

text:
# Question
Title: Stack Mega Shield
I need to support 18 push buttons and 66 IR sensors on my Arduino Mega (model railway). I have a Mega Sensor Shield, but won't have enough pins for all the sensors. Can I get a second sensor shield and nest it some way?

https://www.aliexpress.com/item/1005004554959620.html?spm=a2g0o.order\_list.order\_list\_main.31.1cda18022wJnOM

# Answer
> 2 votes
I may be interpreting your question wrong, but it seems that you're asking if you can somehow get more input pins for your sensor (general-purpose input/output), with which your sensor shield will not help with that. If you want to get more inputs for your sensors, you'll need to use shift registers.

Link to understanding how to add more digital GPIO pins

# Answer
> 1 votes
For a model railway, this may not work as well as you are expecting. Sending 66 sensors values and 18 push-buttons along long cable lengths, as may be expected for a model railway, could introduce noise which would give bogus readings. The noise in long, adjacent, cables could be from one cable inducing a voltage in its neighbour, or simply from the railway operations themselves.

It may be better to use something like RS485 which is a balanced protocol. That is, of the two data wires connecting nodes, one is positive and one is negative simultaneously, for a signal to be considered genuine. Noise would tend to influence the cables in the same direction (eg. both positive) and would thus be discarded.

As described in the Wikipedia article, RS485 is used in aircraft for reliability. The wiring is minimal: two wires for data, plus an earth wire. You would also need 5V power available at the nodes.

What I would suggest here is a series of nodes, spread around your railway layout. Each node could be an inexpensive Atmeg328P processor (around $3 on eBay) with a couple of supporting resistors and capacitors. You would use 3 pins for the RS485 (transmit, receive and enable) which would leave 17 inputs for your sensors and switches per node. Thus, around 5 nodes.

You would keep the cabling for the sensors running to each node as short as possible, to reduce noise. Maybe use shielded cable.

I wrote an RS485 non-blocking library \- available on Github.

There are some explanations about using it on my website most of which is also on the Github page.

Basically what you would do is give each node an address (stored in EEPROM) and then have a master query each node in turn for the values on its sensors or switches. The node would reply, and then the master could move onto the next one.

---

I realise this isn't directly answering the question about the Mega shield, but I am trying to answer the underlying problem of how to connect 84 sensors and switches to one Arduino reliably.

---
Tags: arduino-mega, shields
---


# Question
Title: Connecting Arduino to a cheap Graphics Card for VGA Output
**I understand that** the Arduino is generally not fast or powerful enough to generate a suitable VGA/HDMI signal with higher resolution.

However, I've noticed that there are **inexpensive PC graphics cards** available that can easily maintain a stable screen on a monitor.

---

Back in the DOS era, it was relatively straightforward to write a short program that could output text to CGA/EGA/VGA cards using BIOS calls and a few assembly instructions. The BIOS itself surely was not overly complex or large.

---

So my idea is to take an Arduino, use shift registers like the 74HC595 to create a sufficiently long bus, and connect it to a cheap, obsolete GPU (e.g., an NVIDIA card from a discarded PC) along with a regular monitor. I would then write Arduino code to emulate a BIOS call, such as 10h, which would shift out the "bus status" to the 74HC595s, send the signal to the GPU, and continue this process until the characters are transferred to the GPU.

The GPU can easily generate VGA/HDMI signals and work with any modern monitor. It also has enough memory to support screen resolutions like 80x25, 80x50, or even 132x60 for text-based displays. In fact, it might even be possible to run at full graphical resolutions such as 640x480 or even 2560x1440, with the Arduino slowly sending graphic primitives to display.

While the GPU's performance would be severely degraded, it would still be a better alternative than throwing it away.

---

**My question** is whether it is possible or even feasible to connect a GPU to such a slow source. If it is, I would like to know if there are any readily available and understandable documentation or even someone who has already attempted this approach.

(Or should I post it somwere else? Where?)

# Answer
> 1 votes
This doesn't answer your question about the cheap graphics card, but see https://forum.arduino.cc/t/toorums-quest-ii-atmega328p-based-retro-video-game-with-256-color-graphics/192920 for where Petri Häkkinen did an arcade-style game with an Atmega328 and the AD725 chip for generating the VGA signal.

---
Tags: hardware
---


# Question
Title: Why this simple serial monitor code not working?
The follwoing code echoes whatever arduino recieves through reciever pin. The idea is that arduino will echo whole data in the buffer on the same line and starting from the new line while echoing the next data recieved in the buffer.

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

void loop()
{
  if(Serial.available())
    {
        int count = Serial.available();
        for(int i = 0; i < count; i++)
        {
            char character = Serial.read();
            Serial.print(character);
        }
        Serial.print("\n");
    }
}

```

When I run the code it prints the characters line by line. for example if I enter the word "QUICK" it echoes the following

```
Q
U
I
C
K

```

Whereas I think it should be echoing

```
QUICK

```

Please help me out.

# Answer
You seem to have the assumption, that the string "QUICK" is send as one package of characters, because you send it with one keypress from the Serial Monitor. But Serial (UART) is a "serial" protocol, meaning, that each byte (aka character for ASCII encoding) is send sequentially.

At 9600 baud each byte will take about 1ms to transmit. Also: small random delays can be introduced by the PC or in the USB communication (if you are communication through a USB to Serial chip, like when you connect the Uno via USB).

Your code runs faster than the data arrives at the Unos microcontroller. The first `if` clause is entered as soon, as there is one byte in your Serial buffer. Then you start reading the data from the buffer, but at that time no further bytes did arrive. So the loop is exited after one iteration.

If you want to process the Serial data line by line, you should send a line ending from the Serial Monitor (or whichever program you are using) via the Line ending option. The common way is to use `\n` aka the newline character as line ending. Then in your code you should read the data until you receive the newline character.

That can be done in multiple ways. One way is to read each arriving character into your own buffer, which is big enough to hold the maximum number of characters, that can occur in your messages. Then, when receiving the newline character you can process the data in the buffer. A variables holds the current position in the buffer:

```
unsigned int pos = 0;
char buffer[20] = ""; // enough space for 19 characters + the null character for terminating the string correctly

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

void loop(){
  if(Serial.available()){
    char c = Serial.read();
    if(c != '\n'){
      buffer[pos] = c; // Adding the received character to the buffer
      if(pos < sizeof(buffer) - 1){
        // incrementing the position variable to point to the next position in the buffer
        // but only, if there is enough space in the buffer left
        // otherwise this code will overwrite the last character
        pos++;
      }
    } else {
      buffer[pos] = 0; // Terminating the string correctly
      // Process the message here
      Serial.println(buffer);
      // Reset buffer by setting the position back to zero
      pos = 0;
    }
  }
}

```

Note: This code needs your `loop()` function to iterate fast enough, so that you won't miss more data, than the internal buffer of Serial can hold (I think 32 characters). So you probably don't want to use long delays (which is nearly always a bad idea anyways, see non-blocking coding and the `millis()` function).
> 4 votes

---
Tags: arduino-uno, serial
---


# Question
Title: Trying to resolve invalid conversion from 'byte' {aka 'unsigned char'} to
I'm trying to use an existing Arduino library on the Raspberry Pi Pico. The library is here:

https://github.com/j-bellavance/EdgeDebounce/tree/master

It's based on some interesting insight at Jack Ganssel's blog: http://www.ganssle.com/debouncing.htm

The library works great on an ATMega 328, but I got two errors when changing to the Raspberry Pi Pico.

The first one was resolved by editing the last line of EdgeDebounce.h like this:

```
//#endif;  // Arduino ATMega version
#endif   // Pico version, also works on ATMega

```

The second is a bit more complex. Here's the relevant section of code, these are lines 78 - 102 in EdgeDebounce.cpp :

```
  byte EdgeDebounce::debounce(byte pin) {
  unsigned long pinStatus;
  do {
    pinStatus = 0xffffffff;
    for (byte i = 1; i <= MYsensitivity; i++) pinStatus = (pinStatus << 1) | digitalRead(pin);
  } while ((pinStatus != debounceDontCare) && (pinStatus != 0xffffffff));
  return byte(pinStatus & 0x00000001);
}//debounce------------------------------------------------------------------------------------------------

//updateStatus===================================================================
//After releasing EdgeDebounceLite, I realized that EdgeDebounce could do more
//With this small piece of code, EdgeDebounce can return if a switch is
//  .isclosed();  //Conducting current
//  .isopen();    //Not conducting current
//  .rose();      //Just went from open to closed
//  .fell();      //just went from closed to open
//-------------------------------------------------------------------------------
void EdgeDebounce::update() {
  byte newStatus = debounce();
  if (MYmode == PULLUP) newStatus = !newStatus;
  if (MYstatus == OPEN && newStatus == CLOSED) MYrose = true;
  else                                         MYrose = false;
  if (MYstatus == CLOSED && newStatus == OPEN) MYfell = true;
  else                                         MYfell = false;
  MYstatus = newStatus;
}//update-------------------------------------------------------------------------

```

When I try to compile, I get this error:

```
c:\Users\thisuser\Documents\Arduino\libraries\EdgeDebounce\EdgeDebounce.cpp: In member function 'void EdgeDebounce::update()':
c:\Users\thisuser\Documents\Arduino\libraries\EdgeDebounce\EdgeDebounce.cpp:102:14: error: invalid conversion from 'byte' {aka 'unsigned char'} to 'pinStatus' [-fpermissive]
  102 |   MYstatus = newStatus;
      |              ^~~~~~~~~
      |              |
      |              byte {aka unsigned char}

exit status 1

Compilation error: exit status 1

```

So I see that the byte of "newStatus" doesn't convert to "pinStatus" which is an unsigned long. I've done a bunch of Google searches but can't quite figure out what the fix is.

# Answer
In C and in much pre-standard C++ nothing stops you just assigning an integer value to a variable of enumeration type. In standard C++ (from 1998 onward) that requires an explicit type conversion (a "cast").

The AVR Arduino core supplies the `-fpermissive` option to the compiler which among other things allows the implicit conversion they're doing despite not being standards compliant C++. Whatever you're using (odds are this or this) for RPI Pico Arduino core does not provide the `-fpermissive` option. A lot of Arduino cores don't and probably shouldn't.

You *could* modify the RPI Pico core's platform.txt to give the `-fpermissive` option to g++, but it is probably better to make the code compliant.

## Minimal change

There are probably dozens of ways to do this, but a combination of *mimimal* and *pleasing* to C++ nerds probably looks like:

```
MYstatus = static_cast<pinStatus>(newStatus);

```

### Alternative Casts

```
MYstatus = static_cast<decltype(MYstatus)>(newStatus); // fancier
MYstatus = (pinStatus)newStatus;  // traditional cast
MYstatus = pinStatus(newStatus);  // function-style cast
MYstatus = (decltype(MYstatus))newStatus;  // uhhh
MYstatus = (decltype(MYstatus))(newStatus);  // sure... why not?

```

The `static_cast` declares in intent in a way that other types of cast don't. `decltype` would make that line survive changes to the type of MYstatus better, but `decltype` is not as widely understood.

### Alternately not type-converting at all

You can also observe that `return byte(pinStatus & 0x00000001);` is the only point of return from `byte EdgeDebounce::debounce(byte pin)`. So you know this function returns either 0 (false) or 1 (truthy). That's just what's going to happen with applying `& 1`.

They've defined the enumeration type:

```
enum pinStatus {OPEN, CLOSED};

```

The rules of C and C++ (even pre-standard C++) will assign these constants numeric values 0 and 1, where they weren't explicitly given values and were listed in that order.

So, you could replace `MYstatus = newStatus;` with:

```
{
  if (newStatus) {
      MYstatus = CLOSED;
  } else {
      MYstatus = OPEN;
  }
}

```

Or use the ternary operator if you want don't mind people trying to argue with you:

```
MYstatus = newStatus ? CLOSED : OPEN;

```
> 4 votes

# Answer
`pinStatus` is an enum:

```
enum pinStatus {OPEN, CLOSED};

```

The pinStatus you posted is a local variable, nothing to do with `pinStatus` in the EdgeDebounce.h file.

The error is pointing out that you can't assign an unsigned char to an enum which can only hold OPEN and CLOSED. The unsigned char might hold various other values.

Whoever coded that has made some confusing code.
> 0 votes

---
Tags: c++, library, pins
---


# Question
Title: sim800l gsm module response isn't completed
I am using the `sim800l gsm module` with `nodemcu esp8266` and comunicating with it using AT+ commands. The module is working correctly but I am trying to use the command `AT+CLCC` to get all the current calls' state but it responds with only the first call information and a part of the second call.

This is the response while there are two active calls

```
15:37:19.156 -> AT+CLCC
15:37:19.156 -> +CLCC: 1,0,1,0,0,"+0123456789",145,"name"
15:37:19.156 ->
15:37:19.156 -> +CLCC: 2,

```

I think it is the Serial buffer's problem because the size of the serial buffer is 64 bytes and the response is more than that but I don't know how to handle that

I hope someone can help.

EDIT: this is the code i am using

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

#include <Arduino.h>

#define simTX D3
#define simRX D4

SoftwareSerial sim800l(simRX, simTX);  //RX, TX

void setup() {

  Serial.begin(115200);  //Begin serial communication with Arduino and Arduino IDE (Serial Monitor)

  sim800l.begin(115200);  //Begin serial communication with Arduino and SIM800L

}

void loop() {

  updateSerial();

}

//Start
// this method takes input from the serial monitor the pass it to sim800l via serial communication
void updateSerial() {
  delay(500);
  while (Serial.available()) {
    sim800l.write(Serial.read());  //Forward what Serial received to Software Serial Port
  }
  while (sim800l.available()) {
    Serial.write(sim800l.read());  //Forward what Software Serial received to Serial Port
  }
}
//End

```

# Answer
Just for someone in the future who is having the same issue.

the problem was because of the boadrate 115200 is pretty fast for a software serial implementation so i just changed it to 9600

```
 sim800l.begin(9600);  //Begin serial communication with Arduino and SIM800L

```

good luck from the past :)
> 2 votes

---
Tags: serial, esp8266, softwareserial, gsm, sim800
---


# Question
Title: LED doesn't completely turn off with digitalWrite(led, LOW);
When I was testing out a program I found a strange behavior of ESP8266.

LEDs don't turn off completely in the first `digitalWrite(led, LOW)`, just the brightness of the LED goes down, but it does turn off in the second `digitalWrite(led, LOW)`.

I don't know if it's related to the code or the circuit, so here are both (the program is just two different visual patterns of LEDs toggled by a button)

```
#define led1 D0
#define led2 D1
#define led3 D2
#define led4 D3
#define button D7

unsigned long pressedButton;
bool change = 0;
unsigned long previousTime = millis();
unsigned int difference;

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(button, INPUT_PULLUP);
}

void loop(){
  if (!digitalRead(button) && millis()-pressedButton>200){       //check if button was pressed to change visual pattern of leds
      pressedButton = millis();
      change = !change;
      digitalWrite(led1, LOW);         //here led completely turn off
      digitalWrite(led2, LOW);
      digitalWrite(led3, LOW);
      digitalWrite(led4, LOW);
      previousTime = millis();
  }

  difference = millis()-previousTime;

  if (!change){                                     //default visual pattern of leds
    if (!digitalRead(led1) && difference>=200){
      digitalWrite(led1, HIGH);
    }
    if (!digitalRead(led2) && difference>=400){
      digitalWrite(led2, HIGH);
    }
    if (!digitalRead(led3) && difference>=600){
      digitalWrite(led3, HIGH);
    }
    if (!digitalRead(led4) && difference>=800){
      digitalWrite(led4, HIGH);
    }
    if (difference>=1000){
      digitalWrite(led4, LOW);           //the leds just shrink here
    }
    if (difference>=1200){
      digitalWrite(led3, LOW);
    }
    if (difference>=1400){
      digitalWrite(led2, LOW);
    }
    if (difference>=1600){
      digitalWrite(led1, LOW);
      previousTime = millis();
    }
  }

  if (change){                    //alternative pattern
     if (!digitalRead(led1) && difference>=200 && change){
       digitalWrite(led1, HIGH);
       digitalWrite(led4, HIGH);
       digitalWrite(led2, LOW);
       digitalWrite(led3, LOW);
    }
    if (digitalRead(led1) && difference>=400 && change){
       digitalWrite(led1, LOW);
       digitalWrite(led4, LOW);
       digitalWrite(led2, HIGH);
       digitalWrite(led3, HIGH);
       previousTime = millis();
    }
  }
}

```

Actually, it's a NodeMCU Esp8266, with the pins defined on the code and a 470 ohms resistor. (obs: resistor is not shorted, in my breadboard those rows are separated)

# Answer
> 2 votes
```
if (!digitalRead(led3) && difference>=600){
  digitalWrite(led3, HIGH);
}
if (!digitalRead(led4) && difference>=800){
  digitalWrite(led4, HIGH);
}
if (difference>=1000){
  digitalWrite(led4, LOW);           //the leds just shrink here
}
if (difference>=1200){
  digitalWrite(led3, LOW);
}

```

Consider what will happen when the difference is \>= 1000.

If the LED is off you turn it on (because it passes the first test, the difference is \>= 600), and a moment later you turn it off. So the LEDs are being turned on and off in quick succession, which makes them look dim.

Try re-ordering the tests, and add `else` for each subsequent one. That seems to work for me:

```
  if (!change){                                     //default visual pattern of leds
    if (difference>=1600){
      digitalWrite(led1, LOW);
      previousTime = millis();
    }
    else if (difference>=1400){
      digitalWrite(led2, LOW);
    }
    else if (difference>=1200){
      digitalWrite(led3, LOW);
    }
    else if (difference>=1000){
      digitalWrite(led4, LOW);
    }
    else if (!digitalRead(led4) && difference>=800){
      digitalWrite(led4, HIGH);
    }
    else if (!digitalRead(led3) && difference>=600){
      digitalWrite(led3, HIGH);
    }
    else if (!digitalRead(led2) && difference>=400){
      digitalWrite(led2, HIGH);
    }
    else if (!digitalRead(led1) && difference>=200){
      digitalWrite(led1, HIGH);
    }
  }

```

---

Also, that resistor on the bottom row isn't achieving anything because all the pins on the bottom row are connected together so it is just shorted out. Not good for the LEDs or the processor.

---
Tags: arduino-ide, led, nodemcu, button, digitalwrite
---


# Question
Title: ESP8266 serial monitor spitting out garbage
I am trying to set up a weather station, and I should just have the anemometer left. This code works fine (as far as I know).

```
// Pin definitions
const int reedSwitchPin = 2;

// Variables
volatile unsigned long lastRotationTime = 0;
volatile float windSpeed = 0.0;
const float windSpeedFactor = 2.4; // Factor to convert rotation time to wind speed

void setup() {
  pinMode(reedSwitchPin, INPUT_PULLUP);
  // attachInterrupt(digitalPinToInterrupt(reedSwitchPin), handleRotation, FALLING);
  Serial.begin(9600);
  Serial.println("hello world!");
}

void loop() {
  // Test reed switch functionality
  int reedState = digitalRead(reedSwitchPin);
  if (reedState == HIGH) {
    Serial.println("Reed switch triggered!");
  }

  // Calculate wind speed based on the time between rotations
  unsigned long elapsedTime = micros() - lastRotationTime;
  if (elapsedTime > 0) {
   windSpeed = windSpeedFactor / (float)elapsedTime;
  }

  Serial.print("Wind Speed: ");
  Serial.print(windSpeed);
  Serial.println(" m/s");

  delay(1000); // Delay for 1 second before measuring again
}

void handleRotation() {
  // Record the time of the last rotation
  lastRotationTime = micros();

}

```

But when I uncomment the following line: `attachInterrupt(digitalPinToInterrupt(reedSwitchPin), handleRotation, FALLING);`

it prints garbage characters on the serial monitor. Here is the full code:

```
    // Pin definitions
const int reedSwitchPin = 2;

// Variables
volatile unsigned long lastRotationTime = 0;
volatile float windSpeed = 0.0;
const float windSpeedFactor = 2.4; // Factor to convert rotation time to wind speed

void setup() {
  pinMode(reedSwitchPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(reedSwitchPin), handleRotation, FALLING);
  Serial.begin(9600);
  Serial.println("hello world!");
}

void loop() {
  // Test reed switch functionality
  int reedState = digitalRead(reedSwitchPin);
  if (reedState == HIGH) {
    Serial.println("Reed switch triggered!");
  }

  // Calculate wind speed based on the time between rotations
  unsigned long elapsedTime = micros() - lastRotationTime;
  if (elapsedTime > 0) {
   windSpeed = windSpeedFactor / (float)elapsedTime;
  }

  Serial.print("Wind Speed: ");
  Serial.print(windSpeed);
  Serial.println(" m/s");

  delay(1000); // Delay for 1 second before measuring again
}

void handleRotation() {
  // Record the time of the last rotation
  lastRotationTime = micros();
}

```

# Answer
Pin 2 that is gpio2 (D4) is not suitable for this esp8266 application because this pin must be high at boot time and your anemometer could be in either state. Try say pin 4 that is gpio4 (D2) instead or search for "best pins to use - esp8266"

A crash during boot time can result in characters being written to the serial monitor at a baud rate of 115200 or 74880.
> -1 votes

---
Tags: serial, esp8266, nodemcu, esp
---


# Question
Title: What is the max output rating of the pins on the Arduino Mega?
I have conflicting information on the max output rating for the Arduino Mega. Some say 200 mA and others say 800 mA like the Uno board. I am running 8 model railroad signal devices that have (3) 3mm LEDs (Red, Yellow, and Green) in each signal. Of the 24 LEDs, only 8 are energized at any point in time. 8\*.020 = 160 mA. I believe I am good, but confused as to why the Uno board with 13 digital output pins can handle 800 mA and the Mega board with 40 or so output pins (not including all the TX RX IO pins) can only handle 200 mA. Lots of forum discussion on this, but most go over my head without answering the question! LOL

Simply, how many mA can all of the digital pins combined provide?

---

Well theory (math) is nice, and a good starting point, but reality is better.

The signals I am talking about are (model) railroad trackside warning signal devices that have a red, yellow and green light, and depending on which light is lit, tells the train's Engineer if it is safe to continue down the track.

Each of these signals are 2.1/2" in height and the LEDs use 30 gauge wires and a 1K resistor.

I connected the red LED on all 8 signal devices to my variable power supply, turned it on and lit all 8 red LEDs with 5 volts, and wow, all 8 only used .023 amps total.

I then disconnected 7 of them and a single red LED only used .002 - .003 amps. I connected the rest of the signals one at a time, and 2 signals used .006 amps, 3 signals used .009 amps, 4 signals used .011 amps, 5 signals used .014 amps, 6 signals used .017 amps, 7 signals used .020 amps and all 8 signals again only used .023 amps.

If this is the case, that is less than the max output from a single pin.

So, my plan is to connect the signals to the Arduino Mega 2560 on at a time, monitor the total current the Arduino in using after connecting each signal, and see just how much these signals are using.

# Answer
The answers are right there in the datasheet.

The datasheet of the ATMega2560 (and 1280 etc.), page 355, states an absolute maximum current of 200 mA for the ATMega package and 40 mA per I/O pin.

In addition (thank you for the comment, @NickGammon), there are some further restrictions that are described from page 356 of the linked datasheet:

* The sum of current which can be *sunk* from various ports cannot exceed 100 mA, and from others, 200 mA.
* The same is true for the amount of current that can be sourced from various ports.

For example, for ports A0-A7 you cannot source a total of more than 100 mA (under steady conditions) and not 40 mA * 8 like you might expect.

So, if you had 8 LEDs on at once, continuously, you would only have 12.5 mA available for each of those ports (for a total of 8 x 12.5 mA = 100 mA).

That means that the 160 mA mentioned in the question could easily be out of spec.

It's not recommended to stay at or near the Absolute Maximum values mentioned in the datasheet for an extended amount of time. It's better to design your solution so that these abolute maximum values are never approached.

For your particular situation I would look into external (TTL) buffers between your Mega and your LEDs.

Alternatively, you could reduce the amount of current through the LEDs to make sure the total amount of current will always stay well below 200 mA or the other limitations mentioned above.
> 1 votes

---
Tags: current, atmega2560
---


# Question
Title: Why does my Arduino stop uploading to the Thingspeak server after several hours?
I'm using a Maduino Zero 4G SIM7600 device to upload data from 28 sensors to a ThingSpeak IoT server. It works well for a few hours, then stops uploading the data. Sometimes it starts again after an inconsistent amount of time (an hour or two), sometimes it doesn't.

I can confirm that it's only the SIM7600 and/or Thingspeak functions that are failing, as the serial monitor demonstrates the other I2C related operations on the Arduino board are still working fine even when the server uploads fail.

Here's the relevant part of the code:

```
void setup(){
    SerialUSB.begin(115200);
    SerialUSB.println("Serial initialized");
    Serial1.begin(115200);
    Wire.begin();

    pinMode(LTE_PWRKEY_PIN, OUTPUT);
    digitalWrite(LTE_RESET_PIN, LOW);
    delay(100);
    digitalWrite(LTE_PWRKEY_PIN, HIGH);
    delay(2000);
    digitalWrite(LTE_PWRKEY_PIN, LOW);

    pinMode(LTE_FLIGHT_PIN, OUTPUT);
    digitalWrite(LTE_FLIGHT_PIN, LOW);//Normal Mode

    delay(5000);

    sendData("AT+CCID", 3000, DEBUG);
    sendData("AT+CREG?", 3000, DEBUG);
    sendData("AT+CGATT=1", 1000, DEBUG);
    sendData("AT+CGACT=1,1", 1000, DEBUG);
    sendData("AT+CGDCONT=1,\"IP\",\"sp.mb.com\"", 1000, DEBUG);

    delay(5000);
}

void loop(){
  getData();

  //Sensors 0-6
  http_str = "AT+HTTPPARA=\"URL\",\"https://api.thingspeak.com/update?api_key=" + Apikey1 + "&field1=" + (String)hallData[0] + "&field2=" + (String)hallData[1] + "&field3=" + (String)hallData[2] + "&field4=" + (String)hallData[3] + "&field5=" + (String)hallData[4] + "&field6=" + (String)hallData[5] + "&field7=" + (String)hallData[6] + "\"\r\n";
  SerialUSB.print("Sent to Channel 1: ");
  SerialUSB.println(http_str);
  sendData("AT+HTTPINIT\r\n", 2000, DEBUG);
  sendData(http_str, 2000, DEBUG);
  sendData("AT+HTTPACTION=1\r\n", 3000, DEBUG);
  sendData("AT+HTTPTERM\r\n", 3000, DEBUG);

  //Sensors 7-13
  http_str = "AT+HTTPPARA=\"URL\",\"https://api.thingspeak.com/update?api_key=" + Apikey2 + "&field1=" + (String)hallData[7] + "&field2=" + (String)hallData[8] + "&field3=" + (String)hallData[9] + "&field4=" + (String)hallData[10] + "&field5=" + (String)hallData[11] + "&field6=" + (String)hallData[12] + "&field7=" + (String)hallData[13] + "\"\r\n";
  SerialUSB.print("Sent to Channel 2: ");
  SerialUSB.println(http_str);
  sendData("AT+HTTPINIT\r\n", 2000, DEBUG);
  sendData(http_str, 2000, DEBUG);
  sendData("AT+HTTPACTION=1\r\n", 3000, DEBUG);
  sendData("AT+HTTPTERM\r\n", 3000, DEBUG);

  //Sensors 14-20
  http_str = "AT+HTTPPARA=\"URL\",\"https://api.thingspeak.com/update?api_key=" + Apikey3 + "&field1=" + (String)hallData[14] + "&field2=" + (String)hallData[15] + "&field3=" + (String)hallData[16] + "&field4=" + (String)hallData[17] + "&field5=" + (String)hallData[18] + "&field6=" + (String)hallData[19] + "&field7=" + (String)hallData[20] + "\"\r\n";
  SerialUSB.print("Sent to Channel 3: ");
  SerialUSB.println(http_str);
  sendData("AT+HTTPINIT\r\n", 2000, DEBUG);
  sendData(http_str, 2000, DEBUG);
  sendData("AT+HTTPACTION=1\r\n", 3000, DEBUG);
  sendData("AT+HTTPTERM\r\n", 3000, DEBUG);

  //Sensors 21-27
  http_str = "AT+HTTPPARA=\"URL\",\"https://api.thingspeak.com/update?api_key=" + Apikey4 + "&field1=" + (String)hallData[21] + "&field2=" + (String)hallData[22] + "&field3=" + (String)hallData[23] + "&field4=" + (String)hallData[24] + "&field5=" + (String)hallData[25] + "&field6=" + (String)hallData[26] + "&field7=" + (String)hallData[27] + "\"\r\n";
  SerialUSB.print("Sent to Channel 4: ");
  SerialUSB.println(http_str);
  sendData("AT+HTTPINIT\r\n", 2000, DEBUG);
  sendData(http_str, 2000, DEBUG);
  sendData("AT+HTTPACTION=1\r\n", 3000, DEBUG);
  sendData("AT+HTTPTERM\r\n", 3000, DEBUG);
}

String sendData(String command, const int timeout, boolean debug){
  String response = "";
  Serial1.println(command);

  long int time = millis();
  while ( (time + timeout) > millis()){
    while (Serial1.available()){
      char c = Serial1.read();
      response += c;
    }
  }
  if (debug){
    SerialUSB.print(response);
  }
  return response;
}

```

All SIM7600 related operations are taken directly from the Makerfabs examples, found on this page. One thing of note is that in their example, they use the command `AT+HTTPACTION=0`, which, according to this page, means READ. This does work but it sometimes returns ERROR instead of OK. I've changed it to `AT+HTTPACTION=1`, which means POST, which seems to work a bit better - at least there are no ERROR messages. But the same problem still persists.

UPDATE #1: The ERROR messages sometimes return even with the `AT+HTTPACTION=1` adjustment. Something I've noticed is that generating new API keys for each of the Thingspeak pages (there are 4 in total, 7 sensors per page) causes it to work for a while when it didn't before. No explanation for why that is.

Any advice would be greatly appreciated.

Hardware wise, I'm powering this from an AC adapter through a DC-DC 5V converter. I'm also using a 3.7 battery for backup power.

# Answer
From the ThingSpeak License Options page:

> ThingSpeak is available as a free service for non-commercial small projects (\<3 million messages/year or ~8,200 messages/day).

Could you be hitting that limit?
> 0 votes

---
Tags: iot, arduino-zero, thingspeak
---


# Question
Title: ArduinoHTTPClient POST multipart/form-data from SD card returning 400 Bad Request
I have been having trouble trying to send a small txt file to my server using the following function with TinyGSM. I know I am connected to the internet and reaching the web server, however, I keep receiving a `400 Bad Request` code. I think something is wrong with my `PostHeader`, but I have no clue where or what it could be... I know I am connecting to my server as I try a default get and return webpage text...

```
TinyGsm modem(SerialAT);
TinyGsmClient client2(modem);
HttpClient client(client2, server, port);

void fileUpload(String filename){
  if(!initSD()){
    return;
  }
  File dataFile = SD.open(filename.c_str());
  Serial.println("Uploading File...");
  if (!client.connect(server, port)) {
    Serial.println("Failed connecting to Server");
    return;
  }
  String fileType = "text/plain";
  String content = "--boundary1\r\n";
  content += "Content-Disposition: form-data; name=\"fileToUpload\"; filename="+String(filename)+"\r\n";  // the fileToUpload is the form parameter
  content += "Content-Type: "+fileType+"\r\n\r\n";
  //after this, post the file data.
  String closingContent = "\r\n--boundary1--";
  //Serial.println(content);
  client.println(String("POST ") + "/upload.php" +" HTTP/1.1\r\n");
  client.println(String("Host: ") + server + "\r\n");
  client.println("Content-Type: multipart/form-data; boundary=boundary1\r\n");
  client.println("Connection: close\r\n");
  client.println("Content-Length: "+String(content.length()+dataFile.size()+closingContent.length())+"\r\n");
  client.println(content);
  client.println();
  if (dataFile) {  // start sending file content
    while (dataFile.available()) {
      char c = dataFile.read();
        client.print(c);
      }
    dataFile.close();
  }
  client.println(closingContent);
  Serial.println("File Sent.");
    // read the status code and body of the response
  int statusCode = client.responseStatusCode();
  String response = client.responseBody();

  Serial.print("Status code: ");
  Serial.println(statusCode);
  Serial.print("Response: ");
  Serial.println(response);
}

```

# Answer
> 0 votes
There were a couple issues that I finally managed to solve... I was able to get it to work by *not* using `ArduinoHTTPClient`. Here is working code for anyone else who stumbles here.

```
TinyGsmClient client(modem);

void fileUpload(String filename){
  File dataFile = SD.open(filename.c_str());
  Serial.println("Uploading File...");
  if (!client.connect(server, port)) {
    Serial.println("Failed connecting to Server");
    return;
  }
  String fileType = "text/plain";
  String content = "--boundary1\r\n";
  content += "Content-Disposition: form-data; name=\"fileToUpload\"; filename="+String(filename)+"\r\n";  // the fileToUpload is the form parameter
  content += "Content-Type: "+fileType+"\r\n\r\n";
  //after this, post the file data.
  String closingContent = "\r\n--boundary1--\r\n";
  //Serial.println(content);
  client.println(String("POST ") + "/upload.php" +" HTTP/1.1"); // or wherever you need to call/print to.
  client.println(String("Host: ") + server);
  client.println("Content-Length: "+String(content.length()+dataFile.size()+closingContent.length()));
  client.println("Content-Type: multipart/form-data; boundary=boundary1");
  client.println();
  client.println(content);
  if (dataFile) {  // start sending file content
    String data = "";
    while (dataFile.available()) {
      char c = dataFile.read();
      data += c;
      //write every line break...
      if(c == '\n'){
        client.write(data.c_str());
        data = "";
      }
    }
    dataFile.close();
  }
  client.print(closingContent);
  unsigned long timeout = millis();
  while (client.connected() && millis() - timeout < 50000L) {
    // Print available data
    while (client.available()) {
      char c = client.read();
      Serial.print(c);
      timeout = millis();
    }
  }
  client.stop();
}

```

---
Tags: esp32, gsm, http
---


# Question
Title: Pin Change Interrupt Flag timing on 1284P
I want to ask about pin change interrupts on a 1284P chip using MightyCore. I have a question about the timing of multiple interrupts on one port. Specifically, if I am servicing a PCINT vector and another pin in the port changes while I am in the ISR, will it generate another interrupt immediately following the one I am servicing?

When I read the datasheet I see:

> Bit 2 – PCIF2: Pin Change Interrupt Flag 2 When a logic change on any PCINT\[23:16\] pin triggers an interrupt request, PCIF2 will be set. If the I-bit in SREG and the PCIE2 bit in PCICR are set, the MCU will jump to the corresponding Interrupt Vector. The flag is cleared when the interrupt routine is executed. Alternatively, the flag can be cleared by writing '1' to it.

When it says that the flag is cleared when the interrupt routine is executed, does that mean when it enters or exits the ISR? If it is at the end, can I clear the flag in the first line of the ISR and allow another pin change to set it again even if it happens before I exit the ISR?

# Answer
When it is entered. The wording is slightly vague but I think "when the interrupt routine is executed" means the commencement of execution. Otherwise multiple pin-change interrupts could be easily missed, depending on how long you took inside the ISR.

I suggest writing a simple test that saves somewhere what the flag is, upon entering the ISR, and check it is cleared already.

---

I wrote this test for the Uno (which is the same basic architecture):

```
volatile bool firstTime = true;
volatile byte PCIFR_copy = 0;

ISR (PCINT0_vect)
 {
 // handle pin change interrupt for D8 to D13 here

 if (!firstTime)
   return;

 firstTime = false;
 PCIFR_copy = PCIFR;
 }  // end of PCINT0_vect

void setup ()
  {
  pinMode (9, INPUT_PULLUP);
  Serial.begin (115200);

  // pin change interrupt (for D9)
  PCMSK0 |= bit (PCINT1);  // want pin 9
  PCIFR  |= bit (PCIF0);   // clear any outstanding interrupts
  PCICR  |= bit (PCIE0);   // enable pin change interrupts for D8 to D13
  }  // end of setup

void loop ()
  {
  Serial.print ("First time is ");
  Serial.print ((int) firstTime);
  Serial.print (", Flag is ");
  Serial.println ((int) PCIFR_copy);
  delay (1000);
  }  // end of loop

```

The PCIFR flag was always zero, even after triggering the pin-change interrupt, which shows that it was cleared upon **entering** the ISR.

> will it generate another interrupt immediately following the one I am servicing?

So, based on the above, the answer is yes it will. Upon leaving the ISR one more instruction will be executed and then the next interrupt will be serviced (assuming a higher-priority interrupt doesn't get in first).

---

Another way of looking at it is that the pin change will always set that flag. Between instructions the processor would check that flag (and the flags for the other interrupts) and for the highest priority interrupt, if that flag is set, then it would clear that flag and then commencing processing that interrupt. That is really the only logical way it could work.

---

Also, it makes more sense from the design of the processor to clear the flag upon entering the ISR. Apart from the problem that interrupts could be missed if it didn't, when it enters the ISR the processor "knows" which interrupt it is servicing, because it would have checked the PCIFx flag, it would have checked the PCIEx flag (to see if the interrupt should be executed) and it would have then changed the program counter to the appropriate address for that interrupt, after pushing the current program counter onto the stack. This would be the logical time to clear that flag while all this information is in the processor's "head" so to speak.

At the end of the ISR the code simply executes a RTI (Return from Interrupt) instruction which doesn't have associated with it which interrupt it is returning from. Thus it would be hard to clear the flag at that point.
> 7 votes

---
Tags: interrupt, avr
---


title: Arduino UNO Power interruption

text:
# Question
Title: Arduino UNO Power interruption
Do you have to upload the UNO after the applied power is disconnected?

Does the UNO retain the code without any power?

And when the power is disconnected, if the code is retained, will the timers retain their values? Thanks

# Answer
> 4 votes
> Do you have to upload the UNO after the applied power is disconnected?

No.

> Does the UNO retain the code without any power?

Yes.

> And when the power is disconnected, if the code is retained, will the timers retain their values?

No.

# Answer
> 1 votes
This answer simply add some detail to that provided by VE7JRO to make it more generally applicable but this does look rather like a school assignment. Program code is stored in flash memory and this is retained after a power down. It is not necessary to reload it. The registers which hold timer values or other data from a running program are stored in RAM memory and this is lost on power off. It is possible also to save some data from a running program in EEPROM (or in some cases flash memory) which also survives after a power down.

---
Tags: arduino-uno, power, timers, uploading
---


# Question
Title: How to turn LEDs based on voltage readings?
I am trying to turn LEDs in an LED bridge based on the voltage reading from a power source. when the Voltage is zero nothing is ON and then the LEDs gradually turn ON as increase the voltage connected to the Ao pin. ( I am using a pro trinket 3V 120 MHZ)

This is my code:

```
const int analogPin = A0; // the pin that the potentiometer is attached to
const int ledCount = 7; // the number of LEDs in the bar graph

int ledPins[] = { 3, 4, 5, 6, 8, 9, 10}; // an array of pin numbers to which LEDs are attached

void setup() {
    // loop over the pin array and set them all to output:
    for (int thisLed = 0; thisLed < ledCount; thisLed++) {
        pinMode(ledPins[thisLed], OUTPUT);
    }
}

void loop() {
    // read the potentiometer:
    int sensorReading = analogRead(analogPin);
    // map the result to a range from 0 to the number of LEDs:
    int ledLevel = map(sensorReading, 0, 1023, 0, ledCount);

    // loop over the LED array:
    for (int thisLed = 0; thisLed < ledCount; thisLed++) {
        // if the array element's index is less than ledLevel,
        // turn the pin for this element on:
        if (thisLed < ledLevel) {
            digitalWrite(ledPins[thisLed], HIGH);
        }
        // turn off all pins higher than the ledLevel:
        else {
            digitalWrite(ledPins[thisLed], LOW);
        }
    }
}

```

However, I am not getting the outcome I want. when there is 0 voltage one LED turns ON instead of nothing. when there is a voltage all connected LEDs turn ON regardless of what the voltage is

when there is no voltage connected (floating wires), I get this:

when I put any amount of Voltage as long as the power supply is ON the results is the same:

Note: What am I doing wrong? edit: connections are something like that but with fewer digital pins.

Note: What am I doing wrong!EDIT: I was able to get around and print the serial monitor result:

* when the power source is OFF, the reading at A0 (sensorreading) is:

Note: What am I doing wrong!- when the power source is ON at any value, the reading at A0 (sensorreading) is:

(Note: What am I doing wrong!)

# Answer
You are using a Full-size breadboard, for the full-size breadboards, the power rails are divided into two half sections as shown in this picture, and you need to have jumpers to bridge the two half-sections if you want to use them as a single power trail full-size section.

So on your photo, you thought that your blue wire (for GND) is connected to the rest of GND pins, but it is actually not connected.
> 3 votes

# Answer
I can say your code is working but you need to check the wirering of your circuit .

Note that the voltage on the analogread pin should not be an oscillating voltage at low frequency like AC voltage. It should be a direct stable voltage to get the correct output.

Here is my diagram below for you to make changes with yours . Ive testedit on my simulation app and its working perfectly.

The code

```

const int analogPin = A0; // the pin that the potentiometer is attached to
const int ledCount = 7; // the number of LEDs in the bar graph
int ledPins[] = { 3, 4, 5, 6, 8, 9, 10}; // an array of pin numbers to which LEDs are attached

void setup() {
Serial.begin(9600);
// loop over the pin array and set them all to output:
for (int thisLed = 0; thisLed < ledCount; thisLed++) {
pinMode(ledPins[thisLed], OUTPUT); }
}

void loop() { // read the potentiometer:
int sensorReading = analogRead(analogPin);
Serial.print("sensor read : ");
Serial.println(sensorReading);

// map the result to a range from 0 to the number of LEDs:
int ledLevel = map(sensorReading, 0, 1023, 0, ledCount);
Serial.print("led Level : ");
Serial.println(ledLevel);

// loop over the LED array:
for (int thisLed = 0; thisLed < ledCount; thisLed++) {
// if the array element's index is less than ledLevel, // turn the pin for this element on:
if (thisLed < ledLevel) {
digitalWrite(ledPins[thisLed], HIGH);
}

// turn off all pins higher than the ledLevel:
else {
digitalWrite(ledPins[thisLed], LOW);
} }

//delay(500); //for debugging
 }

```

The diagram

Note that if you're tryingto measure a voltage higher than 5 volts, make sure to build the voltage divider circuit with the appropriate resistor values for you to get 5v output as that is the highest volt the arduino can carry. measure Example below shows a 12 volts dc battery voltage measure(note that 5 volts is the highest voltage supplied to the arduino, not the full 12 volts):
> 2 votes

---
Tags: led, analogread, voltage-level, arduino-pro-mini, electronics
---


title: PlatformIO and const PROGMEM

text:
# Question
Title: PlatformIO and const PROGMEM
I'm using the DuinoWitchery LCD library (https://github.com/duinoWitchery/hd44780) in a PlatformIO Arduino project with CLion.

The following code works if I stick it in main.cpp:

```
// near top of class...
const PROGMEM uint8_t decimalDigit[10][8] = {
        {0x07, 0x05, 0x05, 0x05, 0x07, 0x18, 0x18}, // .0
        {0x02, 0x02, 0x02, 0x02, 0x02, 0x18, 0x18}, // .1
        {0x07, 0x01, 0x07, 0x04, 0x07, 0x18, 0x18}, // .2
        {0x07, 0x01, 0x07, 0x01, 0x07, 0x18, 0x18}, // .3
        {0x5,  0x05, 0x07, 0x01, 0x01, 0x18, 0x18}, // .4
        {0x07, 0x04, 0x06, 0x01, 0x06, 0x00, 0x18, 0x18}, // .5
        {4,    4,    7,    5,    7,    0,    0x18, 0x18}, // .6
        {7,    1,    1,    1,    1,    0,    0x18, 0x18}, // .7
        {7,    5,    7,    5,    7,    0,    0x18, 0x18}, // .8
        {7,    5,    7,    1,    1,    0,    0x18, 0x18}, // .9
};

hd44780_I2Cexp lcd(0x27);

// ... snip ...

void setup() {
    for (int x=0; x<8; x++)
       lcd.createChar((uint8_t)x, decimalDigit[x]);
    // ...snip...
}

```

... but if I move the code into another class, like:

**Renderer.h**

```
class Renderer : BaseRenderer {
public:
    virtual void renderTo(hd44780* lcd) override;
    // ... snip ...
private:
const PROGMEM uint8_t decimalDigit[10][8] = {
        {0x07, 0x05, 0x05, 0x05, 0x07, 0x18, 0x18}, // .0
        {0x02, 0x02, 0x02, 0x02, 0x02, 0x18, 0x18}, // .1
        {0x07, 0x01, 0x07, 0x04, 0x07, 0x18, 0x18}, // .2
        {0x07, 0x01, 0x07, 0x01, 0x07, 0x18, 0x18}, // .3
        {0x5,  0x05, 0x07, 0x01, 0x01, 0x18, 0x18}, // .4
        {0x07, 0x04, 0x06, 0x01, 0x06, 0x00, 0x18, 0x18}, // .5
        {4,    4,    7,    5,    7,    0,    0x18, 0x18}, // .6
        {7,    1,    1,    1,    1,    0,    0x18, 0x18}, // .7
        {7,    5,    7,    5,    7,    0,    0x18, 0x18}, // .8
        {7,    5,    7,    1,    1,    0,    0x18, 0x18}, // .9
    };
}

```

**Renderer.cpp**

```
void Renderer::renderTo(hd44780lcd* lcd) {
    for (int x=0; x<8; x++)
       lcd->createChar((uint8_t)x, decimalDigit[x]);
    // ...snip...
}

```

... the custom characters end up with garbage data.

I **think** I might be breaking some esoteric rule that governs where you're allowed to put a `const PROGMEM uint8_t[]`, and causing the array declared in Renderer.h to end up in SRAM. But I'm not sure how to confirm it OR fix it.

---

note: the for/next loop to create the chars is just for the sake of illustration & to demonstrate that something that works in main.setup() fails in Renderer.renderTo(). In *real* life, the sequence of characters getting rendered to the LCD owns one of the 8 custom characters & redefines it as necessary to be the decimal point and tenths value.

# Answer
> 4 votes
The `PROGMEM` qualifier can only be applied to statically-allocated constant data. When you move the `decimalDigit` array inside the class, it becomes a data member, i.e. you have one copy of the array per instance... in RAM. In this case, `PROGMEM` does not work. My compiler says:

```
warning: ‘__progmem__’ attribute ignored [-Wattributes]

```

If you want to keep the array inside the class, it must be given the `static` qualifier. It then becomes statically-allocated class data (not instance data):

```
// Renderer.h:
class Renderer : BaseRenderer {
public:
    virtual void renderTo(hd44780* lcd) override;
    // ... snip ...
private:
    static const PROGMEM uint8_t decimalDigit[10][8];
};

// Renderer.cpp:
const PROGMEM uint8_t Renderer::decimalDigit[10][8] = {
    {0x07, 0x05, 0x05, 0x05, 0x07, 0x18, 0x18}, // .0
    {0x02, 0x02, 0x02, 0x02, 0x02, 0x18, 0x18}, // .1
    // ... snip ...
};

```

Of course, putting the array within the class is not an obligation. If it is going to be private anyway, the outside world (the files that include Renderer.h) does not need to know about its existence.

# Answer
> 1 votes
OK, I ended up blindly stumbling over the solution, even though at this moment I have no idea why it actually works.

I moved the `const PROGMEM uint8_t decimalDigit[10][8] = {...}` declaration **from** Renderer.h **to** the almost-top of Renderer.cpp, so it sits between `#include "Renderer.h"` and constructor:

```
#include "Renderer.h"

const PROGMEM uint8_t decimalDigit[10][8] = {
        {0x07, 0x05, 0x05, 0x05, 0x07, 0x18, 0x18}, // .0
        {0x02, 0x02, 0x02, 0x02, 0x02, 0x18, 0x18}, // .1
        {0x07, 0x01, 0x07, 0x04, 0x07, 0x18, 0x18}, // .2
        {0x07, 0x01, 0x07, 0x01, 0x07, 0x18, 0x18}, // .3
        {0x5,  0x05, 0x07, 0x01, 0x01, 0x18, 0x18}, // .4
        {0x07, 0x04, 0x06, 0x01, 0x06, 0x00, 0x18, 0x18}, // .5
        {4,    4,    7,    5,    7,    0,    0x18, 0x18}, // .6
        {7,    1,    1,    1,    1,    0,    0x18, 0x18}, // .7
        {7,    5,    7,    5,    7,    0,    0x18, 0x18}, // .8
        {7,    5,    7,    1,    1,    0,    0x18, 0x18}, // .9
};

Renderer::Renderer(int col, int row, int customCharNumber) : BaseRenderer(col, row) {
    assignCustomChar(customCharNumber);
}

```

For now, I just have to chalk it up as 'black magic', because some subsequent experiments have forced me to question and doubt everything I ever thought I understood about how #include directives work.

---
Tags: progmem, platformio
---


# Question
Title: ERROR: return reinterpret_cast<T>(pgm_read_ptr(p));
I need to update **DHT** sensor data to the webserver in ***JSON*** format using **ESP8266**. This is my code.

```
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <DHT.h>
#include <ArduinoJson.h>

const char* ssid = "YOUR_SSID";
const char* password = "YOUR PASSWORD";
const int dhtPin = D4;
DHT dht(dhtPin, DHT11);
ESP8266WebServer server(80);

void handleRoot() {
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();

  if (isnan(temperature) || isnan(humidity)) {
     server.send(500, "text/plain", "Failed to read from DHT sensor");
    return;
  }

  StaticJsonDocument<200> jsonDoc;
  jsonDoc["temperature"] = temperature;
  jsonDoc["humidity"] = humidity;

  String jsonString;
  serializeJson(jsonDoc, jsonString);

  server.send(200, "application/json", jsonString);
}

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

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }

  Serial.println("Connected to WiFi");
  dht.begin();
  server.on("/", handleRoot);
  server.begin();
  Serial.println("Server started");
}

void loop() {
  server.handleClient();
}

```

But I got error like,

```
In file included from c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Polyfills/static_array.hpp:11:0,
                 from c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Numbers/FloatTraits.hpp:14,
                 from c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Numbers/FloatParts.hpp:8,
                 from c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Json/TextFormatter.hpp:11,
                 from c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Json/JsonSerializer.hpp:7,
                 from c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Variant/ConverterImpl.hpp:7,
                 from c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson.hpp:37,
                 from c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson.h:9,
                 from C:\Users\Kuralmozhi.R\Downloads\ID_2\ID_2.ino:5:
c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Polyfills/pgmspace_generic.hpp: In instantiation of 'typename ArduinoJson6193_F1::enable_if<ArduinoJson6193_F1::is_pointer<T>::value, T>::type ArduinoJson6193_F1::pgm_read(const void*) [with T = const __FlashStringHelper*; typename ArduinoJson6193_F1::enable_if<ArduinoJson6193_F1::is_pointer<T>::value, T>::type = const __FlashStringHelper*]':
c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Deserialization/DeserializationError.hpp:85:12:   required from here
c:\Users\Kuralmozhi.R\Documents\Arduino\libraries\ArduinoJson\src/ArduinoJson/Polyfills/pgmspace_generic.hpp:15:45: error: 'const void*' is not a pointer-to-object type
   return reinterpret_cast<T>(pgm_read_ptr(p));
                                             ^

exit status 1

Compilation error: exit status 1

```

I don't know how to solve this error. Please suggest me some ideas!

---

I tried to update ESP8266. But now it shows like this,

```
Variables and constants in RAM (global, static), used 28984 / 80192 bytes (36%)
║   SEGMENT  BYTES    DESCRIPTION
╠══ DATA     1504     initialized variables
╠══ RODATA   1376     constants
╚══ BSS      26104    zeroed variables
Instruction RAM (IRAM_ATTR, ICACHE_RAM_ATTR), used 60439 / 65536 bytes (92%)
║   SEGMENT  BYTES    DESCRIPTION
╠══ ICACHE   32768    reserved space for flash instruction cache
╚══ IRAM     27671    code in IRAM
Code in flash (default, ICACHE_FLASH_ATTR), used 273120 / 1048576 bytes (26%)
║   SEGMENT  BYTES    DESCRIPTION
╚══ IROM     273120   code in flash

```

# Answer
> 4 votes
With the info from the link Fahad provided in the comments, I can only offer a guess: Your ESP8266 board definitions are outdated and the old version of the ESP8266 board definitions contains a bug.

There is an outdated URL to the ESP8266 board definition JSON floating around on the web. I *guess* you found that one. The URL still works, but is not updated anymore. Please check the version of your ESP8266 board definitions: Open the Board Manager (`Tools -> Board -> Board Manager`), search for ESP8266 and verify that the version is at least 3.1.2 (current version as of this writing; I don't know the lowest version where this bug is fixed).

If the Board Manager does not offer to update to version 3.1.2 (or later), you may need to provide the current URL to the board definitions in `File -> Preferences -> Tab "Settings" -> Additional Boards Manager URLs`. Remove the old ESP8266 URL, but don't remove URLs for *other* boards. Then try to update using the Board Manager again:

```
https://arduino.esp8266.com/stable/package_esp8266com_index.json

```

---
Tags: arduino-uno, esp8266, web-server, esp8266webserver, dht11
---


title: Encoder giving value between steps

text:
# Question
Title: Encoder giving value between steps
I'm trying to interface an encoder and a 1602 i2c display. My encoder seems to be giving an output between steps.

I have tried to make my code as simple as possible and am outputting whether the encoder rotated clockwise or counter clockwise to serial. When I rotate the knob one physical step clockwise, '++' (separated by a new line) outputs to the serial monitor when I am expecting just '+'. The same occurs when rotating counter clockwise, except with '--' instead of '++'.

Parts:

Code:

```
#define enc1 32
#define enc2 33
#define button 25
#define led 2;

int oldPos1;
int newPos1;
int newPos2;

void setup() {
  pinMode(enc1, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(enc1),encRead,CHANGE);
  pinMode(enc2, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(enc2),encRead,CHANGE);
  Serial.begin(115200);

  oldPos1 = digitalRead(enc1);
}

void encRead(){
  newPos1 = digitalRead(enc1);
  newPos2 = digitalRead(enc2);
  if(oldPos1 != newPos1){
    if (newPos1 == newPos2){
      Serial.println("+");
    }
    else{
      Serial.println("-");
    }
  }
  oldPos1 = newPos1;
}

void loop() {
  delay(10);
}

```

# Answer
This is the kind of thing that can happen when you buy cheap parts that come with no documentation whatsoever: you don't know how they are supposed to work! Many rotary encoders have two detents per pulse: if you rotate them by a single detent, you get a single transition on each pin. If using such an encoder, you would indeed expect a single `+` or `-` printed per detent. But what about the encoder you bought? You can't tell, since there is no documentation!

Quite fortunately, a helpful individual left a useful review on the product page you linked to. It can serve as an ersatz of datasheet:

> Each movement of the spindle from one detent to the next results in the encoder1 and encoder2 pins going through multiple transitions, not a single one (as you might expect).
>
> Assuming that you have tied the encoder pins to (say) 5V with a resistor, a rotation between detents, will produce a set of encoder transitions. For example: 11 10 00 01 11 (clockwise) or 11 01 00 10 11 (anti-clockwise).

This explains the behavior you are experiencing.

Side note: as jsotola writes in a comment, you should remove the `enc2` `attachInterrupt()`. As your interrupt handler explicitly ignores transitions in `enc2` (it does nothing unless `enc1` changed), there is no point in interrupting the processor for those ignored transitions.
> 2 votes

# Answer
Unfortunately you did not provide a link to the data sheet of the encoder.

One physical step at the knob can generate changes on both pins. And since you have assigned the interrupt service routine to both pins, it is called two times for each physical step.

Another possible reason is "bouncing" of the mechanical contacts in this encoder. That means, that multiple pulses are generated on the change between *open* and *closed*. Therefore, change or edge interrupts are only a correct solution, if you take bouncing into account.

To investigate the issue, you can insert port pin toggles to your interrupt service routine. For example, set a pin on entry and reset it on exit. Then connect an oscilloscope or logic analyzer and compare the input signals and this output.

Oh, and it is never a good idea to put serial output in an interrupt service routine. Depending on the amount of sent data and the chosen baudrate, this output will block the routine for several milliseconds. During this time, the same interrupt is not serviced, and can be skipped in case of multiple triggers.
> 1 votes

---
Tags: rotary-encoder
---


# Question
Title: Whether my board analog pins shorted? I see same input on all
I am puzzled. I just connected 3.3 V input to the Analog pin A5 of the Arduino UNO. On the script, I am reading all the input pins. Surprizingly, all the pins are giving voltage as that of A5 pin. This made me think whether all of them shorted?

code:

```
int a0_analogPin = A0;
float a0_val = 0;
int a1_analogPin = A1;
float a1_val = 0;
int a2_analogPin = A2;
float a2_val = 0;
int a3_analogPin = A3;
float a3_val = 0;
int a4_analogPin = A4;
float a4_val = 0;
int a5_analogPin = A5;
float a5_val = 0;

void setup() {
  Serial.begin(9600);           //  setup serial
  pinMode(a0_analogPin,INPUT);
  pinMode(a1_analogPin,INPUT);
  pinMode(a2_analogPin,INPUT);
  pinMode(a3_analogPin,INPUT);
  pinMode(a4_analogPin,INPUT);
  pinMode(a5_analogPin,INPUT);
  Serial.println("A0_val,A1_val,A2_val,A3_val,A4_val,A5_val");
}

void loop() {
  a0_val = analogRead(a0_analogPin)*5.0/1023.0;  // read the input pin
  Serial.print(a0_val);          // debug value
  Serial.print(",");
  a1_val = analogRead(a1_analogPin)*5.0/1023.0;  // read the input pin
  Serial.print(a1_val);
  Serial.print(",");
  a2_val = analogRead(a2_analogPin)*5.0/1023.0;  // read the input pin
  Serial.print(a2_val);
  Serial.print(",");
  a3_val = analogRead(a3_analogPin)*5.0/1023.0;  // read the input pin
  Serial.print(a3_val);
  Serial.print(",");
  a4_val = analogRead(a4_analogPin)*5.0/1023.0;  // read the input pin
  Serial.print(a4_val);
  Serial.print(",");
  a5_val = analogRead(a5_analogPin)*5.0/1023.0;  // read the input pin
  Serial.println(a5_val);
}

```

Board:

Serial Monitor:

# Answer
Most of your analog pins are not connected to anything. In electrical engineering, that's called "floating". It means they have no reference to anything and thus their value can be anything.

Basically their value is determined by static electricity. Moving your hands near the pins or moving them away may be enough to change the value you read.

It could be that your "oscilloscope view" actually shows that nicely. One pin gets the voltage immediately (`value 6`) and through static electricity, the other pins slowly take that value as well (`value 1`, `value 2`, ...). Probably the steepest curve of those is closest to the pin that is high and the most shallow curve is furthest away. Your observations may vary depending on humidity and temperature, since that makes static electricity spread faster or slower.

Solution: don't let your pins float. Connect them to a defined value, e.g. ground if you want them to have a predictable value.
> 2 votes

# Answer
You are seeing crosstalk between the analog input channels. In the datasheet of the microcontroller you can see the analog input circuitry. See the capacitor labeled “CS/H”? This is the “sample and hold” capacitor. Its job is to hold the voltage being read while the ADC performs the conversion. When you measure channel A5, you are charging this capacitor to 3.3 V. Then, when you switch to a floating input, the capacitor has no path to discharge, and you end up measuring the same voltage.

Actually, you do not measure exactly the same voltage. The reason is that each input pin has a parasitic capacitance. When you switch from A5 to A0, the charge in CS/H splits between this capacitor and the stray capacitance of the pin A0. Then, you switch to A1 and the remaining charge is split between CS/H and the stray capacitance of A1, and so on. Eventually, when you come back to A5, you charge again CS/H to the full 3.3 V and the cycle starts again. The net effect is that you are progressively moving charges between the successive pins. This is why the curves look like exponential relaxations, where each successive pin charges more slowly than the preceding one.

The solution, as already written in other answers, is to avoid leaving the pin floating. The datasheet recommends making sure the connected source has an impedance no larger than 10 kΩ.
> 2 votes

---
Tags: arduino-uno, board
---