title: Just one more pin!

text:
# Question
Title: Just one more pin!
I have an Arduino project to control a motor's speed at 3 levels, indicated by 3 LEDs, so level 1 is speed 1 and LED 1, and so on for levels 2/3.

Also, I added a low-battery voltage indicator to monitor the battery level.

I am going to use an ATtiny45, which has 8 pins(Vcc, GND, 1 analog pin, 5 digital pins). The project needs 6 digital pins and 1 analog pin, so only one more pin is needed.

I do not want to use an expander or I2C, as they will make the project more complex, and it is only one pin!

I can use a larger microcontroller but it would be the last choice.

Here is my project's diagram and code:

```
//********************************************^************************************************
//  https://forum.arduino.cc/t/control-motor-speed-with-npn-and-push-button-no-driver/1184925
//
//
//
//  Version    YY/MM/DD    Comments
//  =======    ========    ====================================================================
//  1.00       20/23/02    Running code
//  1.10       20/23/03    Added motor and LEDs OFF if switch pressed for >= 3 sec.
//
//
//

#define PRESSED            HIGH
#define RELEASED           LOW

#define ENABLED            true
#define DISABLED           false

#define LEDon              HIGH
#define LEDoff             LOW

#define MOTORoff           0

#define lipo               A0

float lipoV = 0;

//GPIOs
const byte Button        = 2;
const byte ledpin        = 3;
const byte ledpin1       = 4;
const byte ledpin2       = 5;
const byte Motor         = 9;
const byte heartbeatLED  = 13;
const byte Red           = 6;

//Variables
byte lastButton          = RELEASED;
byte currSwitch;

int Speed_Level;

bool bCheckingSwitch     = DISABLED;

//timing stuff
unsigned long heartbeatTime;
unsigned long switchesTime;
unsigned long threeSecondTime;

//                                      s e t u p ( )
//********************************************^************************************************
void setup()
{
  pinMode(Button, INPUT);
  pinMode(lipo, INPUT);

  pinMode(ledpin, OUTPUT);
  pinMode(ledpin1, OUTPUT);
  pinMode(ledpin2, OUTPUT);
  pinMode(Motor, OUTPUT);
  pinMode(heartbeatLED, OUTPUT);
  pinMode(Red, OUTPUT);

} //END of   setup()

//                                       l o o p ( )
//********************************************^************************************************
void loop()
{

  //************************************************              T I M E R  heartbeatLED

  //is it time to toggle the heartbeat LED ?
  if (millis() - heartbeatTime >= 500ul)
  {

    //restart this TIMER
    heartbeatTime = millis();

    //toggle the heartbeat LED
    if (digitalRead(heartbeatLED) == HIGH) digitalWrite(heartbeatLED, LOW);
    else digitalWrite(heartbeatLED, HIGH);
  }

  //************************************************              T I M E R  check switches
  //is it time to check our switches ?
  if (millis() - switchesTime >= 50ul)
  {
    //restart this TIMER
    switchesTime = millis();

    checkSwitches();
  }

  //************************************************              T I M E R  three seconds
  //if enabled, is it time to turn things OFF ?
  if (bCheckingSwitch == ENABLED && millis() - threeSecondTime >= 2000ul)
  {
    //we are finished with this TIMER
    bCheckingSwitch = DISABLED;

    //restart the sequence
    Speed_Level = -1;

    analogWrite(Motor, MOTORoff);
    digitalWrite(ledpin, LEDoff);
    digitalWrite(ledpin1, LEDoff);
    digitalWrite(ledpin2, LEDoff);
    digitalWrite(Red, LEDoff);
  }

} //END of   loop()

//                               c h e c k S w i t c h e s ( )
//********************************************^************************************************
void checkSwitches()
{
  byte state;

  //************************************************              Button
  state = digitalRead(Button);

  //has there been a state change in the switch ?
  if (lastButton != state)
  {
    //update to the new state
    lastButton = state;

    //*******************************
    if (state == PRESSED)
    {
      //enable the TIMER
      bCheckingSwitch = ENABLED;

      //start the TIMER
      threeSecondTime = millis();
    }

    //*******************
    //the switch was released
    else
    {
      //disable the TIMER
      bCheckingSwitch = DISABLED;

      Speed_Level++;
      lipoV = analogRead(lipo);

      //battery checker
      if(lipoV < 680){
        digitalWrite(Red,LEDon);
      }

       else
       {
        digitalWrite(Red,LEDoff);

       }

      //don't go over 3
      if (Speed_Level >= 4)
      {
        Speed_Level = 0;
      }

      //*******************
      if (Speed_Level == 1)
      {
        analogWrite(Motor, 50);
        digitalWrite(ledpin, LEDon);
        digitalWrite(ledpin1, LEDoff);
        digitalWrite(ledpin2, LEDoff);
      }

      //*******************
      else if (Speed_Level == 2)
      {
        analogWrite(Motor, 75);
        digitalWrite(ledpin, LEDoff);
        digitalWrite(ledpin1, LEDon);
        digitalWrite(ledpin2, LEDoff);
      }

      //*******************
      else if (Speed_Level == 3)
      {
        analogWrite(Motor, 100);
        digitalWrite(ledpin, LEDoff);
        digitalWrite(ledpin1, LEDoff);
        digitalWrite(ledpin2, LEDon);
      }

      //*******************
      else
      {
        analogWrite(Motor, MOTORoff);
        digitalWrite(ledpin, LEDoff);
        digitalWrite(ledpin1, LEDoff);
        digitalWrite(ledpin2, LEDoff);
        digitalWrite(Red,LEDoff);
      }

  }

}
}//END of   checkSwitches()

//********************************************^************************************************

```

Can I use tA0 as input and output at the same time like this?

Or can I reduce the LED pins, meaning use 1 pins for 2 LEDs?

# Answer
As a (slightly hacky and binary :) ) suggestion, you could use just two LEDs and free up a pin with the following...

Level 1 - LED 1 on, LED 2 off

Level 2 - LED 1 off, LED 2 on

Level 3 - LED 1 on, LED 2 on

This is a really simple change to your current set up and code

Alternatively (as suggested by @dandavis) use a set of 3 neopixels and drive from just 1 pin
> 4 votes

# Answer
You may try charlieplexing your LEDs. Using only 3 digital pins you can drive up to 6 LEDs. A web search for “charlieplexing Arduino” should get you started.
> 2 votes

---
Tags: led, pins
---


# Question
Title: Please help me with my project of water pump relay switching too fast
I have some problems with my project.

I'm using a water level sensor with two outputs, a 5V fan and a water pump. Here's the wiring .

What I want to do with this project is:

1. When the water reaches 2 cm, then the water pump is on while the fan is off.
2. When the water is less than 2 cm, then the water pump is off and fan is on.

The problem is, when the water is below the threshold, the sensor reading is quite unstable, thus making the relay switching too fast (see the video).

How to eliminate this problem?

```
#include <Wire.h>
#include <Blynk.h>
#include <LiquidCrystal_I2C.h>
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

//Initialize the LCD display
LiquidCrystal_I2C lcd(0x27, 16, 2);
char auth[] = "xxx";//Enter your Auth token
char ssid[] = "xxx";//Enter your WIFI name
char pass[] = "xxx";//Enter your WIFI password
BlynkTimer timer;

#define pinSensor A0
#define PIN_RELAY_1  D3
#define PIN_RELAY_2  D4
const int startThreshold = 2; // pumping shall start at startThreshold [cm] and above
const int stopThreshold  = 1; // pumping shall start at stopThreshold  [cm] and below

int sensorValue = 0; // sensor reading integer
float tinggiAir = 0; // height of water
float sensorVoltage = 0; // voltage sensor
int nilaiMax = 686; // max value of sensor after fully drowning it in water
float panjangSensor = 4.0 ; // sensor's height in cm

enum StatusType {CHECKLEVEL, LEVELHIGH, PUMPING};
StatusType status = LEVELHIGH;   // Let's start with LEVELHIGH to check level and set the display correctly

void setup() {
  Serial.begin(115200);
  lcd.begin();
  Blynk.begin(auth, ssid, pass, "blynk.cloud", 80);
  lcd.backlight();
  pinMode(PIN_RELAY_1, OUTPUT);
  pinMode(PIN_RELAY_2, OUTPUT);
  digitalWrite(PIN_RELAY_1, LOW);
  digitalWrite(PIN_RELAY_2, LOW);
  lcd.setCursor(0, 0);
  lcd.print("Water level");
  lcd.setCursor(4, 1);
  lcd.print("Monitoring");
  delay(1000);
  lcd.clear();
  timer.setInterval(100L, wLevel);
}
void wLevel() {
   sensorValue = analogRead(pinSensor);
  tinggiAir = sensorValue*panjangSensor/nilaiMax;
  sensorVoltage = sensorValue*5.0/686;
}

void loop() {
      Blynk.run();
     timer.run();
     handleStatus();
}

void handleStatus() {
  switch (status) {
    case CHECKLEVEL:
      // Wait for level above threshold
      if (tinggiAir >= startThreshold) { // if wlevel more than startThreshold [cm], then
        status = LEVELHIGH;
        Serial.println("LEVELHIGH");
      }
      break;
    case LEVELHIGH:
      levelIsHigh();
      break;
    case PUMPING:
      if (tinggiAir < stopThreshold) { // if wlevel less than stopThreshold [cm] (use hysteresis!) then
        levelIsLowAgain();
        status = CHECKLEVEL;
        Serial.println("CHECKLEVEL");
      }
      break;
  }
  displayValues();
}

void displayValues() {
  static int oldSensorValue = -1; // variable untuk menampung nilai baca dari sensor dalam bentuk integer
  float oldTinggiAir = -1; // variabel untuk menampung ketinggian air
  float oldSensorVoltage = -1; // untuk menampung nilai ketinggian air

  if (oldSensorValue != sensorValue ||
      oldTinggiAir   != tinggiAir   ||
      oldSensorVoltage != sensorVoltage) {
    Serial.print("Sensor Value = ");
    Serial.println(sensorValue);
    Serial.print("Sensor Voltage = ");
    Serial.println(sensorVoltage);
    Serial.print("Tinggi Air = ");
    Serial.println(tinggiAir);
    Serial.println();
    // Display ke LCD
    lcd.setCursor(0, 0);
    lcd.print("WLevel:");
    lcd.print(tinggiAir);
    lcd.setCursor(12, 0);
    lcd.print("cm");
    oldSensorValue = sensorValue;
    oldTinggiAir   = tinggiAir;
    oldSensorVoltage = sensorVoltage;
    Blynk.virtualWrite(V0, tinggiAir);
  }
}
void levelIsHigh() {
  digitalWrite(PIN_RELAY_1, HIGH);
  digitalWrite(PIN_RELAY_2, LOW);
  lcd.setCursor(0, 1);
  lcd.print("F:OFF P:ON");
  Blynk.logEvent("wlevel", "wLevel more than 2cm");
  status = PUMPING;
  Serial.println("PUMPING");
}

void levelIsLowAgain() {
  digitalWrite(PIN_RELAY_1, LOW);
  digitalWrite(PIN_RELAY_2, HIGH);
  lcd.setCursor(0, 1);
  lcd.print("F:ON P:OFF");
  status = CHECKLEVEL;
  Serial.println("CHECKLEVEL");
}

```

# Answer
> 4 votes
The problem lies in the specification itself. According to your rules, what should the pump do if the water level is *exactly* 2 cm? Granted, there is no such thing as an *exact* physical measurement. But you have to realize that *every* measurement system is noisy. Noise is a fact of life you have to cope with when playing with hardware. You may try to make it smaller (by filtering), but it will always be there. Now the question is: what should the pump do if the difference between the water level and the required 2 cm is less than the noise amplitude?

The standard solution, as suggested by KIIV, is to implement some hysteresis. You define *two* thresholds: one for turning the pump on and another, lower threshold for turning it off. When the readings are in between these two thresholds, you live the pump alone, in whatever state it was before.

In pseudo-code:

```
const float low_threshold = 1.9;
const float high_threshold = 2.1;

void loop() {
    float water_level = get_level_reading();
    if (water_level < low_threshold)
        turn_pump_off();
    if (water_level > high_threshold)
        turn_pump_on();
}

```

If the difference between these thresholds is larger than the noise amplitude, noise will not disturb your system.

---
Tags: esp8266, relay, switch, iot, delay
---


# Question
Title: I'm planning on using 2 arduino boards for my project. Should I use 2 voltage regulators for project or use 1 for both?
For context, my first board would contain a motor circuit with an L298N motor driver while my second contains a controlled heating system that uses 2 relays with PTC heating elements, DHT11 sensor, I2C LCD display, and 1 12V exhaust fan.

My input would be a 12V DC power adapter and I'm going to use it to run the motor, the fan, and the 2 heating elements.

Since I want to minimize the chances of my boards from overheating, I want to reduce the input voltage for my board to around 7V, so I want to integrate a voltage regulator circuit.

Should I include 2 voltage regulator circuits or should just utilize 1 for both boards?

# Answer
If you want an external voltage regulator, one should be plenty. In that case I would regulate down to 5V (not 7V) and connect that to the 5V pin on the board.

An alternative might be to just run the 12V from the battery through a diode or two, thus dropping 0.7V for each diode. Use a diode that can handle a reasonable amount of current, eg. 1N4004. Then you would still connect it to the normal "power input" socket (not the 5V pin).

I assume that the heating, motors, etc., are not being powered by the Arduino board, but directly from the battery via some sort of switching, like a MOSFET or a relay.
> 0 votes

# Answer
I would use a buck or SEPIC regulator and feed Vin on each of the Arduino with about 7.5V from the one regulator. I prefer using Vin because of the additional filtering I get. Also be sure you are using appropriate drivers for your loads, such as relays or MOSFETs.

Consider replacing the L298N with a newer part, that will lose about 3V on the motor leads which is burnt up as heat in the device. There are many others that use MOSFET outputs which will drop less them 0.2 volts.
> 0 votes

---
Tags: arduino-uno, power, voltage
---


# Question
Title: Use TCC1 timer to generate PWM on personnal board built with SAMD21E18A
I'm trying to generate a PWM signal from `TCC1`. I have a personnal board built with `SAMD21E18A`. I want to use pin 27 `PA30`, in my `variant.cpp` I have this line:

```
{ PORTA, 30, PIO_PWM, PIN_ATTR_DIGITAL|PIO_SERCOM, No_ADC_Channel, NOT_ON_PWM, TCC1_CH0, EXTERNAL_INT_10 }, // SWCLK

```

I understand I can use `TCC1_CH0` on this pin with `PIO_TIMER`. Here is what I've tried at the end of my setup:

```
  pinPeripheral(27, PIO_TIMER);
  pinMode(27, OUTPUT);

  ....

  Tcc* TC = (Tcc*)GetTC(TCC1_CH0);
  TC->CTRLA.reg &= ~TCC_CTRLA_ENABLE;
  TC->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV1;
  TC->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
  TC->PER.reg = 255;
  TC->CC[0].reg = 128;
  TC->CTRLA.reg |= TCC_CTRLA_ENABLE;

```

But it's not working: I have nothing on my pin.

Edit: I've also tried this in my setup:

```
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(TCC1_GCLK_ID) |
                     GCLK_CLKCTRL_GEN_GCLK0 |
                     GCLK_CLKCTRL_CLKEN;
  while (GCLK->STATUS.bit.SYNCBUSY);

  Tcc* TC = (Tcc*) TCC1;
  TC->CTRLA.reg &= ~TCC_CTRLA_ENABLE;

  TC->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM;

  TC->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV1 |
                   TCC_CTRLA_RUNSTDBY;

  PORT->Group[PORTA].PINCFG[30].bit.PMUXEN = 1;
  PORT->Group[PORTA].PMUX[15].reg = PORT_PMUX_PMUXE_E;

  TC->CC[0].reg = 1000;
  TC->CC[1].reg = 4000;

  // Activer le timer
  TC->CTRLA.reg |= TCC_CTRLA_ENABLE;
  while (TC->SYNCBUSY.bit.ENABLE);

```

I have something on my oscilloscope, but the signal seems not to be good, HIGH signal is very very quick and low signal very long.

# Answer
> 1 votes
For example, settings for ATSAMR21G18A (it is similar to you MCU), PA08 PWM:

Pin init:

```
// GPIO PA08 PWM (DO)
PORT->Group[0].PINCFG[8].reg = PORT_PINCFG_PMUXEN;
PORT->Group[0].PMUX[8/2].bit.PMUXE = PORT_PMUX_PMUXE_E_Val; // TCC0/WO[0]

```

Timer init:

```
void timer0_init()
{
    GCLK->CLKCTRL.reg =   GCLK_CLKCTRL_ID_TCC0_TCC1 // Gen Clk Sel ID TCC0_TCC1
                | GCLK_CLKCTRL_GEN_GCLK0    // Generic clock generator 0
                | GCLK_CLKCTRL_CLKEN;       // Clock Enable

    PM->APBCSEL.reg = PM_APBCSEL_APBCDIV_DIV1;      // Divide by 1
    PM->APBCMASK.reg |= PM_APBCMASK_TCC0;           // TCC0 APB Clock Enable

    TCC0->WAVE.reg = TCC_WAVEB_WAVEGENB_NPWM;

    TCC0->PER.reg = 80; //TCC0/WO[0] PWM 100kHz DT=50%
    TCC0->CC->reg = 40;

    TCC0->CTRLA.reg = TCC_CTRLA_CPTEN0 | TCC_CTRLA_ENABLE;  // Enable
}

```

---
Tags: pwm, timers, arduino-zero
---


# Question
Title: How to compile without adding the bootloader?
I'm using a standalone atmega328p with a 16MHz crystal.

I'm programming it via `avrdude` on a raspberry pi, using the SPI and RESET pins.

When I compile my program, this is what I see at the end of the output:

```
----------------
Device: atmega328p

Program:    4152 bytes (12.7% Full)
(.text + .data + .bootloader)

Data:        253 bytes (12.4% Full)
(.data + .bss + .noinit)

```

As far as I understand, the bootloader is used to program the chip via UART, which I do not need(?). I'm assuming that the bootloader is still being compiled because of the output above containing `.bootloader` in the program part.

My program is compiled using the arduino SDK, with the following `Makefile`

```
ARDUINO_DIR = /usr/share/arduino
BOARD_TAG = uno

include /usr/share/arduino/Arduino.mk

```

I went through `Arduino.mk` and found this on line `1626`:

```
ifndef AVRDUDE_ISP_BURN_BOOTLOADER
    ifneq ($(strip $(BOOTLOADER_FILE)),)
        AVRDUDE_ISP_BURN_BOOTLOADER += -U flash:w:$(BOOTLOADER_PARENT)/$(BOOTLOADER_PATH)/$(BOOTLOADER_FILE):i
    endif
endif

```

Which supposedly provides an option to turn off adding the bootloader but I couldn't figure out how to use it, so I just commented the line out:

```
ifndef AVRDUDE_ISP_BURN_BOOTLOADER
    ifneq ($(strip $(BOOTLOADER_FILE)),)
        # AVRDUDE_ISP_BURN_BOOTLOADER += -U flash:w:$(BOOTLOADER_PARENT)/$(BOOTLOADER_PATH)/$(BOOTLOADER_FILE):i
    endif
endif

```

But still, after compiling i see the `.bootloader` part and the program size remains the same.

Is it possible to tell it to skip adding the bootloader?

And yes, this is completely unnecessary for my application, I just want it, I want it bad.

# Answer
> 4 votes
Seeing .bootloader section in size output doesn't mean it's really present. It just means the sum of all three is 4152 bytes.

You can check the hex file if it contains large block of data at the bootloader address space. The main program starts at the lower adresses and then there should be big gap and at the end bigger chunk of data with adresses in bootloader section (but only if you really have a bootloader).

But unless you program also BOOTRST fuse, it won't start in bootloader anyway.

Usage of `AVRDUDE_ISP_BURN_BOOTLOADER` is normal environment variable (can be also set inside of Makefile) and as it's tested for not being present so you can just check if it's not being set somewhere in Makefile

# Answer
> 2 votes
I found this question which shows that the bootloader's address space is `7800` to `7FF0`. I also confirmed that by taking a look at `atmega328p`'s bootloader hex file stored in `/usr/share/arduino/hardware/arduino/bootloaders/atmega/ATmegaBOOT_168_atmega328.hex` and indeed the first line is this:

```
:107800000C94343C0C94513C0C94513C0C94513CE1

```

*Hex file format explained here.*

So I then went back to my compiled hex file and checked whether there's anything at this address and there wasn't.

So apparently my program does not contain the bootloader.

I'm adding this as a separate answer with all the details because it took me some time to figure it out after reading KIIV's answer, credit goes to him.

# Answer
> 2 votes
I strongly doubt the compiler adds the bootloader. What that message is probably trying to tell you is that the bootloader is being included in its assumed address space.

There are various bootloaders, Optiboot is only 512 bytes. If you are programming directly (not via a bootloader) then the bootloader isn't required, of course.

If you program via SPI and set the BOOTRST flag appropriately then the processor will boot directly into your code which will save a small amount of time as the bootloader waits to see if there is any serial input for reprogramming. Plus, you get another 512 bytes for your code.

In your case, it hardly matters as the reported 4152 bytes is way short of 32 KB.

---
Tags: arduino-uno, bootloader, compile
---


# Question
Title: nrf24l01+ does not work with a battery, or very unreliably
For a project in progress, I have an Arduino UNO sending a message when a condition occurs, and a Raspberry Pi that listens to it. Both are fitted with NRF24L01+ modules with antennas.

It works perfectly when the Arduino is powered from a wall socket, for instance using a 9V / 1A power supply. But when I try it with a 9V battery (which is supposed to supply 600 mAh), the Raspberry Pi receives only 1/10 of the messages.

Could you tell me:

1. Why this happens
2. How I can solve this problem (software / wiring / capacitor / ...)
3. What would be the best way to power an Arduino whose only job is to detect that a switch closes, and emit a message over the air

Here is the code of the emitter (Arduino). And there is the code of the receiver (Raspberry Pi).

Thank you.

# Answer
According to the datasheet of another 9V battery, I should not expect more than 30 - 50 mA of constant current. This is probably the reason why.

Long story made short: One can not power a NRFL01+ reliably with a 9V battery. I'd be better off using 2xAA batteries.
> 1 votes

# Answer
Another thing to consider is that a nrf24l01+ chip at full power will potentially be pulling more current than your 5v reg can supply, try a lower power setting on the PA.
> 0 votes

# Answer
Add a 100uf capacitor between ground and 3.3v directly on the nrf breakout. They're very susceptible to noise on the power supply. I had issues with the same thing and this solved it. Also, make sure you're powering from 3.3v. Also make sure you solder the negative to the negative!
> 0 votes

# Answer
I got a similar problem while not exactly the same but it may include the solution. I have a arduino nano with the nrf24l01 with the adapter and antenna (PA LNA). Transmitter work well but the receiver only work/receive data when plug by USB to the computer, not using an external battery (by USB too). I search for hours looking for a solution (the capa, the robin nrf24 tutorial, SPI problem, power supply problem, trying with another nrf24 module...) without finding any reason for this unexpected behaviour. Then i figured out that the USB cable that i use make a big difference: two were preventing transmission, one allowing transmission (the 3 cables perfectly work to upload sketch): i was thinking to a ground plan problem due to different size of USB cable but then i check the voltage arriving on the adapter of the nrf24l01. It was 4.7V for the cables that doesn't work, 4.6 with the cable that work. Then i just bypass the arduino alimentation of the nrf24l01 by using a regulated power supply directly applied on vcc and gnd of the adapter. By manually adjusting the voltage i could trigger the transmission with 4.5 V and stops it at 4.7V. I don't know why it's work like this (defect of the 5V to 3.3V regulator of the adapter?) but that do the trick for me. I know that it looks like a very unlikely solution for you but if you are desperate after hours of research, take a minute to put a voltmeter just before the adapter to look for difference in the voltage in the condition where it works versus where it doesn't work.
> 0 votes

---
Tags: power, battery, nrf24l01+
---


title: Why my pushbutton always reads LOW?

text:
# Question
Title: Why my pushbutton always reads LOW?
This is the code I used in my project

```
void setup() {
  Serial.begin(9600);
  pinMode(6,OUTPUT);
  pinMode(7,OUTPUT);
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);
  pinMode(12,OUTPUT);
  pinMode(5,INPUT);
}
void loop() {
  Serial.println(digitalRead(5));
  if(digitalRead(5)==HIGH){
    blink(12,100);
    blink(11,100);
    blink(10,100);
    blink(9,100);
    blink(8,100);
    blink(7,100);
    blink(6,100);
    Serial.println("blink done");
  }

}
void blink(int a,int b)
{
  digitalWrite(a,HIGH);
  delay(b);
  digitalWrite(a,LOW);
  delay(b);
}

```

> Project link https://www.tinkercad.com/things/55vY18FFxDR-blinking-led-wave/editel?sharecode=xQAM80Uu6sJ-hBnLLd04KasomJ2eNNzWLgKZMARe4ig

# Answer
> 1 votes
When you press the button, you short the bottom blue (GND) and the bottom red (+5V) lines. That will in the least serious case cause your Arduino to reset, but could also damage the button, burn a wire or a capacitor, or brick your Arduino. There's some protection on the board to prevent serious damage or even injury to someone, but still you should **absolutely avoid** shorting +5V to GND.

The fix is actually quite simple: Replace the short blue wire with a large resistor, something like 10k. Then the Button will still read low when it's not pressed, but read high when it's pressed. That's called a "pull-down" resistor.

---
Tags: arduino-uno
---


# Question
Title: Best Solution to Parallel UART reads with Arduino Due
I have 4 Arduino boards pushing data over UART to 4 serial ports on the Arduino Due at `115200` baud rate.

Data format - `<Short URL>,<Number of the Node>`

Eg: `px.ht/d/mCxG,1"`

Arduino Due has 4 hardware serial ports and one native USB port. I want to interface all the 4 UART nodes to each hardware serial of the Due and then push this data onto the `SerialUSB` port which is native USB at baud rate of `2000000`.

**What did I try?**

1. Sequential read of all Serial ports - Obviously poor performance
2. Used Serial Events - For some reason never able to get the callback triggered.
3. Used some FreeRTOS library and there are a lot of data misses.

When using RTOS, the data from multiple nodes is getting mixed up and printed incorrectly. I'm looking for some efficient way to read parallel data from all UARTs without data overlap and stream data and given the MCU on Arduino Due is very powerful I don't think that's what is bottlenecking the performance.

# Answer
> 1 votes
> It seems the arduino's wrappers for serial API's are very slow

They aren't. There are some functions that depend on timeouts: these can indeed be very slow. However, if you read the ports in a *non blocking* fashion, everything should be fast. Non blocking basically means never waiting, and never trying to read more bytes than what is currently `available()`. For example:

```
const int buffer_size = 64;  // tune to taste

char buffer1[buffer_size];
int size1 = 0;
// same for buffer2, size2, etc.

void loop() {
    while (Serial1.available()) {
        char c = Serial1.read();
        if (size1 < buffer_size - 1)
            buffer1[size1++] = c;  // buffer the incoming character
        if (c == '\n') {  // found end-of-message
            buffer1[size1] = '\0';  // terminate the string
            Serial.print(buffer1);  // send through USB
            size1 = 0;  // get ready for next message
        }
    }
    // then the same for Serial2, ...
}

```

If you know a bit about object oriented programming, you can easily rewrite this in a more elegant way, with no repeated code.

---
Tags: usb, arduino-due, uart
---


# Question
Title: PROGMEM : pgm_read_float_near() equivalent for double? (Arduino Due)
I'm using an Arduino Due where double have a size of 8 bytes. In my software, I use double table const stored in prog memory, I was using an UNO before and used pgm\_read\_float\_near() to retrieve these values. What function should I use?

# Answer
> 6 votes
Arduino Due (ARM Cortex-M3) doesn't need anything like `PROGMEM` as it has access into the flash memory in the same way as into the `RAM`. The `const` qualifier is enough to keep it in program memory only.

The `AVR` based boards like `UNO` needs PROGMEM because there are different instructions for fetching data from program memory and `g++` is not very advanced in this way (some other compilers supports it directly - for example in gcc you can use \__flash and \__eeprom instead, but not in g++ as it was rejected for some reasons)

**Edit:**

Currently there are also AVRs with a new design (they are more like xmegas) and they are having flat address space (emulation) so with single pointer you can fetch RAM, FLASH, EEPROM and so on. But it's limited to the devices with smaller FLASH (all of it must fit into 64kB/16b pointers). In those cases you can just use const for global arrays and it'll be stored in FLASH (and not in FLASH and loaded into RAM upon startup like old AVRs) and string literals doesn't need P\_STR / F() macros

For example:

* Atmega4809 (nano every, uno wifi r2) and variants: 808, 809, 1608, 1609, 3208, 3209, 4808
* Attiny(2/4/8/16/32)(0/1/2)(2,4,6,7) - eg Attiny212 1616 ...
* It should be also possible on AVR16/AVR32 devices, but 64kB/128kB ones needs PROGMEM again (compiler can't optimize it into FLASH as you have only snapshot of 32kB in direct address space, but it's possible to change it - however there is also erratum about it not working properly)

# Answer
> 0 votes
For anyone looking for an equivalent, you can manually copy the bytes into a double like:

```
double pgm_read_double(const double* address) {
    double result;
    memcpy_P(&result, address, sizeof(double));
    return result;
}

```

And use `memcpy_PF` for `far` addresses. **But** know that many MCUs have access into the flash memory in the same way as into the RAM, so you don't need to use this at all.

---
Tags: progmem
---


# Question
Title: Water level Detection using Ultrasonic Sensor and arduino
I'm making a water level detector to control my motor which supplies water in water tank and for that I'm going to use ultrasonic sensor to be attached to tank lid. My question is whether the vapor arising from water inside the tank hamper the overall working of ultrasonic sensor and/or it may be damaged permanently. I can cover complete ultrasonic sensor using hot glue stick but cannot cover its diaphragm as it will block sound waves. Please suggest something.

# Answer
Majenko, agreed. Use some FM antenna cable, if you can find it. Insulate the lower end by dipping in molten heat glue. Two rods, insulated with heat shrink tubing also works well. Use LM393 dual comparator as Schmitt trigger and inverter. That will oscillate at frequency dependant on the water level. Works well, recalibrate or clean the sensor when accuracy suffers due to being too dirty. should not be necessary more than annually.
> 2 votes

# Answer
A friend of mine worked on a liquid level monitoring project, and after many iterations finally abandoned the kinds of sensors you're talking about. Ultimately he just pointed a cheap USB webcam at the thing and used OpenCV and the edge detection algorithm to find the level of the water. Then it's just a matter of doing some math using the dimensions of the container, to figure out how full it is.

If you are using a clear container and if you have the option of using a Raspberry Pi (or a PC, whatever) that can run OpenCV, you might find that option worth exploring.
> 1 votes

# Answer
Sensors exist for exactly your use case. Here is an example;

Maxbotix MB7589 Ultrasonic Sensor

I have used several of these to measure river levels. they are virtually indestructible and have all the features that you would expect;

* Temperature compensation
* Self heating to deal with humidity/condensation
* serial output
* 1mm resolution
> 0 votes

---
Tags: sensors
---


# Question
Title: How to write an integer value to an RFID tag?
I'm working on a project in which two Arduinos are to be used. Each Arduino is connected to an RFID reader. The first RFID reader should write an integer value to the tag detected, whereas the second RFID reader will read the value that was written by Arduino 1.

I'm facing a problem writing an integer value to the tag. I've found many libraries that include functions that write only strings or characters to the tag. But I need to write an integer. Can anyone help me solve this issue?

Following is code that I found and I tried to edit, so that the write and read functions accept (integer values) as the blockContent. However as expected it didn't work because those functions are defined to accept arrays.

```
/******************************************
   PURPOSE:  Learn to use the MF522-AN RFID card reader
  Created by      Rudy Schlaf for www.makecourse.com
  DATE:   2/2014
*******************************************/

/*
  This sketch uses the MFRC522 Library to use ARDUINO RFID MODULE KIT   13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT.
  The library file MFRC522.h has a wealth of useful info. Please read it.
  The functions are documented in MFRC522.cpp.

  Based on code Dr.Leong   ( WWW.B2CQSHOP.COM )
  Created by Miguel Balboa (circuitito.com), Jan, 2012.
  Rewritten by Søren Thing Andersen (access.thing.dk), fall of 2013
  (Translation to English, refactored, comments, anti collision, cascade levels.)

           This library has been released into the public domain.
*/

#include <SPI.h>//include the SPI bus library
#include <MFRC522.h>//include the RFID reader library

#define SS_PIN 10  //slave select pin
#define RST_PIN 5  //reset pin

MFRC522 rfid(SS_PIN, RST_PIN);

MFRC522::MIFARE_Key key;
char order = 49;

void setup() {
  Serial.begin(9600);        // Initialize serial communications with   the PC
  SPI.begin();               // Init SPI bus
  mfrc522.PCD_Init();        // Init MFRC522 card (in case you wonder what PCD means: proximity coupling device)
  Serial.println("Scan a MIFARE Classic card");

  // Prepare the security key for the read and write functions - all six key bytes are set to 0xFF at chip delivery from the factory.
  // Since the cards in the kit are new and the keys were never defined, they are 0xFF
  // if we had a card that was programmed by someone else, we would need to know the key to be able to access it. This key would then need to be stored in 'key' instead.

  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;//keyByte is defined in the "MIFARE_Key" 'struct' definition in the .h file of the library
  }

}

int block = 2; //this is the block number we will write into and then read. Do not write into 'sector trailer' block, since this can make the block unusable.

byte blockcontent[16] = {"SubScribe______"};//an array with 16 bytes to be written into one of the 64 card blocks is defined!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//byte blockcontent[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//all zeros. This can be used to delete a block.
byte readbackblock[18];//This array is used for reading out a block. The MIFARE_Read method requires a buffer that is at least 18 bytes to hold the 16 bytes of a block.

void loop() {
  /*****************************************establishing contact with a tag/card**********************************************************************/
  // Look for new cards (in case you wonder what PICC means: proximity integrated circuit card)
  if ( ! mfrc522.PICC_IsNewCardPresent()) {//if PICC_IsNewCardPresent returns 1, a new card has been found and we continue
    return;//if it did not find a new card is returns a '0' and we return to the start of the loop
  }

  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) {//if PICC_ReadCardSerial returns 1, the "uid" struct (see MFRC522.h lines 238-45)) contains the ID of the read card.
    return;//if it returns a '0' something went wrong and we return to the start of the loop
  }

  // Among other things, the PICC_ReadCardSerial() method reads the UID and the SAK (Select acknowledge) into the mfrc522.uid struct, which is also instantiated
  // during this process.
  // The UID is needed during the authentication process
  //The Uid struct:
  //typedef struct {
  //byte    size;     // Number of bytes in the UID. 4, 7 or 10.
  //byte    uidByte[10];            //the user ID in 10 bytes.
  //byte    sak;      // The SAK (Select acknowledge) byte returned from the PICC after successful selection.
  //} Uid;

  Serial.println("card selected");

  /*****************************************writing and reading a block on the card**********************************************************************/
  writeBlock(block, blockcontent);//the blockcontent array is written into the card block
  //mfrc522.PICC_DumpToSerial(&(mfrc522.uid));

  //The 'PICC_DumpToSerial' method 'dumps' the entire MIFARE data block into the serial monitor. Very useful while programming a sketch with the RFID reader...
  //Notes:
  //(1) MIFARE cards conceal key A in all trailer blocks, and shows 0x00 instead of 0xFF. This is a secutiry feature. Key B appears to be public by default.
  //(2) The card needs to be on the reader for the entire duration of the dump. If it is removed prematurely, the dump interrupts and an error message will appear.
  //(3) The dump takes longer than the time alloted for interaction per pairing between reader and card, i.e. the readBlock function below will produce a timeout if
  //    the dump is used.

  //mfrc522.PICC_DumpToSerial(&(mfrc522.uid));//uncomment this if you want to see the entire 1k memory with the block written into it.

  readBlock(block, readbackblock);//read the block back
  Serial.print("read block: ");
  for (int j = 0 ; j < 16 ; j++) {
    //print the block contents
    Serial.write (readbackblock[j]);//Serial.write() transmits the ASCII numbers as human readable characters to serial monitor
  }
  Serial.println("");
}

int writeBlock(int blockNumber, byte arrayAddress[]) {
  //this makes sure that we only write into data blocks. Every 4th block is a trailer block for the access/security info.
  int largestModulo4Number = blockNumber / 4 * 4;
  int trailerBlock = largestModulo4Number + 3; //determine trailer block for the sector
  if (blockNumber > 2 && (blockNumber + 1) % 4 == 0) {
    Serial.print(blockNumber);  //block number is a trailer block (modulo 4); quit and send error code 2
    Serial.println(" is a trailer block:");
    return 2;
  }
  Serial.print(blockNumber);
  Serial.println(" is a data block:");

  /*****************************************authentication of the desired block for access***********************************************************/
  byte status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  //byte PCD_Authenticate(byte command, byte blockAddr, MIFARE_Key *key, Uid *uid);
  //this method is used to authenticate a certain block for writing or reading
  //command: See enumerations above -> PICC_CMD_MF_AUTH_KEY_A = 0x60 (=1100000),    // this command performs authentication with Key A
  //blockAddr is the number of the block from 0 to 15.
  //MIFARE_Key *key is a pointer to the MIFARE_Key struct defined above, this struct needs to be defined for each block. New cards have all A/B= FF FF FF FF FF FF
  //Uid *uid is a pointer to the UID struct that contains the user ID of the card.
  if (status != MFRC522::STATUS_OK) {
    Serial.print("PCD_Authenticate() failed: ");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return 3;//return "3" as error message
  }
  //it appears the authentication needs to be made before every block read/write within a specific sector.
  //If a different sector is being authenticated access to the previous one is lost.

  /*****************************************writing the block***********************************************************/

  status = mfrc522.MIFARE_Write(blockNumber, arrayAddress, 16);//valueBlockA is the block number, MIFARE_Write(block number (0-15), byte array containing 16 values, number of bytes in block (=16))
  //status = mfrc522.MIFARE_Write(9, value1Block, 16);
  if (status != MFRC522::STATUS_OK) {
    Serial.print("MIFARE_Write() failed: ");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return 4;//return "4" as error message
  }
  Serial.println("block was written");
}

int readBlock(int blockNumber, byte arrayAddress[]) {
  int largestModulo4Number = blockNumber / 4 * 4;
  int trailerBlock = largestModulo4Number + 3; //determine trailer block for the sector

  /*****************************************authentication of the desired block for access***********************************************************/
  byte status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  //byte PCD_Authenticate(byte command, byte blockAddr, MIFARE_Key *key, Uid *uid);
  //this method is used to authenticate a certain block for writing or reading
  //command: See enumerations above -> PICC_CMD_MF_AUTH_KEY_A = 0x60 (=1100000),
  // this command performs authentication with Key A
  //blockAddr is the number of the block from 0 to 15.
  //MIFARE_Key *key is a pointer to the MIFARE_Key struct defined above, this struct needs to be defined for each block. New cards have all A/B= FF FF FF FF FF FF
  //Uid *uid is a pointer to the UID struct that contains the user ID of the card.
  if (status != MFRC522::STATUS_OK) {
    Serial.print("PCD_Authenticate() failed (read): ");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return 3;//return "3" as error message
  }
  //it appears the authentication needs to be made before every block read/write within a specific sector.
  //If a different sector is being authenticated access to the previous one is lost.

  /*****************************************reading a block***********************************************************/

  byte buffersize = 18;//we need to define a variable with the read    buffer size, since the MIFARE_Read method below needs a pointer to the variable that contains the size...
  status = mfrc522.MIFARE_Read(blockNumber, arrayAddress, &buffersize);//&buffersize is a pointer to the buffersize variable;     MIFARE_Read requires a pointer instead of just a number
  if (status != MFRC522::STATUS_OK) {
    Serial.print("MIFARE_read() failed: ");
    Serial.println(mfrc522.GetStatusCodeName(status));
    return 4;//return "4" as error message
  }
  Serial.println("block was read");
}

```

# Answer
> 0 votes
Let's say you have an array and an int.

```
unsigned char blockcontent[16];
int number = 15;

```

To save the int at position 0 of `blockcontent`, you do this:

```
memcpy(blockcontent, &number, sizeof(int));

```

If you want it at another position, do `blockcontent+offset`.

If you want to read the int from `blockcontent`, do the reverse:

```
memcpy(&number, blockcontent, sizeof(int));

```

That's all there is to it.

---
Tags: arduino-uno, rfid
---


# Question
Title: Why can't I upload a sketch by connecting directly to the serial pins?
I have an handful of fake arduino nanos. The work fine, but as an experiment, I tried to program them with a *usb serial adapter* (a real FTDI one). It doesn't work, but also, strangely, it seems to stop the bootloader from working properly too, or just puts the arduino in a mode where the `/dev/ttyUSB*` device doesn't appear, and only reappears when I burn the bootloader again

When I try to upload the sketch using the usb serial adapter, I get this:

```
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x00
Failed uploading: uploading error: exit status 1

```

Then, when I try to upload a sketch over usb again, `/dev/ttyUSB*` no longer appears when I plug in the usb cable to the normal usb jack.

However, when I can still put the sketch on using an in-circuit-programmer, and when I use the in-circuit-programmer to burn the bootloader again, `/dev/ttyUSB*` appears again, and I can upload sketches over usb again.

Is that possible? What could I be doing wrong

Here is how I connected the usb to serial adapter to the fake arduino:

(checkout https://i.stack.imgur.com/nh3d6.jpg for a bigger picture)

So basically I have connected between the arduino (left column) and the usb to serial adapter right column:

```
TX - RX
RX - TX
VIN - VCC
GND - GND
RST - 0.1uF capacitor - DTR

```

I have tried it with and without the reset pin.

The usb to serial adapter is set to 5V.

---

another clue:

If I leave the adapter and arduino connected as in the picture, but plug the usb cable into the arduino instead of the adapter, so the adapter is powered by the arduino - it still gets the error that I have shown, and stops working completely until I reburn the bootloader.

---

Does anybody have any idea why this could be happening?

---

UPDATE:

After it was pointed out, I started using the 5v pin instead of the VCC pin on the fake arduino, but the same thing keeps happening:

* burn the boot loader
* normal usb upload works
* try to upload with the serial adapter
* doesn't work
* normal usb upload no longer works until I burn the bootloader again

# Answer
> 1 votes
OK this was a combination of at least two things:

---

Main problem:

connecting the fake arduino's RST pin to the FTDI's DTR pin via a 0.1uF capacitor seems to stop it from uploading, when when you manually reset. Also when I remove it it doesn't seem to fix itself right away if you can believe it.

---

Red Herring

This was not the direct cause of this issue, but is probably a big problem for a lot of other fake arduinos out there:

When I went back to the built-in USB, `brltty`'s udev rules were claiming the CH341 as described here https://askubuntu.com/questions/1403705/dev-ttyusb0-not-present-in-ubuntu-22-04

So if you just have the simpler problem of a fake arduino not appearing, this might solve the problem for you:

```
sudo apt-get remove brltty

```

or if you need `brltty` you can just go into the udev rules that come with it and comment out this one:

```
# Device: 1A86:7523
# Baum [NLS eReader Zoomax (20 cells)]
ENV{PRODUCT}=="1a86/7523/*", ENV{BRLTTY_BRAILLE_DRIVER}="bm", GOTO="brltty_usb_run"

```

(as long as that isn't the screen reader you use - then you might just have to buy a real arduino, or make some better udev rules that recognise your screenreader from the port it's plugged into)

The reason this confused me is that when I tried to plug in to the standard usb port after failing to use the programmer, the above udev rules kicked me out. But then I think when I burned a new bootloader, because you still have to power the board from usb while the pololu is connected, I managed to have it connected without the above udev rule kicking it - and then when I tried the external FTDI again, and then plugged back in the internal CH341, the brltty udev rule claimed it, and it seemed like trying to upload over FTDI is what broke it.

# Answer
> -1 votes
It appears the boot loader does not support serial programming. You would need to change that first. Is the baud rate the same?

---
Tags: serial, bootloader, uploading, uart
---


# Question
Title: Make two LEDs fade in and out with with different PWM values
I have two UV leds, one Vf 3.3V @ 150 mA and the second one Vf 5V @ 150 mA. I need a circuit to make them fade in and out alternatively, *i.e.*, as one goes dimmer the other goes brighter and vice versa. I tried an Arduino PWM transistor approach with the Attiny85 board and the code below and it works, but I need the *ledPin2* led to work with at a lower *maxbrightness*. How can I modify the code so that I can set the *maxbrightness* for *ledPin2* to be around 25, while the *maxbrightness* for *ledPin1* remains 255 and yet both take the same time to fade in and out?

```
int ledPin1 = 0;
int ledPin2 = 4;
int minbrightness = 0;
int maxbrightness = 255;
int fadeAmount = 1;
int tim=4;

void setup()  {
   pinMode(ledPin1, OUTPUT);
   pinMode(ledPin2, OUTPUT);
}

void loop()  {
  analogWrite(ledPin1, minbrightness);
  analogWrite(ledPin2, maxbrightness);
  minbrightness = minbrightness + fadeAmount;
  maxbrightness = maxbrightness - fadeAmount;
  if (minbrightness == 0 || minbrightness == 255 ){
    fadeAmount = -fadeAmount ;
  }
  delay(tim);
}

```

# Answer
I don't think you have much choice than to come up with a sort of a counter and instead of having a single variable for the brightness of all the LEDs, you'll have to maintain a separate brightness variable for each channel which will have its own unique dimming profile. You'll then have to empirically determine how many counts it'll take for you to decrease/increase the PWM duty cycle on each separate channel (since perceived brightness isn't linear).

Something like this? The brightness of 32 and a modulo 8 was chosen to be a factor of 256, so it's more or less synced.

```
int ledPin1 = 0;
int ledPin2 = 4;
int brightnessLP1 = 0;  //begin with the LED off
int brightnessLP2 = 32; //begin with the LED on
int fadeAmount = 1;
int tim=4;

void setup()  {
   pinMode(ledPin1, OUTPUT);
   pinMode(ledPin2, OUTPUT);
}

void loop()  {
  //counter value accommodates the modulo below
  for(int brightnessCounter = 1; brightnessCounter < 257; brightnessCounter++) {

     analogWrite(ledPin1, brightnessLP1);
     analogWrite(ledPin2, brightnessLP2);
     brightnessLP1 = brightnessLP1 + fadeAmount;
     if(brightnessCounter  % 8) {
       brightnessLP2 = brightnessLP2 - fadeAmount;
     }
     delay(tim);
  }
  fadeAmount = -fadeAmount;
}

```

I'm sure you could make it cleaner or link the brightness values to the counter, but I'll leave that to you.
> 0 votes

---
Tags: programming, led, attiny85
---


title: How to use assembly in Arduino?

text:
# Question
Title: How to use assembly in Arduino?
I have been assigned a university project to make a sound/audio responsive LED using assembly language. I have already wrote C++ code in Arduino that uses the Fastled library.

How do I write working code for this project in assembly (not restricted to @rduino IDE, but preferable)? I've already tried converting my code to assembly using an online converter, but it is useless.

# Answer
The Arduino IDE is quite idiosyncratic. It won't let you work on a project that doesn't have a file with the extension “.ino”. On the other hand, it doesn't care about how much code is in that file, and you can keep it happy by creating an empty .ino file. I recommend however that you put at least a comment block in that file, in order to make things less confusing for other people who could see your project. Then you can put your assembly code alongside this empty file, in files of their own ending with the “.S” extension. These files will be preprocessed before being assembled, so you can `#include <avr/io.h>` and use the macros defined therein for the IO ports, bits, etc.

The project would look like this:

```
my_project/         # containing directory
├── my_project.ino  # comments only, to keep the IDE happy
├── my_project.S    # main assembly file
└── some_extras.S   # possibly more assembly files...

```

If the whole project is pure assembly, one of your assembly files should define a symbol called `main`, which is the entry point of the program:

```
.global main
main:
    ; code starts here

```

If you are going to mix assembly and C++, then you can define `main()` in the .ino file, and call from there your assembly routines, which should be declared as `extern "C"`:

```
extern "C" void my_assembly_routine();

int main()
{
    my_assembly_routine();
}

```

Mind the calling conventions when mixing asm and C++ though.

If you are going to use the Arduino core library, then you should define `setup()` and `loop()` instead of `main()`. The Arduino core will then provide it's own `main()`, which takes care of its initialization.

If you are going to write mostly C++, with only some assembly sprinkled here and there, *inline* assembly could be a better option. C.f. Michel Keijzers' answer.
> 10 votes

# Answer
Sorry.

The main learning effect of this exercise is "Don't do it". You won't beat the c++ compiler regarding performance (speed). But you will run into more errors than you can imagine.

The only purpose of manual assembler language inside c/c++ is to add nanosecond timing by adding some `asm("nop");` statements to wait a controlled small number of cpu clock cycles. @Michel Keijzers' examples are already implemented. Even in Arduino's convenience environment.

IMO it's more challenging to get beyond Arduino programming by going directly to the MCU's hardware level, dealing with Timers, other MCU components, Registers etc. directly. In C/C++ of course. There you learn that there's much more that can be done beyond the Arduino environment.

Or: Look at compiled results via `avr-objdump` to learn how C++ is compiled to machine code by experts. Very eventually, you might notice how you could help the compiler optimizing.
> 1 votes

# Answer
Re: "The main learning effect of this exercise is "Don't do it". You won't beat the c++ compiler..." I agree with Edgar Bonet: (1) Arduino is about learning, including learning Assembler programming, hardware, etc. And ... (2) Yes, you can beat the C++ compiler with a little practice. E.g. the GNU tool-chain can input the C++ program and output the corresponding Assembler. This can be very instructive for learning Assembler. You can then hand-craft any bit of that code...make it faster, or smaller --o-0--
> 1 votes

# Answer
You have to use the `asm` keyword, like:

```
asm("sei \n")

```

In your case it is advised to use defines, e.g.

```
#define CLI()          asm("cli \n")
#define noInterrupts() cli()

#define SEI()          asm("sei \n")
#define interrupts()   sei()

```

See more info at arduino-inline-assembly-tutorial-1.
> 0 votes

---
Tags: led, assembly
---


# Question
Title: Why isn't pin 6 on my Adafruit Feather RP2040 being sent high when I ask it to?
I have an Adafruit Feather RP2040 (pinouts) connected via pin 6 to a relay. The code (below) triggers the relay when a separate color sensor returns "enough" red values.

The color sensor works (confirmed by the serial print statements); the on-board LED (connected internally to pin 13) lights up when it should; but I don't get any voltage on pin 6 when I should. I'm testing the voltage with a standard multimeter. If I move my connecting wire from pin 6 to pin 13, I get voltage (and the relay activates). Why doesn't pin 6 get voltage? What else can I do to diagnose the issue?

Software versions:

Code:

```
// copied & modified from the source at:
// https://github.com/adafruit/Adafruit_APDS9960/blob/master/examples/color_sensor/color_sensor.ino

#include "Adafruit_APDS9960.h"
Adafruit_APDS9960 apds;

// the pin on the feather that we're using to talk to the relay
#define PIN_TO_RELAY 6

#define BUCKET_FULL_RED 50

void setup() {
  // enable Serial communication
  Serial.begin(115200);

  // try to start the color sensor
  if(!apds.begin()) {
    Serial.println("failed to initialize device! Please check your wiring.");
  }
  else {
    // Assume success
    // Serial.println("Device initialized!");

    // we want color readings
    apds.enableColor(true);
  }

  // define the relay pin as an OUTPUT pin
  pinMode(PIN_TO_RELAY, OUTPUT);
  // start with the relay "open" AKA not running the pump
  digitalWrite(PIN_TO_RELAY, LOW);

  // use the built-in LED as an external signal for "pumping"
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  // create some variables to store the color data in; unused, except for 'red'
  uint16_t red, green, blue, clear;

  // for checking the relay pin state
  int relay_pin_state = 0;

  // for extra printing
  int debug = 1;

  // wait for color data to be ready
  while (!apds.colorDataReady()) {
    delay(5);
  }
  // get fresh data; we only care about the red, but we have to read them all
  apds.getColorData(&red, &green, &blue, &clear);

  if (debug) {
    Serial.print("current red value is:"); Serial.println(red);
  }

  if (debug > 2) {
    relay_pin_state = digitalRead(PIN_TO_RELAY);
    if (relay_pin_state == HIGH) {
      Serial.println("steadystate: Relay pin is HIGH / enabled");
    } else {
      Serial.println("steadystate: Relay pin is LOW / disabled");
    }
  }

  if (red > BUCKET_FULL_RED) {
    if (debug) {
      Serial.println("start the pump (for 5 sec)");
    }

    // light up the built-in LED
    digitalWrite(LED_BUILTIN, HIGH);
    // "close" the relay to turn on the pump
    digitalWrite(PIN_TO_RELAY, HIGH);

    if (debug > 2) {
      relay_pin_state = digitalRead(PIN_TO_RELAY);
      if (relay_pin_state == HIGH) {
        Serial.println("pumping: Relay pin is HIGH / enabled");
      } else {
        Serial.println("pumping: Relay pin is LOW / disabled");
      }
    }

    // wait for a while for the pump to do its work
    // 5 sec in ms; TODO: eventually circa 4 min
    delay(5 * 1000);

    if (debug) {
      Serial.println("stop the pump");
    }

    // turn off the built-in LED
    digitalWrite(LED_BUILTIN, LOW);
    // "open" the relay to turn off the pump
    digitalWrite(PIN_TO_RELAY, LOW);
  }
  // no need to cycle quickly; wait 1 sec in ms
  delay(1 * 1000);
}

```

I just looked more closely at the pinouts page again, and was surprised to see the hole labeled "6" on the front is labeled "GP08" on the back, which corresponds to "GPIO8" in https://learn.adafruit.com/assets/107203. I wonder if I'm sending the "D4" pin HIGH ("GPIO6") instead of the one I'm expecting.

# Answer
Turns out I misled you with my ignorance. I took for granted that the thing labeled "6" on the front was in fact Pin 6, but it's not:

Indeed, if I turn it over, that's "GP08":

... and so my code needs to use pin 8, not pin 6.

User timemage pointed out similar confusion on a recent post: D1 mini ESP8266 no sound on speaker where the silk-screened label on the front of the board did not match the actual pin number. They additionally point out a file that I would have never stumbled upon, but demonstrates this mapping: https://github.com/adafruit/circuitpython/blob/16c8c9a739cfe0db2c712696eb340de2d7944d41/ports/raspberrypi/boards/adafruit\_feather\_rp2040/pins.c#L24, namely:

```
    { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO2) },
    { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO3) },
    { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO7) },
    { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO8) },  /* right here */
    { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO9) },
    { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO10) },

```

The description of the pinout still contains some misleading information, in my opinion:

> D6/GP08 - Digital I/O pin 6. It is also SPI1 MISO, UART1 TX, I2C0 SDA and PWM4 A.

Here, it seems to me that this spot is still being called "pin 6".
> 3 votes

# Answer
The pin labeled as GP06 on the bottom side of the PCB is labeled as D4 on the top side of the PCB. It is pin 4.

from https://learn.adafruit.com/adafruit-feather-rp2040-pico/pinouts

> D4/GP06 - Digital I/O pin 4. It is also SPI0 SCK, I2C1 SDA and PWM3 A.
> 2 votes

---
Tags: pins, feather
---


# Question
Title: How to find out all #define used by arduino-cli in compile?
How to find out all `#define` used by `arduino-cli` in compile?

I had seen something some time ago, but I cannot find it again. I think that it was some option somewhere, and the result was that the compile did not end normally, but some generated file contained lots of useful and lots of obscure defined names.

I would like to find everything that's defined in my program, which I want to write, compile, and then run on different Arduinos, but it sometimes need different Serial to be used, different pin assignments, different internal buffer sizes and so on.

And I would like to organize the differences better, than just put all and everything to one big `#ifdef` \- `#endif` for each extra platform.

Something like:

* if it does not have `Serial` but `Serial1`, `#define Serial Serial1`
* if it has 2kB RAM or less, set MY\_BUF\_SIZE to 10; if it has less than 3kB use 30, else use 100.
* but if it is `Micro Pro`, use this pin assignment, else if it is `Nano Every` use that, else issue error/warning for user, that pins need to be assigned.

And many others...

# Answer
> 3 votes
I am not familiar with arduino-cli. If you can manage to find the `g++` command line it uses for compiling your sketch, then you can get the list you are looking for by using a modified version of that command:

* add the options `-E -dM`
* find the option `-o output_file` and change the name of the output file to something more appropriate.

---

**Edit**: Following a suggestion by @gilhad, you can build the required command line by piping the output of arduino-cli through `sed`:

```
arduino-cli compile | \
    sed -n '/g++.*\.ino\.cpp\.o/{s/-MMD//;s/-o .*/-E -dM -o defines.dump/;p}'

```

---
Tags: compile, arduino-cli
---


# Question
Title: Reading serial data from Arduino in Python continually
Using a stepper motor and a range finder (TFLuna), I am trying to build a "Lidar" (like a Radar, but with light). Here is the algorithm:

* Turn motor one step, calculate angle, measure distance to whatever it hits, giving polar coordinates;
* Calculate Cartesian coordinates and send to Python;
* Collect a few hundred measurements and show the scatter plot.

This works, but only if I restart the sketch and the Python routine at the same time. After I collected all the data for one plot, I cannot restart the Python script to collect another round of data - it shows that there is no data in waiting. Also, the Arduino script never hangs due to the buffer getting full (as Python has stopped reading).

How can I make it so that the Arduino and the motor do their thing (swinging back and forth 180º, looking at stuff), and I am able to collect an amount of data in Python intermittently -- whenever I choose to restart the script one more time?

Here is the code. First, Arduino. "count" is the number of steps by which the motor has rotated; tflI2C is the range-finder object.

```
#include <Stepper.h>
#include <Arduino.h>
#include <Wire.h>        // Instantiate the Wire library
#include <TFLI2C.h>      // TFLuna-I2C Library v.0.1.1
#include <math.h>

TFLI2C tflI2C;
int16_t  tfDist;    // distance in centimeters
int16_t  tfAddr = TFL_DEF_ADR;  // Use this default I2C address

const int stepsPerRevolution = 2048;  // change this to fit the number of steps per revolution

// initialize the stepper library on pins 8 through 11:
Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);
int stepCount = 0;         // number of steps the motor has taken

void serialFlush(){
  while(Serial.available() > 0) {
    char t = Serial.read();
  }
}

void setup() {
  // initialize the serial port:
  Serial.begin(115200);
  Wire.begin();           // Initalize Wire library
  myStepper.setSpeed(10);
  //myStepper.step(stepsPerRevolution/2);
  //delay(1000);
  //myStepper.step(-stepsPerRevolution/2);
}

void coordinates(int count){
  struct Polar {
    float angle;
    int16_t distance;
  } pPoint;
  struct Cartesian {
    float xCoord;
    float yCoord;
  } cPoint;

  float angle = count*(2.0*PI)/stepsPerRevolution;
  byte flag = 0;
  //Serial.flush();
  while (Serial.availableForWrite() < sizeof(struct Cartesian)){}
  if(tflI2C.getData(tfDist, tfAddr)){
    pPoint.angle = angle + PI/2.0;
    pPoint.distance = tfDist;
    cPoint.xCoord = pPoint.distance * cos(pPoint.angle);
    cPoint.yCoord = pPoint.distance * sin(pPoint.angle);
    if (pPoint.distance <= 50 ){
      Serial.write((char*)&cPoint, sizeof(struct Cartesian));
    }
  }
  return;
}

void loop() {
  // step one step:
  for (int k=0; k<stepsPerRevolution/4; k++){
    myStepper.step(1);
    coordinates(stepCount);
    stepCount += 1;
    delay(10);
  }
  for (int k=0; k<stepsPerRevolution/2; k++){
    myStepper.step(-1);
    coordinates(stepCount);
    stepCount -= 1;
    delay(10);
  }
  for (int k=0; k<stepsPerRevolution/4; k++){
    myStepper.step(1);
    coordinates(stepCount);
    stepCount += 1;
    delay(10);
  }
  delay(5000);
}

```

and here is Python:

```
ardu = serial.Serial('/dev/cu.usbserial-1460', baudrate=115200, timeout=.1)
radarImage = []
structSize = struct.calcsize("ff")
ardu.reset_input_buffer()

i = 0;
while True:
    if ardu.in_waiting >= structSize:
        arduRead = ardu.read(structSize)
        point = list(struct.unpack("ff",arduRead))
        if i <= 10:
            print(point)
        radarImage.append(point)
        i += 1
    else:
        pass
    if i > 2000:
        break
ardu.close()

```

Here is a sample from a "first round" data collection. Yes, my desk is messy...

# Answer
> 2 votes
> I am puzzled why the Arduino code isn't simply stopping at "Serial.availableForWrite()" when I stop reading data on the Python side -- it keeps on running.

This depends on the Arduino board used - specifically on if it has native USB support. Boards without native USB support (like Uno or Nano) use a second chip, which receives UART (Serial) data from the main chip and interfaces that to USB. The main chip cannot know about the state of the USB chip, so it will send regardless of a program listening.

Boards with native USB support somewhat depend on the OS/driver/program to collect the data from the USB endpoints. If your program doesn't collect that data, but also doesn't close the connection, then the data will pile up in the buffer and `availableForWrite()` should return 0 when the buffer is full (blocking further writing to Serial). But if your program closes the connection correctly (as it should on exiting), then the Serial data doesn't even get send, but discarded. See Majenkos answer to this question, which is relevant here.

So generally: No, the Arduino won't stop sending data, only because you don't listen. Building a simple command system to tell the Arduino to start/stop sending data is a common way to handle this situation. Or you could implement a protocol, which lets the python script correctly detect start and end of each data packet.

---
Tags: serial, python
---


# Question
Title: Need help with parsing NWS JSON weather alerts causing reset on ESP8266
I'm trying to parse the JSON string from the National Weather Service Alerts and am encountering a problem where the code can't parse the value and the device auto-resets. I've used this code before on a different API to get the current weather conditions, and that works fine - I'm not sure what I'm doing wrong and would greatly appreciate any advice or help. Thanks!

Here is the error:

```
21:13:07.521 -> wdt reset
21:13:07.521 -> load 0x4010f000, len 3424, room 16
21:13:07.521 -> tail 0
21:13:07.521 -> chksum 0x2e
21:13:07.521 -> load 0x3fff20b8, len 40, room 8
21:13:07.521 -> tail 0
21:13:07.521 -> chksum 0x2b
21:13:07.521 -> csum 0x2b
21:13:07.521 -> v00045d00
21:13:07.521 -> ~ld
21:13:07.555 -> ����n�r��n|�l�l`b��|r�l�n��n�l`��r�l�l��

```

And here's my code:

```
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>

const char* ssid     = "mySSID";                      // SSID of local network
const char* password = "myPassword";                 // Password on network

WiFiClient client;
char weatherServerName[] = "api.weather.gov";
String result;

//For testing change this zone to any zone from the NWS that's currently experiencing a weather alert
//Find an active alert area by going to https://api.weather.gov/alerts/active and looking for the code in the "affectedZones"
String zone = "LEZ144";

bool hasAlert = false;

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

  WiFi.begin(ssid, password);

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

  Serial.println("Connected");
  delay(1000);
}

void loop() {
  Serial.println(":D");
  getWeatherAlerts();
  delay(100000);
}

void getWeatherAlerts()
{
  String server = weatherServerName;

  if (client.connect(server, 443))
       {
          client.println("GET /alerts/active?zone=" + zone);
          client.println("User-Agent: ArduinoWiFi/1.1");
          client.println("Connection: close");
          client.println();
          }
  else {
         Serial.println("connection failed");        //error message if no client connect
         Serial.println();
       }

                                       //waits for data
  while (client.connected() || client.available())
       {                                             //connected or data available
         char c = client.read();                     //gets byte from ethernet buffer
         result = result+c;
       }

  client.stop();                                      //stop client
  result.replace('[', ' ');
  result.replace(']', ' ');
  Serial.println(result);
  char jsonArray [result.length()+1];
  result.toCharArray(jsonArray,sizeof(jsonArray));
  jsonArray[result.length() + 1] = '\0';
  StaticJsonDocument<8196> root;
  DeserializationError error = deserializeJson(root, jsonArray);

  if (error)
    {
      Serial.println("parseObject() failed");
    }

  String features = root["features"];

  Serial.println(features);

  if(features.length() == 0)
  {
    Serial.println(features);
    hasAlert = false;
  }
  else
  {
    String severity = root["features"]["severity"];
    Serial.println(severity);
    if(severity == "Moderate" || severity == "Severe")
    {
      hasAlert = true;
    }
    else
    {
      hasAlert = false;
    }
  }

  Serial.println(hasAlert);
}

```

# Answer
> 6 votes
By default, the size of the stack is limited to 4KB on ESP8266, so you cannot store an 8KB document there.

To fix this issue, replace the `StaticJsonDocument` with a `DynamicJsonDocument` to move the buffer to the heap.

See also: Why does my device crash or reboot?

# Answer
> 2 votes
There is a good clue in the first line of your reported error:

```
21:13:07.521 -> wdt reset

```

The ESP-8266 Watchdog Timer (WDT) will reset the device if it has not been correctly 'fed' for a period of time (the watchdog timeout).

As @Juraj noted, the ESP-8266 Arduino libraries 'helpfully' add WDT feeds at various points, suggesting the timeout is because your code is either crashing (overflowing into invalid program code) or is timing out (valid code, but stuck in a loop).

The backtrace information printed on the reset can be used to find where the WDT happened specifically in your code, so you can find the issue (which could be the one @Benoit Blanchon noted). I have found this exception decoder to be very useful to translate the code to the functions in your code.

Also worth noting that the 'garbled characters' after the WDT reset backtrace information is the bootloader startup message, which is fixed at 74880 baud, you can change baud rate of your serial terminal to see those (and 'garble' the other messages).

(Info about watchdog timers and feeding below isn't directly relevant in this case, as @Juraj noted, but is left in for context)

This is an example document from TI introducing watchdog timers. For the ESP8266, you might find this techtutorialsx document more useful. In summary, you need to either turn off the watchdog, or issue periodic

```
ESP.wdtFeed();

```

commands. Turning off the watchdog is an appealingly easy option, but it disables a really useful tool to help you to make your project/product handle unexpected conditions/bugs more gracefully, so I'd encourage you to learn how to use it and then *feed* it as above.

(As @Benoit Blanchon noted, there are other issues on the implementation, which should be addressed, and perhaps deserve a separate post in code review. However I wanted to explain the reason for the reset you asked about, which isn't specifically JSON-related, and will continue to occur unless you take action as above)

---
Tags: esp8266, json, watchdog
---


# Question
Title: Typedef not accepted as a data type in a function?
I know I'm in a C++ compiler, but I typically create a typedef from structures, probably a holdover from earlier C programming. So this has my head spinning. I create a Typedef from a structure. After that, I have no trouble declaring a global or local version of that structure anywhere in a function, or outside of all functions (global). But when I try to create a function with this typedef as an arg, or even a function arg with a pointer the such a typedef, the compiler complains (and the complaint doesn't seem to make sense). Example...

```
typedef struct ss_tag {
  uint16_t settingsSavedCount;
  uint16_t codeID;

// a few more vars

  uint8_t powerDownSaveFlag; // lets me know why we're being reset.
  uint8_t future[10];
} Sunstates;

```

So now, this typedef seems as good as any other. Either of these statements compile fine...

```
Sunstates sunStates;
Sunstates * pSS = &sunStates;

```

But if I now try to create a function, with either an instance of this data type or a pointer to it, like so...

```
void systemDataVerify(Sunstates *pST) {  }

```

The Arduino compiler offers this confusing error message...

> Arduino: 1.8.3 (Windows XP), Board: "Arduino Nano, ATmega328"
>
> SolarControler\_21a:393: error: variable or field 'systemDataVerify' declared void
>
> void systemDataVerify(Sunstates \*pSS) { }
>
> ```
>                    ^
>
> ```
>
> SolarControler\_21a:393: error: 'Sunstates' was not declared in this scope
>
> SolarControler\_21a:393: error: 'pSS' was not declared in this scope
>
> void systemDataVerify(Sunstates \*pSS) { }
>
> exit status 1 variable or field 'systemDataVerify' declared void

The fact that it doesn't like me declaring a function void is odd, but not as troubling as it calling my function a 'variable or field' and definitely not as strange as it saying my datatype (Sunstates) was NOT "declared in this scope." The data type was defined immediately before the function... and the fact I could declare both instances of the type AND pointers to it kind of proves it exists within the scope. Can someone help me understand why the compiler is complaining?

Edit... I was asked to include a short sketch that shows the problem...

```
uint8_t somefunction() {
  return;
}

// define structure to hold/save setup and mode info

typedef struct ss_tag {
  uint16_t settingsSavedCount;
  uint8_t powerDownSaveFlag; // lets me know why we're being reset.
} Sunstates;

Sunstates sunStates; // create an instance

// create a function to accept a pointer to
// type Sunstates as an arg

void systemDataVerify(Sunstates *p) {
  return;
}

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
}

```

Now... I have discovered that if I remove the 'somefunction()' definition before the Structure definition, the problem goes away. And I'm using Arduino 1.8.3 to compile this.

# Answer
> 5 votes
I do not get this error in Arduino IDE 1.8.5 with snippet you provided, but I get it in Sloeber Eclipse plugin. The later attached sketch fails to compile in Arduino IDE 1.8.5 too.

The error is in Arduino build chain ino to cpp conversion for the C++ compilation. Put the typedef declaration into .h file and include it in ino.

EDIT: Details are in my newer answer to a similar problem.

# Answer
> 2 votes
It's **not** a compiler bug, @alm.

If I take the Minimal, Reproducible Example provided by the OP, and compile it, and then look at the intermediate file produced by the IDE (not the compiler) you can see what is happening:

```
#include <Arduino.h>
#line 1 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
#line 1 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
#line 1 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
uint8_t somefunction();
#line 18 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
void systemDataVerify(Sunstates *p);
#line 22 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
void setup();
#line 26 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
void loop();
#line 1 "/home/nick/Arduino/typedef_issue/typedef_issue.ino"
uint8_t somefunction() {
  return;
}

// define structure to hold/save setup and mode info

typedef struct ss_tag {
  uint16_t settingsSavedCount;
  uint8_t powerDownSaveFlag; // lets me know why we're being reset.
} Sunstates;

Sunstates sunStates; // create an instance

// create a function to accept a pointer to
// type Sunstates as an arg

void systemDataVerify(Sunstates *p) {
  return;
}

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
}

```

You will notice that the IDE "helpfully" produces function prototypes for your functions, and that the order in which it does that means that it puts the prototype for `void systemDataVerify(Sunstates *p);` **before** the typedef for the structure, leading to the error message.

The solution is simple. Put your own function prototype into your source, thus telling the IDE to not bother, like this:

```
uint8_t somefunction() {
  return;
}

// define structure to hold/save setup and mode info

typedef struct ss_tag {
  uint16_t settingsSavedCount;
  uint8_t powerDownSaveFlag; // lets me know why we're being reset.
} Sunstates;

void systemDataVerify(Sunstates *p);  // <<<<<< ---- function prototype

Sunstates sunStates; // create an instance

// create a function to accept a pointer to
// type Sunstates as an arg

void systemDataVerify(Sunstates *p) {
  return;
}

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
}

```

---

> Looks like a compiler bug to me. Perhaps that should be passed along to the compiler people.

It's not a bug in the compiler, arguably it is an idiosyncrasy of how the IDE works. No point in submitting bug reports to the compiler-writers. You could conceivably raise an issue on Github for the IDE complaining about the way they generate function prototypes.

---

For more information see my answer here. In it I mention:

> The function prototype generation however can lead to obscure error messages if you are not careful.

# Answer
> 0 votes
Here I am 5 years after the OP with the same issue. I'm on Arduino IDE Version: 2.2.1 Date: 2023-08-31T14:35:44.802Z. And I'm using the Adafruit ATSAMD21 M0.

Note that my offending typedef is already in a .h file placing it after everything it needs and before any use so that fix doesn't work for me.

I've discovered what does work around this issue:

Changing this:
int storeXXX( framBlock \*fb ) {

To this:
int storeXXX( struct \_framBlock \*fb ) {

That is, use the 'real' type for function arguments. The typedef appears to be Ok everywhere else, locals, globals, before and after the point of the error report, etc. Just not as a function argument.

Note that the OP found a similar solution in using void * as the type of his typedef'd pointer. I saw no mention of using the 'real' type which is a more straight forward fix.

Looks like a compiler bug to me. Perhaps that should be passed along to the compiler people.

---
Tags: typedef
---


# Question
Title: The Arduino copy of example code for tone() function produces a compile error: 'tone' is not declared in this scope. How can I fix this?
It's 32-bit ARM core processor is SAM3X8E ARM Cortex-M3 CPU.

Error:

```
sketch_nov16b\sketch_nov16b.ino: In function 'void setup()': sketch_nov16b:49:43: error: 'tone' was not declared in this scope tone(8, melody[thisNote], noteDuration);
^ sketch_nov16b:61:13: error: 'noTone' was not declared in this scope noTone(8);
^ exit status 1 'tone' was not declared in this scope

```

Code:

```
/*

  Melody

  Plays a melody

  circuit:

  - 8 ohm speaker on digital pin 8

  created 21 Jan 2010

  modified 30 Aug 2011

  by Tom Igoe

  This example code is in the public domain.

  https://www.arduino.cc/en/Tutorial/Tone

*/

#include "pitches.h"

// notes in the melody:
int melody[] = {

  NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {

  4, 8, 8, 4, 4, 4, 4, 4
};

void setup() {

  // iterate over the notes of the melody:

  for (int thisNote = 0; thisNote < 8; thisNote++) {

    // to calculate the note duration, take one second divided by the note type.

    //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.

    int noteDuration = 1000 / noteDurations[thisNote];

    tone(8, melody[thisNote], noteDuration);

    // to distinguish the notes, set a minimum time between them.

    // the note's duration + 30% seems to work well:

    int pauseBetweenNotes = noteDuration * 1.30;

    delay(pauseBetweenNotes);

    // stop the tone playing:

    noTone(8);

  }
}

void loop() {

  // no need to repeat the melody.
}

```

# Answer
> 3 votes
In short, they just never implemented `tone()` in the Due/SAM core. So you're not going to get the normal `tone()` function working.

* The tone.h header is empty.
They probably should done any number of things that would produced a somewhat clearer warning about this.
* The counterpart .cpp file has been renamed to .cpp.disabled so that the no attempt is made to compile it and is full of AVR-based code that they'd copied into the project for reference with the intention of replacing it but never did.

There a github issue tracking this. But it hasn't been updated since 2020. That issue references the Arduino forum for apparently working alternative code for producing tones. So maybe try their code.

I don't see any popular alternative packaged as an Arduino library for producing simple tones. However, the chip has a DAC and there is an Audio Library. It's a bit overkill for producing basic tones, but you could modify the example there to fill the buffer with a tone's waveform rather than loading it from an sdcard file.

---
Tags: compile, error
---


# Question
Title: Arduino Uno, does a lower Aref voltage work well for measuring current? without increasing ADC integral non-linearity
I want to measure current using a Arduino Uno and use a very low resistance of 0.1Ohm or lower for the shunt resistor to measure the current(to reduce power waste and heat generation), as a result resolution wouldn't be good at lower currents, while I do not need a very good resolution better resolution makes it more dependable and more easy to use and more universal. and it is very unlikely that I would run close to that many amps through it, as for that it would need 10A of current to reach 1V.

**my idea to solve this was** to set the Aref to a lower voltage of 1.1V by setting it to the internal Aref this would mean it could measure up to 11A of current but also has 5 times as much resolution.

but I noticed people online seemed to never do this, and instead just use higher restance of 1Ohm or such or directly use a external higher resolution ADC(and still only use a small part of it) or some dedicated amp measuring hadware. so I started to wonder **does the internal ADC in the arduino behave worse when set to 1.1V aref instead of the default 5V aref despite the datasheet saying it can go down to 1V aref?**

setting the Aref inside of the arduino to the internal Aref of 1.1V and using a 0.1 Ohm resistor would give +-10mA resolution(up to 11A), if I where to use a 1 Ohm resistor like most others do it would even give 1ma resolution(up to 1.1A).

is there something I am missing? which is the reason why other people do not change the Aref for this? **does lowering the Aref to 1.1V cause a reduction in the lineairity of the ADC curve(so that at some places the steps are a bigger difference than at some other places) compared to when it is kept to the default 5V Aref?**

## or as a shorter more TLDR question:

**does anyone have graphs or data available about the linearity of the arduino ADC with the ADC Aref at different voltages?** mostly to compare the linearity at a Aref of 1.1V and 5V.

## **definitions**

ADC Linearity in this context refers to integral non-linearity

## **extra**

I already looked into those 4 sources:

they all seem to confirm exactly what I was thinking with my solution. but none of them seem to give any info about how actually the Analog to Digital converter works on different Aref voltages, so for example if using a lower Aref might for example make the steps per volt less of a straight line and instead more of a curve or such where steps might all have different voltage difference differences? the datasheet I found only gave a fixed offset value but not how or if it was affected by the used Aref voltage, and neither any form or graph or such of the typical integral non-linearity. only one value that it has a integral non-linearity of 0.5LSB

## things people mentioned

* apaerently the arduino ADC indeed has some non linearity, but no actual values are given and neither if it also depends on the Aref voltage, people mention/reffer that the arduino ADC should be most efficient at the middle value of the ADC https://arduino.stackexchange.com/a/69390/70020
* to reduce energy wasting and maintain higher resolutions people recommend adding in a differential amplifier which would allow using even lower shunt resistors and still a good resolution. in theory this should do the same as changing the Aref, but then allowing even more sensitivity since the Aref can only go down to 1v so 5 times amplificaton

# Answer
If you used the 3.3 volt pin as external AREF a 1.5Ω resistor would drop 3V @ 2 Amps, 3V would produce an ADC value of 930 or 2.15mA per ADC count. If you use the 1.1V internal AREF, a 0.5Ω resistor would drop 1V @ 2A, ADC values would be the same.
> 2 votes

---
Tags: arduino-uno, analogread, analogreference
---


# Question
Title: PubSubClient constructor parameter type mismatch
I am just learning an Arduino so this is totally educational purpose call.

I want to instantiate `PubSubClient` client with `WiFiClient` parameter.

```

#include <WiFiClient.h>
#include <PubSubClient.h>

WiFiClient *wifi = NULL;
PubSubClient client(wifi);

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
}

```

compilation gives me back:

```
Compilation error: no matching function for call to /home/tepo/Arduino/libraries/PubSubClient/src/PubSubClient.h:116:4: note:   candidate expects 0 arguments, 1 provided
/home/tepo/Arduino/libraries/PubSubClient/src/PubSubClient.h:88:7: note: candidate: 'PubSubClient::PubSubClient(const PubSubClient&)'
 class PubSubClient : public Print {
       ^~~~~~~~~~~~
/home/tepo/Arduino/libraries/PubSubClient/src/PubSubClient.h:88:7: note:   no known conversion for argument 1 from 'WiFiClient*' to 'const PubSubClient&'

exit status 1

Compilation error: no matching function for call to 'PubSubClient::PubSubClient(WiFiClient*&)'

```

and listing all the other constructors.

type chain seems to hold: `class WiFiClient : public ESPLwIPClient` -\> `class ESPLwIPClient : public Client` -\> `class Client: public Stream`

`PubSubClient` ctor:

```
 PubSubClient(Client& client);

```

so why is it not accepting a WifiClient as a parameter?

# Answer
> 1 votes
The issue you're encountering with the PubSubClient constructor in Arduino is related to how you're passing the WiFiClient object. You're currently using a pointer (WiFiClient \*wifi), but the PubSubClient constructor expects a reference to a Client object, not a pointer.

The WiFiClient class inherits from the Client, so it can be used with PubSubClient. However, you need to pass an instance of WiFiClient, not a pointer to an instance.

Here's how you can correct your code:

```
#include <WiFiClient.h>
#include <PubSubClient.h>

WiFiClient wifi;
PubSubClient client(wifi);

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
}

```

In this corrected version, wifi is an instance of WiFiClient, not a pointer. When you pass wifi to the PubSubClient constructor, it correctly matches the expected Client& client parameter type.

In C++ a pointer (WiFiClient \*) is a variable that holds the memory address of an object. A reference (WiFiClient &) is an alias for an object. The PubSubClient constructor expects a reference because it needs to interact with the Client object throughout its lifecycle, and references are generally safer and more straightforward to use in this context than pointers.

---
Tags: esp32
---


# Question
Title: Is there a maximum length of an array in ROM?
Consider the following code:

```
    #include <Arduino.h>

    unsigned char testimage [] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    ... many more rows ...
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };

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

        Serial.println("start");

        for (int i = 0; i < 10; i++) {
            Serial.println((int)(testimage[i]));
        }

        Serial.println("stop");

    }
    void loop()
    {}

```

I found out that then the array gets a certain size, there is nothing being sent to the serial monitor. It looks like the entire program freezes. I do not even see the `start` message appear.

I haven't tried to find the exact size, but it is somewhere between 4500 and 8000. (When sized around 4500, it works, when around 8000 it doesn't).

When I do not address the array though, I do see the `start` and `stop` messages appear.

I am using an Arduino ATMega2560.

# Answer
It isn't clear whether you meant to put your array in ROM as your question implies, but the code you presented assigns it to RAM. That would surely restrict to your array to less than the 8K of of RAM minus whatever is needed by (globals + your libraries' statics + your code's statics + the stack).

Update:

> I assumed the data section of the code would end up in ROM.

In fact, an image of the *initialized data* section does become part of the ROM image. The initial values need to be saved somewhere so RAM can be initialized each time the program is(re-)started but it is not accessed from ROM during run-time. (Note we're not talking about PROGMEM data here, which *is* kept in ROM and accessed from there even at run-time.)
> 4 votes

# Answer
In this case the RAM size is the limit. And you'd need some space for stack/heap,..

If you use non-const array, it'll be copied from flash to RAM at the startup

On the mega2560 even using const it still be copied into the RAM as each FLASH/RAM/EEPROM has different address space

Only way would be using PROGMEM and it can't be used directly (again different address spaces for flash/ram)

You can guess the mega2560 has 8KB RAM and you should keep some RAM for runtime. If there isn't enough of space, the stack and heap will be smashing each other and it would behave completely unpredictably (overwritten return addresses, runaway code and so on)
> 3 votes

---
Tags: array, memory
---


title: Use attiny85 reset pin as analog pin

text:
# Question
Title: Use attiny85 reset pin as analog pin
I want to use the reset pin of the attiny85 as an analog pin to read the battery voltage, to be used as low level battery indicator.

So there is a lipo battery that will always be connected to this pin.

I need a high-voltage programmer to do so but I read that the reset pin can be simply an analog pin if the voltage to it is above 2.5v . Is it true?

If so, I can program it with Arduino SPI normally as the battery will never go below 2.5v.

Edit

Thanks @timemage for your answer, it really has good info.

But I can verify that if you give 5v to the Vcc of the attiny and connect a lipo (above 2.5v) to the reset pin, it will work as an analog pin.

I used a potentiometer and yes it is working, you can see more info about this as well in this post.

The real info starts from Post#10.

It is really a complex situation here as what I did was using the reset pin as reset and as an analog pin at the same time. It is not recommended but it works!

Please if you can review the post in the Arduino forums and rewrite your thoughts here it will be useful for more people to get useful info.

# Answer
The following was in answer to the question in its original form.

This is kind of more on an electronics question. But it may be of some interest people here, mostly because of Digispark clones that still have their reset functionality.

It's easier to answer these in a different order.

> I read that pin reset can be simply analog pin of the voltage to it is above 2.5v Is it true? If so, i can program it with arduino spi normally as the battery will never go below 2.5v

**Practically speaking the answer is best summarized as "no".**

It took me a while to realize what you were talking about, mostly because of this 2.5V number, which I still don't completely understand. Originally I thought you talking about the internal 2.56V reference. The way I'm interpreting this is **"As long as I don't actually cause a reset, is it true that I can use the ADC0 channel that is on the ATtiny85 RESET pin."**

Practically, I think no. But, this idea is amusing and also more than a little disturbing. It seemed that the answer could be a qualified yes only because it seemed ATMEL would need to have done extra work to make this not possible, even if trying to do it is a bit nuts. Naturally, I had to try it.

In testing I found that yes, the RESET pin still seems to function as an ADC channel. I was able to hook the division point of 2/3rds (ish) voltage divider to the reset and got a reading of 0xAD (as an 8-bit measurement) which is indeed about 2/3rds of 0xFF. At least this is the case with my particular chip under whatever operating conditions.

According to the datasheet the V\_RST (nRESET pin voltage threshold) is specified at 3V to be between 0.2 VCC and 0.9 VCC. It doesn't seem like you would have good reason to think the chip is certain to stay out of reset below 0.9 VCC which at 5V is 4.5V. I did not experiment with mine to find out where the threshold happened to be except that 1/3 VCC did trigger a reset.

So, I don't know where your 2.5V comes from except to say it's a number near the middle of the possible V\_RST range for an AVR at 5V. Even if you find this is where the threshold is for your chip, it isn't specified to be exactly there. The fact that I got a reading at 2/3rds instead of a reset does not seem specified to happen that way according to the datasheet.

Another thing about this is when the pin is used as RESET has its internal pullup is enabled, which is listed between 30K and 60K. So whatever you connect to your reset pin (your battery) is connected to the AVR VCC through a pullup.

Anyway, it's interesting but is ultimately probably a bad idea.

> So there is a lipo battery will be always connected to this pin

If you want to play with this using-RESET-pin-for-ADC-channel thing anyway, **definitely don't have your battery connected to reset when you program**, at least not without reasonable series resistance. Otherwise when your programmer goes to reset your ATtiny85 **it will short your battery to GND through the programmer**.

> I want to use reset pin of attiny85 as analog pin to read the battery voltage to be used as low level battery indicator

**Voltage isn't a great indication of the state of charge** of batteries generally. Under some conditions you can get a rough idea with it. The flatter the discharge voltage curve is the less useful voltage is as an indication of charge state. Lithium chemistries are sort of prized for producing fairly flat discharge curves at a voltage level high enough to do useful work. Typically a "coulomb counting" method is used instead. Basically you sample current over time and integrate (sum) this, not reading instantaneous (or short term averaged) battery voltage. And that has its own intricacies with not drifting from true value. Getting a reasonable sense of lipo's state of charge is enough of a pain to do well that **there exist metering chips specifically designed to do this**. I don't have good recommendations for them, but MAX17043 and MAX17048 are among the first part numbers for this sort of chip found on modules from suppliers of Arduino-related stuff.

> I want to use reset pin of attiny85 as analog

For most Arduino users it's really best to leave the reset pin alone. **The ATtiny84 is not much larger than an ATtiny85 and gives you an few extra pins** and is otherwise very similar. The ATtiny84 also supported by attinycore. If you are hard set on using the ATtiny85 **make sure you've exhausted all your options for using your other pins**. There are ways to connect multiple switches to a single `analogRead()` capable pin. There are ways to put LEDs and switches on the same pin if you don't mind the light coming on when you push button, etc.

> I need high voltage programmer to do so but

Right, so back onto using non-RESET functionality of the RESET pin the normal way.

Sort of. **You don't need high voltage serial programming mode to program your code that use the reset pin onto the chip and then to disable the reset pin and use it via `digitalRead()`/`digitalWrite()`/`analogRead()`/etc.**. But **you do need high voltage mode to program again after that,** either by programming code via high voltage mode or programming (unprogramming really) the `RSTDISBL` fuse to re-enable RESET functionality that ISP/SPI mode requires. In other words: if you're treating the parts as one-time-programmable then you need only an ISP programmer. But, during development you're probably not going to want to just toss out piles of otherwise perfectly good chips.

If you're determined to use the ADC channel that's on the reset pin, programming RSTDISBL fuse is the thing you want to do. Then you get useful range out of the ADC channel and the ability to disable the pullup, and maybe even fewer random resets.

And yeah, you need a high-voltage mode programmer to recover from that, and you need to be either able to remove the chip from the board or design the board to handle HVSP signals coming to it; in particular to handle 12V that will be applied to reset. Which is also something that should not make its way to your lipo.
> 2 votes

---
Tags: attiny85, reset
---