# Question
Title: How can i increase the range of values that a light sensor gives?
I have constructed 2 ceptometers that measure light intensity. Each ceptometer consists of 50 photodiodes that are connected to 2 copper wires (+ and - of the photodiodes are on the same orientation). Those wires are soldered with cable (+ to the copper wire where the positive side of the photodiodes is and the ground wire soldered to the copper wire where the negative side of the photodiodes is). Then, pins were soldered to the cables so as to can be connected to the breadboard.

The paper where the protocol for the construction is present, states that a 1.5 ohms resistor needs to be connected to the copper wires so as to enhance the range of the signal that the ceptometers will give. However, it mentions that this step can be followed later and the resistor can be connected to the wires (that is something that makes sense). I need to mention that one more ceptometer is present that was constructed by another person the previous year and it has the 1.5 ohms resistor soldered on the copper wire. It is something very important to keep in mind for the rest of the text!

I decided to use an arduino uno for my experiment and I connected the 3 ceptometeres (the old from the previous year and the 2 that were constructed by me) to a breadboard. Firstly, I applied light to the ceptometers with a projector and I tried different resistors from 470R to 5K but the values I got were the same. I thought that a kind of signal disturbance or noise may has been caused and I made 3 opAmp circuits in 3 different breadboards. When the breadboards were connected to the Arduino I tried the same resistors again but the values I got were the same. For the old ceptometer that has the 1.5 ohms resistor soldered to the copper wires the change of resistors altered a lot the signal and it gave a wide range of values. Here I have to say that when I applied to the 1.5 ohms resistor to the new captometers I got a pure 0 as a value. And it was the same when I placed them under sunlight.

When I converted the output of the Arduino to voltage signal by multiplying it with 5 and then divide it with 1023 I had the same voltage signal as when I measured it with the multimeter. And it was the same under both artificial and sun light. So, I can imagine that it is something that depends on the resistor that is not applied to the copper wires. I mean that maybe this is the case that I do not get a wide range of values like the old ceptometer but only 20 units

My question is: Do you know any way to enhance the range of the output or do you have any recommendation? Thank you a lot in advance!

With kind regards,

Dimitrios

# Answer
> 1 votes
The circuit is a current-to-voltage converter. The - input to the op-amp is held at 0 (the voltage at the + input, since it is grounded) so there will be no voltage across the diodes. The current drawn by the diodes is supplied by the op-amp output through the feedback resistor, so the larger that value, the greater the output voltage will be at any given current. The short answer is that to increase the output voltage, you need to increase the feedback resistor. (7 ohms seems pretty small to me, unless your diodes draw a LOT of current.)

The other complicating issue is that this circuit depends on the op-amp having a low input offset voltage, since its value (~2 mV for the LM358) causes output errors. Normally a low-offset-voltage op-amp would be used here, but maybe the use of so many diodes makes a large enough current to swamp the offset error. If increasing the feedback R doesn't help, you might try a different op-amp (even another LM358) in case the offset of the one you have is trying to force a negative output and that's why you see 0.

Edit 11-8-20: I looked up the sensor used in the PAR-BAR article that seems to be the source of your circuit. It pulls about 10 microamps at 1000 lux, so 50 of them would give 500 microamps. If you want to get (say) a 5V output at 1000 lux, you'd need a feedback resistor of 5/0.0005 = 10 kOhms. That's without the 1.5 ohm shunt. Also, are you applying your test illumination evenly over all 50 sensors? The above calculation assumes that all get 1000 lux.

If you have a single sensor available, I'd recommend breadboarding with just that and a 500 kOhm feedback resistor, and no shunt. That way there will be no issue about equal illumination. If you still have problems, and you are committed to the LM358 for some reason, try using a simple circuit to compensate for input offset. These typically involve a potentiometer (could be a trimmer in the final unit) that adjusts a very small voltage applied to the + input. In your tests you may find that it needs to be negative, which you would have to apply from some external source (since there is no - supply on the Arduino). If that's needed to resolve your problem, consider a better op-amp or a different circuit configuration.

Edit 11-9-20: Had another look at the PAR-bar article and noticed that they are measuring *differential voltage* across the photodiode array, which is not the same as your current-to-voltage converter (although that is indeed typical of photodiode circuits). The voltages that they get are 30 mV or less. I suggest you get a DMM and measure the voltage across the array, without any connection to other circuitry. Cheap DMMs have 200 mV full-scale, which should at least show you what's going on. The article used an expensive datalogger and only *suggests* that Arduino-type solutions may be possible, but gives no circuits. You probably don't need a true differential amp, since the photo voltage is always in the same direction.

---
Tags: signal-processing
---


title: What can I do to optimise this code?

text:
# Question
Title: What can I do to optimise this code?
I have optimised it as much as I feel I can and want to know what suggestions you have that could make it more efficient etc.

Note: I know the array goes on forever :)

```
volatile uint16_t IRCode[]={340,171,21,21,21,21,21,21,21,64,21,21,21,21,21,21,21,21,21,64,21,21,21,64,21,21,21,64,21,64,21,64,21,64,21,64,21,21,21,21,21,21,21,64,21,21,21,21,21,21,21,21,21,64,21,64,21,64,21,21,21,64,21,64,21,64,21,1556,340,86,21,3654}; // ProntoHex to uint16_t delete first 4 array numbers.
volatile uint16_t MicrosPassed;
volatile uint8_t Array_Seq;
uint8_t State;

void setup() {
  Config(); // Config sketch will set working settings for different microcontrollers.
  SendIRCode();
}

void loop() {

}

void SendIRCode() {
  switch(State) {
    case 1:
      TCCR1A&=63; // Opposite of case 0 -193 = 63
      State=0;
      break;

    case 0:
      TCCR1A|=192;
      State=1;
      break;
  }
}

void Config() {
  DDRB|=10;
  ICR1=416;
  OCR1A=9983;
  TCCR1A=2;
  TCCR1B=24;
  TCCR1B|=1;
  TIMSK1=1;
}

ISR(TIMER1_OVF_vect) {
  MicrosPassed++;
  if(MicrosPassed==IRCode[Array_Seq]) {
    SendIRCode();
    MicrosPassed=0;
    Array_Seq++;
       }
}

```

# Answer
> 3 votes
As hinted by chrisl in a comment, there are various criteria you may want to optimize for: speed, size, readability... Judging from the current state of this sketch, I would say that your first goal at this point should be to optimize for readability.

The hardest think to make sense of are most of the plain numbers. When setting registers that are bit fields, do not use decimal values: use either hexadecimal or binary. Or, better yet, use the names of the bits. The avr-libc defines those names, as well as the macro `_BV(bit_position)`, which expands to `(1 << bit_position)` and is meant to be used with those names:

```
void Config() {
  DDRB   |= _BV(PB1) | _BV(PB3);  // PB1 and PB3 as output
  ICR1    =  416;        // timer period = 417 cycles
  OCR1A   = 9983;        // ???
  TCCR1A  = _BV(WGM11);  // mode 14: fast PWM, TOP = ICR1
  TCCR1B  = _BV(WGM12) | _BV(WGM13);  // ...ditto
  TCCR1B |= _BV(CS10);   // clock @ F_CPU
  TIMSK1  = _BV(TOIE1);  // enable TIMER1_OVF interrupt
}

```

Granted, the bit names are somewhat obscure, but they do make the program easier to read if you have the datasheet nearby. I do like to have comments that make the code understandable even without reading the datasheet.

Note that evaluating those expressions does not make the program any slower, as they are evaluated at compile time.

When a variable is used in a single function, it is better to define it in that function. Keeping the definition close to where the variable is used makes the code more “local” and thus easier to read. Since you want some of those variables to remember their values across invocations of the function, give them the `static` qualifier.

You may not need to optimize this program for speed. There is, however, a low hanging fruit here: remove the `volatile` keywords. This keyword is meant to explicitly *disable* some compiler optimizations that are unsafe when a variable is shared between the interrupt and non-interrupt contexts. None of the variable you use needs this.

If I understood correctly, the function `SendIRCode()` just toggles a couple of bits in `TCCR1A`. You can simplify it to this:

```
void SendIRCode() {
  TCCR1A ^= _BV(COM1A0) | _BV(COM1A1);  // toggle PWM output on OC1A
}

```

Finally, there is I believe a bug in this sketch. The variable `Array_Seq` is continuously incremented and never reset. The program will then end up reading past the end of the `IRCode` array.

---
Tags: arduino-ide, c++, infrared
---


title: Sync of Time Library and RTClib

text:
# Question
Title: Sync of Time Library and RTClib
Trying to understand the two libraries and setSyncProvider(RTC.now). Using Arduino Uno with Adafruit ChronoDot. Aduino IDE 1.8.13.

The code below is simply to understand what is happening.
I am getting surprising results which means I do not understand what the libraries are doing.

What I *think* I am telling it to do:

1. Set time RTC to 05:10:30
2. Set Time Library to 09:27:05
3. In Loop, printing Library time (hour, minute, seconds)
4. In Loop, printing RTC time (now.hour, now.minute, now.second)
5. Every 5 seconds sync the Time Library to the RTC.
This is not what it is doing.
The output from serial prints is at the bottom.

**Question 1:** Why does Time Library time hour() minute() second() change from 9:27:9 to 12:43:44 after first sync and then from 12:43:48 to 19:1:20 after second sync, then reseting to 19:1:20 after each subsequent sync?

**Question 2:** After the Sync, why is Time Library hour(), minute() and second() not set to RTC values of now.hour(), now.minute() and now.second()?

```
#include "RTClib.h"
#include <Wire.h>
#include <TimeLib.h>

RTC_DS1307 RTC;
unsigned long LastSyncTime = 0;    //will control when it syncs just to understand

time_t time_provider()

{
    return RTC.now().unixtime();
}

void setup() {
Serial.begin(9600);
Wire.begin();  //sets up the I2C
RTC.begin();   //initializes the I2C to the RTC

//  Set the RTC Time to 5:10:30 Nov 3 2020
RTC.adjust(DateTime(2020,11,3,5,10,30));

//Set Arduino Time Library different than RTC time 9:27:05 so see how sync works
setTime(9, 27, 05, 4, 07, 2015);

}

void loop() {

//Sync time every 5 seconds
if ((millis() - LastSyncTime) > 5000)
  {
  Serial.println("+++++   Sync  ++++++++");
  setSyncProvider(RTC.now);  //sets Time Library to RTC time: hour() set to RTC now.hour (?)
  LastSyncTime = millis();

   }

DateTime now = RTC.now();  // gets RTC time into now Object

//Print Time Lib Times
Serial.print("hour:       ");
Serial.print(hour());
Serial.println();
Serial.print("minute:     ");
Serial.print(minute());
Serial.println();
Serial.print("seconds:    ");
Serial.print(second());
Serial.println();
Serial.println();

//Print RTC time
Serial.print("now.hour:   ");
Serial.print(now.hour());
Serial.println();
Serial.print("now.minute: ");
Serial.print(now.minute());
Serial.println();
Serial.print("now.second: ");
Serial.print(now.second());
Serial.println();
Serial.println("______________________");

delay(1000);
}

```

OUTPUT

hour: 9
minute: 27
seconds: 8

now.hour: 5
now.minute: 10
now.second: 33

hour: 9
minute: 27
seconds: 9

now.hour: 5
now.minute: 10
now.second: 34

+++++ Sync ++++++++
hour: 12
minute: 43
seconds: 44

now.hour: 5
now.minute: 10
now.second: 35

hour: 12
minute: 43
seconds: 45

now.hour: 5
now.minute: 10
now.second: 36

hour: 12
minute: 43
seconds: 46

now.hour: 5
now.minute: 10
now.second: 37

hour: 12
minute: 43
seconds: 47

now.hour: 5
now.minute: 10
now.second: 38

hour: 12
minute: 43
seconds: 48

now.hour: 5
now.minute: 10
now.second: 39

+++++ Sync ++++++++
hour: 19
minute: 1
seconds: 20

now.hour: 5
now.minute: 10
now.second: 40

hour: 19
minute: 1
seconds: 21

now.hour: 5
now.minute: 10
now.second: 41

hour: 19
minute: 1
seconds: 22

now.hour: 5
now.minute: 10
now.second: 42

hour: 19
minute: 1
seconds: 23

now.hour: 5
now.minute: 10
now.second: 43

hour: 19
minute: 1
seconds: 24

now.hour: 5
now.minute: 10
now.second: 44

+++++ Sync ++++++++
hour: 19
minute: 1
seconds: 20

now.hour: 5
now.minute: 10
now.second: 45

hour: 19
minute: 1
seconds: 21

now.hour: 5
now.minute: 10
now.second: 46

hour: 19
minute: 1
seconds: 22

now.hour: 5
now.minute: 10
now.second: 47

hour: 19 minute: 1 seconds: 23

now.hour: 5
now.minute: 10
now.second: 48

hour: 19
minute: 1
seconds: 24

now.hour: 5
now.minute: 10
now.second: 49

+++++ Sync ++++++++
hour: 19
minute: 1
seconds: 20

now.hour: 5
now.minute: 10
now.second: 50

hour: 19
minute: 1
seconds: 21

now.hour: 5
now.minute: 10
now.second: 51

hour: 19
minute: 1
seconds: 22

now.hour: 5
now.minute: 10
now.second: 52

hour: 19
minute: 1
seconds: 23

now.hour: 5
now.minute: 10
now.second: 53

# Answer
> Why does Time Library time hour() minute() second() change from 9:27:9 to 12:43:44 after first sync and then from 12:43:48 to 19:1:20 after second sync, then reseting to 19:1:20 after each subsequent sync?

Because:

1. You keep calling `setSyncProvider()`. The whole point of the sync system is that **you should only call that once to set the sync provider and then it syncs itself *automatically***.
2. You are setting the sync provider to a function that returns an object. The sync provider needs a function that returns an unsigned long (`time_t`).

Your code should be:

```
setSyncProvider(time_provider);

```

And it should **only be called once from inside setup**.

> Question 2: After the Sync, why is Time Library hour(), minute() and second() not set to RTC values of now.hour(), now.minute() and now.second()?

Because of all the things I stated above and were also told in your last question.
> 1 votes

---
Tags: arduino-uno, time, rtc
---


title: If and while statements not working

text:
# Question
Title: If and while statements not working
The second and third `while` and `if` are not working but the first `while` and `if` do work. Am I doing something wrong?

```
#include <DFMiniMp3.h>

int sw1 = 3;
int sw2 = 4;
int sw3 = 5;

class Mp3Notify
{
  public:
    static void OnError(uint16_t errorCode)
    {
      // see DfMp3_Error for code meaning
      Serial.println();
      Serial.print("Com Error ");
      Serial.println(errorCode);
    }

    static void OnPlayFinished(uint16_t globalTrack)
    {
      Serial.println();
      Serial.print("Play finished for #");
      Serial.println(globalTrack);
    }

    static void OnCardOnline(uint16_t code)
    {
      Serial.println();
      Serial.print("Card online ");
      Serial.println(code);
    }

    static void OnCardInserted(uint16_t code)
    {
      Serial.println();
      Serial.print("Card inserted ");
      Serial.println(code);
    }

    static void OnCardRemoved(uint16_t code)
    {
      Serial.println();
      Serial.print("Card removed ");
      Serial.println(code);
    }
};
DFMiniMp3<HardwareSerial, Mp3Notify> mp3(Serial); //Create the UART connection to the module

void setup()
{

  //3 push buttons with pullups
  pinMode(sw1, INPUT); //Define each button as input with pullup
  pinMode(sw2, INPUT);
  pinMode(sw3, INPUT);

  digitalWrite (sw1, HIGH); //12 Votls supply set to off state
  digitalWrite (sw2, HIGH); //5 Votls supply set to off state
  digitalWrite (sw3, HIGH); //3 Votls supply set to off state

  Serial.begin(9600);
  mp3.begin(); //Start communication with the DFplayer module
  uint16_t volume = mp3.getVolume(); //Get actual volume
  mp3.setVolume(30); //Set new volum (max is 30)
  uint16_t count = mp3.getTotalTrackCount(); //Get the total tracks on the SD card in case we want to sue this later...
}

//just a fucntion that we use to create delays in "ms"
//without using the delay() function
void waitMilliseconds(uint16_t msWait)
{
  uint32_t start = millis();

  while ((millis() - start) < msWait)
  {
    // calling mp3.loop() periodically allows for notifications
    // to be handled without interrupts
    mp3.loop();
    delay(1);
  }
}

void loop()
{

  if (digitalRead(sw1) == LOW)
  {
    mp3.playMp3FolderTrack(1); // Play audio track 0001
    waitMilliseconds(5000); // 1s of delay
    while (digitalRead(sw1) == HIGH); // do nothing until state changes

  }

  if (digitalRead(sw2) == LOW)
  {
    mp3.playMp3FolderTrack(2); // Play audio track 0002
    waitMilliseconds(5000); // 1s of delay

    while (digitalRead(sw2) == HIGH); // do nothing until state changes

  }

  if (digitalRead(sw3) == LOW)
  {
    mp3.playMp3FolderTrack(3); // Play audio track 0002
    waitMilliseconds(5000); // 1s of delay

    while (digitalRead(sw3) == HIGH); // do nothing until state changes
  }
}

```

# Answer
> 2 votes
After pressing `sw1`, the first `if` works. After releasing `sw1` (it's a push button), the line `while (digitalRead(sw1) == HIGH);` will make the code just sit there forever without continuing with the rest of the code until you press `sw1` again, which will be caught by the first `if` unless you release 'sw1' inhumanly fast.

So, once you have pressed and released `sw1`, the rest of the code with the next two `if`s will never run.

---
Tags: arduino-uno, arduino-mega, arduino-ide, arduino-nano, arduino-due
---


# Question
Title: Can I control LED brightness with potentiometer without any code, as well as reading the potentiometer value?
I am just getting back into electronics and have started to play around with making my own button box.

I am trying to control an LED's brightness using a potentiometer, while also reading the potentiometer's value with the Arduino's analogue pin. I want to limit the number of pins I am using for things because I have lots of buttons that will need to be hooked up, so I am trying to control the LED without any code.

I have put together the following circuit (sorry, not my tidiest diagram. I am also using a Pro Micro rather than a Leonardo, but I didn't think that would make any difference :) ).

This works to a degree. I am able to adjust the LED brightness using the pot, and I do get a reading on the Arduino from the pot, however, the reading does not go up linearly as I would expect. It seems to get to about 500 out of 1023 at 4/5 of the rotation and then jumps up to 1023 within the last 1/5.

Could someone explain why this happens, and if it is even possible to do what I am attempting?

Thanks in advance!

# Answer
> 1 votes
Thanks for all the suggestions.

In the end, I ordered some dual-gang potentiometers as jsotola suggested and Mejenko confirmed would work. These are working perfectly in my circuit now.

Thanks again!

# Answer
> 3 votes
You need to "buffer" the potentiometer to separate it from the LED and resistor. The simplest circuit for that is a unity-gain voltage follower with an op-amp:

simulate this circuit – Schematic created using CircuitLab

You want to choose a "Rail to Rail I/O" op-amp so that it can get right down to 0V and right up to 5V, otherwise you will clip the top and bottom of the range of the potentiometer.

# Answer
> 0 votes
Some good remarks have already been made by jsotola.

**Potentiometer types**

(updated because of Majenko's comment):

Note there are three types of pots:

* Logarithmic (with name A\<value\>K, e.g. A50K for a logarithmic 50K pot)
* Linear (with name B\<value\>K, e.g. B50K for a linear 50K pot)
* Reserve logarithmic/Exponential (with name C\<value\>K, e.g. C50K for a rserve logarithmic 50K pot)

**Mapping values**

However, in code you can map a value from a pot to any other value, even from logarithmic/linear to anything you want, using logarithmic or other functions available in C/C++.

**Shift Registers**

Also, to reduce the number of pins you need for buttons you can use shift registers. The most known is 74HC595 for output and in your case you need an input shift register, which is 74HC165, see e.g. https://dronebotworkshop.com/shift-registers/ or https://playground.arduino.cc/Code/ShiftRegSN74HC165N/

# Answer
> 0 votes
I am surprised that the pot has survived so far. LEDs are current devices not voltage devices. The above circuits will work to some extent but not very well. You need to vary the current either using an adjustable current source/sink or PWM.

---
Tags: led, potentiometer, arduino-pro-micro, resistor, analog
---


title: DFplayer, Play sound when pin is high

text:
# Question
Title: DFplayer, Play sound when pin is high
I have a code here, from DFmini player. I have a tactile switch. when I press it on and release it will play a sound. My question is that when I press the tactile but not release it so I want it still play the same sound. But while the tactile switch is pressed down it keeps repeating the same sound. I want it to play just for once while the tactile button is still pressed down.

```
//#include <SoftwareSerial.h>   //If we use other pins than D0 adn D1 for TX and RX for the music player
#include <DFMiniMp3.h>          //Downlaod here: https://electronoobs.com/eng_arduino_DFPlayer_Mini_Mp3_by_Makuna.php

int sw1 = 3;
int sw2 = 4;
int sw3 = 5;
int sw4 = 6;
int sw5 = 7;
int sw6 = 8;
class Mp3Notify
{
public:
  static void OnError(uint16_t errorCode)
  {
    // see DfMp3_Error for code meaning
    Serial.println();
    Serial.print("Com Error ");
    Serial.println(errorCode);
  }

  static void OnPlayFinished(uint16_t globalTrack)
  {
    Serial.println();
    Serial.print("Play finished for #");
    Serial.println(globalTrack);
  }

  static void OnCardOnline(uint16_t code)
  {
    Serial.println();
    Serial.print("Card online ");
    Serial.println(code);
  }

  static void OnCardInserted(uint16_t code)
  {
    Serial.println();
    Serial.print("Card inserted ");
    Serial.println(code);
  }

  static void OnCardRemoved(uint16_t code)
  {
    Serial.println();
    Serial.print("Card removed ");
    Serial.println(code);
  }
};

DFMiniMp3<HardwareSerial, Mp3Notify> mp3(Serial);   //Create the UART connection to the module

void setup()
{
  //3 push buttons with pullups
  pinMode(sw1,INPUT);                        //Define each button as input with pullup
  pinMode(sw2,INPUT);
  pinMode(sw3,INPUT);
  pinMode(sw4,INPUT);
  pinMode(sw5,INPUT);
  pinMode(sw6,INPUT);
  digitalWrite (sw1, HIGH); //12 Votls supply set to off state
  digitalWrite (sw2, HIGH); //5 Votls supply set to off state
  digitalWrite (sw3, HIGH); //3 Votls supply set to off state
  digitalWrite (sw4, HIGH); //Ajustable Votls supply set to off state
  digitalWrite (sw5, HIGH); //3 Votls supply set to off state
  digitalWrite (sw6, HIGH); //Ajustable Votls supply set to off state
  Serial.begin(9600);
  mp3.begin();                                      //Start communication with the DFplayer module
  uint16_t volume = mp3.getVolume();                //Get actual volume
  mp3.setVolume(30);                                //Set new volum (max is 30)
  uint16_t count = mp3.getTotalTrackCount();        //Get the total tracks on the SD card in case we want to sue this later...
}

//just a fucntion that we use to create delays in "ms"
//without using the delay() function
void waitMilliseconds(uint16_t msWait)
{
  uint32_t start = millis();

  while ((millis() - start) < msWait)
  {
    // calling mp3.loop() periodically allows for notifications
    // to be handled without interrupts
    mp3.loop();
    delay(1);
  }
}

void loop()
{
  if(!digitalRead(sw1))
  {
      mp3.playMp3FolderTrack(1);  // Play audio track 0001
      waitMilliseconds(1000);     // 1s of delay
  }

  if(!digitalRead(sw2))
  {
      mp3.playMp3FolderTrack(2);  // Play audio track 0002
      waitMilliseconds(1000);     // 1s of delay
  }

  if(!digitalRead(sw3))
  {
      mp3.playMp3FolderTrack(3);  // Play audio track 0003
      waitMilliseconds(1000);     // 1s of delay;
  }

  if(!digitalRead(sw4))
  {
      mp3.playMp3FolderTrack(4);  // Play audio track 0001
      waitMilliseconds(1000);     // 1s of delay
  }

  if(!digitalRead(sw5))
  {
      mp3.playMp3FolderTrack(5);  // Play audio track 0002
      waitMilliseconds(1000);     // 1s of delay
  }

  if(!digitalRead(sw6))
  {
      mp3.playMp3FolderTrack(6);  // Play audio track 0003
      waitMilliseconds(1000);     // 1s of delay;
  }

}//end of void

```

# Answer
> 1 votes
BOUNCE 2

Basically, the mechanical part of buttons and switches vibrate slightly when closed or opened causing multiple undesired false states (similar to noise). This library filters out these undesired state changes. More about debouncing:

John Errington's Experiments with an Arduino : Using digital inputs: Switch bounce and solutions to it Wikipedia article : http://en.wikipedia.org/wiki/Debounce#Contact\_bounce See the bottom of this page for a basic usage example and the "examples" folder for more.

The library is composed of three classes:

Debouncer : The code that does the actual debouncing. Only advanced users should play with this class. Bounce : This is the general use library. It links the Debouncer to a hardware pin on your board. Button : A special version of Bounce for buttons that are pressed.

https://github.com/thomasfredericks/Bounce2

---
Tags: arduino-nano, sd-card, button, audio
---


# Question
Title: How do I Upload a Program via Serial Port to an Optiboot_X-Enabled TinyAVR-0/1 Microcontroller using the Command Line?
### Background

In 2019, Microchip acquired Atmel and released several new AVR microcontrollers, including the Tiny-0 and Tiny-1 Series. On these mircocontrollers, traditional Atmel ICSP programming was not supported. Instead, they feature a new one-wire programming interface called *Unified Programming and Debug Interface (UPDI)*. The new hardware also made existing TTL-serial bootloader programming obsolete. Thus, one must use a native UPDI programmer to work with these microcontrollers, such as pyupdi.

However, Optiboot's developers have subsquently developed a new version of the bootloader called Optiboot\_X and implemented the STK500 programming protocol on these new microcontrollers, allowing one to program these microcontrollers using the traditional TTL-serial bootloader approach, and it appears that the Arduino community has already supported them for a while, with MegaCoreX and megaTinyCore, which was good news to me. Nevertheless, it seems that there's little resource beyond these prepackaged Arduino cores, in particular, there's almost no documentation on how to program them manually from the commandline.

### What I've already done

I designed a custom AVR development board based on the Atmel ATTiny1604 microcontroller, which is a member of the new Tiny-0 family. Due to technical considerations, it must be programmed via the serial port using the bootloader similar to a traditional Arduino, not UPDI (UPDI is only used to burn the bootloader).

To achieve this goal, I installed the latest version of binutils, GCC and an experimental patch to avr-libc, so the compiler is able to generate code targeting my microcontroller. Then, I compiled my personal Optiboot\_X bootloader.

```
$ git clone https://github.com/Optiboot/optiboot.git
$ cd optiboot/optiboot/bootloaders/optiboot
$ make -f Makefile.mega0 optiboot_attiny1604.hex UARTTX=A1 TIMEOUT=8 LED=A7 BAUD_RATE=57600 LED_START_FLASHES=10

Using Compiler at: /home/user/code/optiboot/optiboot/bootloaders/optiboot/avr-gcc
avr-gcc -g -Wall -Os -fno-split-wide-types -mrelax  -DWDTTIME=8  -DLED_START_FLASHES=10  -DLED=A7   -DUARTTX=A1 -DBAUD_RATE=57600       -Wl,-section-start=.text=0 -Wl,--section-start=.application=0x200 -Wl,--section-start=.version=0x1fe -Wl,--relax -nostartfiles -nostdlib  -mmcu=attiny1604 -o optiboot_attiny1604.elf optiboot_x.c
avr-size optiboot_attiny1604.elf
   text    data     bss     dec     hex filename
    494       9       0     503     1f7 optiboot_attiny1604.elf
avr-objdump -S  optiboot_attiny1604.elf > optiboot_attiny1604.lst
avr-objcopy -j .text -j .data -j .version --set-section-flags .version=alloc,load -O ihex optiboot_attiny1604.elf optiboot_attiny1604.hex

```

Then I uploaded the Optiboot\_X bootloader to the ATTiny1604 microcontroller via UPDI, using `pyupdi`.

```
# set fuse BOOTEND
$ pyupdi -d tiny1604 -c /dev/ttyUSB0 -fs 8:0x02

# burn Optiboot_X
$ pyupdi -d tiny1604 -c /dev/ttyUSB0 -f optiboot_attiny1604.hex

# reset
$ pyupdi -d tiny1604 -c /dev/ttyUSB0 -r

```

After burning the Optiboot\_X via UPDI, I was able to see 10 pulses during power-on at A7 on my oscilloscope, indicating that Optiboot\_X was alive.

Note: Technically the installation is not complete yet. Since UPDI and `/RESET` share the same pin, UPDI must be permanently disabled via fuse to allow programming via bootloader, but it means a nonfunctional bootloader can brick the chip. I decided to manually reset the chip by power cycling the board for now.

Next, I wrote a test program.

```
$ cat blink.c

#define F_CPU 20000000UL
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
    PORTB.DIRSET = 0b00000001;

    while(1) {
        PORTB.OUTSET = 0b00000001;
        _delay_ms(500);
        PORTB.OUTCLR = 0b00000001;
        _delay_ms(500);
    }
}

```

And I compiled it.

```
$ make
avr-gcc -mmcu=attiny1604 -Wall -Os -o blink.elf blink.c
avr-objcopy -j .text -j .data -j .rodata -O ihex blink.elf blink.hex

```

### Question

Now what? How do I upload `blink.hex` to the Optiboot\_X on the microcontroller?

On a traditional Arduino, the command is something like...

```
$ avrdude -C/etc/avrdude/avrdude.conf -v -patmega328p \
  -carduino -P/dev/ttyUSB0 -b38400 -D -Uflash:w:blink.hex:i

```

But this is not an ATMega328P and there's nearly zero documentation on the web, I have a lot of questions and I'm not sure how to proceed.

To begin with, in `man avrdude`, there's no mention of any Tiny0 or Tiny1 devices. What should the `-p` argument be? Also, do I need to use a patched version of `avrdude`? Do I need a customized `avrdude.conf`? If so, where can I find them?

# Answer
After poking around in the git repository for a while, I've solved the problem. To work with these new TinyAVR-0/1 microcontrollers, a new version of `avrdude` is needed. Since `avrdude` hasn't made a stable release yet, it's necessary to build a new `avrdude` from source from SVN.

```
$ svn co https://svn.savannah.nongnu.org/svn/avrdude/trunk avrdude
$ cd avrdude/avrdude
$ ./bootstrap
$ mkdir build && cd build
$ ../configure
$ make
$ make install

```

After installation, `/usr/local/bin/avrdude` and `/usr/local/etc/avrdude.conf` should be available. One can see that a bunch of new TinyAVR parts have been added...

```
$ avrdude -p?

Valid parts are:
  [...]
  t10      = ATtiny10
  t11      = ATtiny11
  t12      = ATtiny12
  t13      = ATtiny13
  t15      = ATtiny15
  t1604    = ATtiny1604
  t1606    = ATtiny1606
  t1607    = ATtiny1607
  t1614    = ATtiny1614
  t1616    = ATtiny1616
  t1617    = ATtiny1617
  t1634    = ATtiny1634
  t20      = ATtiny20
  t202     = ATtiny202
  t204     = ATtiny204
  t212     = ATtiny212
  t214     = ATtiny214
  t2313    = ATtiny2313
  t24      = ATtiny24
  t25      = ATtiny25
  t26      = ATtiny26
  t261     = ATtiny261
  t28      = ATtiny28
  t3214    = ATtiny3214
  t3216    = ATtiny3216
  t3217    = ATtiny3217
  t4       = ATtiny4
  t40      = ATtiny40
  t402     = ATtiny402
  t404     = ATtiny404
  t406     = ATtiny406
  t412     = ATtiny412
  t414     = ATtiny414
  t416     = ATtiny416
  t417     = ATtiny417
  t4313    = ATtiny4313
  t43u     = ATtiny43u
  t44      = ATtiny44
  t441     = ATtiny441
  t45      = ATtiny45
  t461     = ATtiny461
  t5       = ATtiny5
  t804     = ATtiny804
  t806     = ATtiny806
  t807     = ATtiny807
  t814     = ATtiny814
  t816     = ATtiny816
  t817     = ATtiny817
  t84      = ATtiny84
  t841     = ATtiny841
  t85      = ATtiny85
  t861     = ATtiny861
  t88      = ATtiny88
  t9       = ATtiny9
  [...]

```

To program the ATTiny1604, simply run...

```
$ avrdude -C/usr/local/etc/avrdude.conf -v -pt1604 \
  -carduino -P/dev/ttyUSB0 -b57600 -D -Uflash:w:blink.hex:i

```

Don't forget to modify the `-b57600` argument to match the baud of your Optiboot\_X build.

Lesson learned: When RTFM is impossible, use the source, Luke!

## Potential Problems

### avrdude: verification error; content mismatch

It's possible that `avrdude` successfully establishes communication with the board via the serial port, reads the correct device signature, then attempts to upload a program, but ultimately fails verification.

```
$ avrdude -v -pattiny1604 -carduino -P/dev/ttyUSB0 -b57600 -D -Uflash:w:blink.hex:i

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9425 (probably t1604)
avrdude: reading input file "blink.hex"
avrdude: writing flash (204 bytes):

Writing | ################################################## | 100% 0.06s

avrdude: 204 bytes of flash written
avrdude: verifying flash memory against blink.hex:
avrdude: load data flash data from input file blink.hex:
avrdude: input file blink.hex contains 204 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.06s

avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x0000
         0x01 != 0x0c
avrdude: verification error; content mismatch

```

Solution: In TinyAVR 0/1, the bootloader is located at the beginning of the flash memory, occupies the first 512 bytes. When compiling the program to be uploaded via the bootloader, the correct 512-byte text section offset must be specified. Otherwise, `avrdude` will attempt to program from 0x00, which is impossible, because it's the location of the bootloader. Upon readback, instead of your program, `avrdude` reads the bootloader, which triggers the verification failure in question (it's worth noticing that `0x01`, the first mismatched byte that triggers verification failure, is actually the first byte in the Optiboot\_X binary code).

Instead of using...

```
avr-gcc -mmcu=attiny1604 -Wall -Os -o blink.elf blink.c

```

Recompile your program with \`

```
avr-gcc -mmcu=attiny1604 -Wall -Os -o blink.elf blink.c \
-Wl,--section-start=.text=0x200

avr-objcopy -j .text -j .data -j .rodata -O ihex blink.elf blink.hex

```

And reupload it.

```
$ avrdude -v -pattiny1604 -carduino -P/dev/ttyUSB0 -b57600 -D -Uflash:w:blink.hex:i

avrdude: Device signature = 0x1e9425 (probably t1604)
avrdude: reading input file "blink.hex"
avrdude: writing flash (716 bytes):

Writing | ################################################## | 100% 0.00s

avrdude: 716 bytes of flash written
avrdude: verifying flash memory against blink.hex:
avrdude: load data flash data from input file blink.hex:
avrdude: input file blink.hex contains 716 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.00s

avrdude: verifying ...
avrdude: 716 bytes of flash verified

avrdude: safemode: Fuses OK (E:FF, H:FF, L:FF)

avrdude done.  Thank you.

```

### avrdude: programmer type jtagice3\_updi not found

It's possible that `avrdude` reports the following error...

```
/usr/bin/avrdude -C/usr/local/etc/avrdude.conf -v -pattiny1604 -carduino -P/dev/ttyUSB0 -b38400 -D -Uflash:w:blink.hex:i

avrdude: Version 6.3, compiled on Jul 24 2019 at 00:00:00
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "/usr/local/etc/avrdude.conf"
avrdude: error at "/usr/local/etc/avrdude.conf:1091: programmer type jtagice3_updi not found
avrdude: error reading system wide configuration file "/usr/local/etc/avrdude.conf"

```

Solution: You are trying to run an old version of `avrdude` with a new configuration file. Make sure the `avrdude` executable you are running is actually the up-to-date version compiled from the upstream SVN repository.
> 2 votes

---
Tags: bootloader, attiny, uploading
---


# Question
Title: Can't communicate with arduino using python (Windows)
I am new to programming and am trying to communicate with my arduino using python through serial communication. I am using the following code:

Arduino code:

```
int ledPin = 11;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin,OUTPUT);
}

void loop() {
  digitalWrite(ledPin,LOW);
    if (Serial.read() == 'M'){
      digitalWrite(ledPin,HIGH);}
}

```

Python code:

```
import imaplib
import serial
ser = serial.Serial("COM3",9600)
ser.write(b'T')
ser.close()

```

I get the following error on running the python script:

> serial.serialutil.SerialException: could not open port 'COM3': PermissionError(13, 'Access is denied.', None, 5)

# Answer
More than likely you ran the Arduino program from the Arduino IDE, and left the terminal window open. You must close it before you run the python program, as it will already 'own' the port until it closes. You dont have to quit Arduino IDE, just close the terminal window.
> 8 votes

# Answer
There can be several reasons as highlighted in these questions:

They include:

* port is already in use by another application
* permissions are set to deny access to normal users
* problems in the code (top answer in first link)

Try to run with administrator priviledges ("run as administrator"). Others claim that a simple retry might help.
> 1 votes

# Answer
Either run your python program in "administrator mode" or close any other programs using the port intended for
> 1 votes

# Answer
Are you by any chance using Jupyter Notebok? I was having a similar error today and managed to solve it by opening Jupyter Notebook through Anaconda Navigator instead of opening it through Anaconda Prompt.
> 1 votes

# Answer
you must use this code

```
>>> import serial
>>> ser.close()             # close port

```
> 1 votes

---
Tags: serial, python
---


title: ESP32: best way to embed certificates

text:
# Question
Title: ESP32: best way to embed certificates
I'm using the Arduino framework on an ESP32 based board. The board has an SD card slot, but I'm not going to use it.

Anyway, I need to store somewhere the certificates. To the the firmware I've just hardcoded them into the code:

```
const char *rootCABuff = \
"-----BEGIN CERTIFICATE-----\n" \
"MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB\n" \
...
"hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq\n" \
"-----END CERTIFICATE-----\n";

const char certificateBuff[] = \
"-----BEGIN CERTIFICATE-----\n" \
"MIIDWTCCAkGgAwIBAgIUZXjPNnJFXMntXOki9BT+QmDFciUwDQYJKoZIhvcNAQEL\n" \
...
"gGXtqlgPnenkZPTaBr9c8o+WjgQXFLM+Jwnw3/53dUI9zBcybTaptI63o3Ct\n" \
"-----END CERTIFICATE-----\n";

const char privateKeyBuff[] = \
"-----BEGIN RSA PRIVATE KEY-----\n" \
"MIIEpAIBAAKCAQEAuuKsFy98/xsJclnWo0d+qm8KImLEILB64BbH7WaYi3NnznLg\n" \
...
"uHfBLQQDrA0HDRvYpAUNw/b2H4dpUK/nGM4FFVMP7V8RM2t2923nhQ==\n" \
"-----END RSA PRIVATE KEY-----\n";

```

Of course this is not suitable for production where each unit will have a different set of certificates. So wonder what is the best way to store them.

The obviously idea is into flash. So I tried to enhance my settings class, based upon the `Preferences` library. In the official documentation I read:

> String values are currently limited to 4000 bytes. This includes the null terminator. Blob values are limited to 508000 bytes or 97.6% of the partition size - 4000 bytes, whichever is lower.

But if I do something like this:

```
Preferences prefs;
prefs.begin("settings", false);
Serial.println(prefs.freeEntries());

```

it return 460, even if I still have plenty of flash:

```
Flash: [=======   ]  73.8% (used 967234 bytes from 1310720 bytes)

```

Is there another library more suitable to store such a data *that can be used* with `Preferences`?

# Answer
I don't know what you need that `Preferences` thing for, but I would use SPIFFS/FAT anyway. Simply store the certificate in a file in flash and read that file when you need it. The required space is no problem as you can choose the size for file system in the partition table and also you can upload the file (there is a plugin in the arduino IDE for this purpose) after flashing the firmware, so having different certificates on individual devices is no problem.

I saw that you tagged the question with 'eeprom': the esp has no eeprom but emulates it with a blob in flash, so using any flash library is just as fine. The esp also supports wear-leveling, which makes using flash an even better option as the dedicated eeprom-partition, which was used in an older version of the sdk, would wear out orherwise. The "eeprom" is just there to be consistent with the use of other arduino's eeproms.
> 3 votes

---
Tags: esp32, eeprom, flash
---


# Question
Title: What happen to the counter value if I do not input the statement (if previous state!=current state)
I refer to the code from this page: http://www.toddholoubek.com/classes/pcomp/?page\_id=58 :

```
int ledPin = 13; // choose the pin for the LED
int switchPin =2; // choose the input pin (for a pushbutton)
int val = 0; // variable for reading the pin status
int counter = 0;
int currentState = 0;
int previousState = 0;

void setup() {
  pinMode(ledPin, OUTPUT); // declare LED as output
  pinMode(switchPin, INPUT); // declare pushbutton as input
  Serial.begin(9600);
}

void loop() {
  val = digitalRead(switchPin); // read input value
  if (val == HIGH) { // check if the input is HIGH (button released)
    digitalWrite(ledPin, HIGH); // turn LED on
    currentState = 1;
  }
  else {
    digitalWrite(ledPin, LOW); // turn LED off
    currentState = 0;
  }
  if(currentState != previousState) {
    if(currentState == 1) {
      counter = counter + 1;
      Serial.println(counter);
    }
  }
  previousState = currentState;
  delay(250);
}

```

I do not have the Arduino device so couldn't test the result currently but am Interested to know if I omitted this line:

```
if(currentState != previousState)

```

, using the command line

```
if(currentState == 1) {
counter = counter + 1;

```

only and lets say I using a FS-V21 fiber optic sensor to count the quantity of products of 1m long each and on a conveyer belt of speed 0.1m/s so the stat will be true of t=1/0.1=10second for each product.

Will the counter value increase one unit only for each product (happen on the transition edge only), or increase indefinitely in the 10 second duration?

# Answer
Because of the line

```
delay(250);

```

towards the end of the `loop()` function it will count up once every quarter of a second all the time the "state" is 1.

That means over a 10 second period it will count 40 objects.
> 1 votes

# Answer
No, it will increment *as long as* there is a product and at the frequency your loop runs at. So, when the light is interrupted, it will count several objects within a second.

The line you want to ommit is very essential, it makes the sketch only detect edges rather than levels.
> 1 votes

---
Tags: arduino-uno
---


# Question
Title: What happens, memory-wise, when I call a function from another function?
I'm inspecting where the memory is used in an application which runs on Arduino. To my surprise, there are several locations where 100 to 200 bytes are consumed by simply calling a function. Example:

```
void Dispatcher::processCommand() {
    ...
    displayMemory();
    this->process(this->instruction);
}

void Dispatcher::process(const Instruction &instruction) {
    displayMemory();
    if (instruction.length > 0) {
        ...
        return;
    }

    ErrorResponse::componentNotFound(instruction).output(this->serial);
    TerminationResponse(instruction.commandId, 0xFF).output(this->serial);
}

```

The first call to `displayMemory()` will report that there is 351 bytes left. The second one will tell that only 159 bytes remain (that is, 192 bytes less).

If I alter the body of the `process` function, the difference between the two memory reports vary. For instance, if I remove the two last lines, the difference drops from 192 bytes to 12 bytes.

I don't understand why this happens. I was thinking that between the moment I'm ready to call a function and a moment when the function starts, the memory should be used exclusively by the additional element in the call stack (the aforementioned 12 bytes maybe?) and the copying of the parameters passed by value (none here). Why is this not the case? What really happens under the hood?

# Answer
The clue is in those last two lines:

```
    ErrorResponse::componentNotFound(instruction).output(this->serial);
    TerminationResponse(instruction.commandId, 0xFF).output(this->serial);

```

Let's tear them apart and see what they actually do.

```
ErrorResponse::componentNotFound(instruction).output(this->serial);

```

Call the static function `componentNotFound` with your `instruction`, then take the object that is returned, and call the `output()` method on it passing `this->serial` as a parameter.

The hint there is *take the object that is returned*.

`componentNotFound()` returns an object. That object has to be stored somewhere. That "somewhere" is on the stack. And stack space is allocated during the function *preamble*. That's the bit of code that runs at the start of the function allocating stack, pushing registers to the stack, etc.

The same happens in the second line:

```
TerminationResponse(instruction.commandId, 0xFF).output(this->serial);

```

Create a new `TerminationResponse` object and call the `output` method.

All that goes on the stack.

It's not the calling of the function that is using the memory, it's *what the function is doing that is using the memory*.
> 3 votes

# Answer
A function's data-memory space is reserved on the stack when the function is called, and returned when the function returns. If that function1 calls another, function2, then function1's space remains on the stack and more space is reserved for function2 for the duration of its execution. When function2 returns to function1, function2's memory is released, and finally, when function1 returns, its memory is released.

Now in a little more detail:

When you call function1, the arguments you pass it are put on the stack. When control actually passes to function1, the instruction address following the call, where function1 should eventually return to, is put on the stack. If function1 needs data temporary data space (automatic variables), space for those is put on the stack. (Ditto for function2, if one is called from function 1; and so on.)

When each of those functions returns, their automatic data space (just the space, not the data!) and the return address are removed from the stack; the caller removes the space for the arguments it had pushed, and execution resumes immediately following the call.

The difference in usage you're seeing depending on the presence or absence of the last two lines of Dispatcher::process(), is the memory (arguments+return address+automatic data) used by those two functions.
> 2 votes

---
Tags: memory-usage, memory
---


title: Why isn't this EEPROM.get() working?

text:
# Question
Title: Why isn't this EEPROM.get() working?
I am trying to save a string/char to EEPROM with `EEPROM.put()` and then get the value, but it doesn't work and I get a blank value when I do a `EEPROM.get()`. I remember this is how it worked on **arduino nano**, but now I am trying with an **ESP32 board**, do they work different ?

```
#include <EEPROM.h>

char my_string[8];

void setup() {

  Serial.begin(115200);

// I am writing by this code, then comment it out to try to read from EEPROM
/*
    my_string[0] = 'S';
    my_string[1] = 'N';
    my_string[2] = '-';
    my_string[3] = 'A';
    my_string[4] = 'B';
    my_string[5] = 'C';
    my_string[6] = 'D';

  EEPROM.put(0, my_string);
*/

  EEPROM.get(0, my_string);

  Serial.println("data is: ");
  Serial.println((char*)my_string);
}

void loop() { }

```

# Answer
> 4 votes
EEPROM can't store string. It stores numbers. `put()` takes a type and stores that type as numbers.

The `char[]` isn't a string - it's a number. More specifically it's a memory address for where the string data is stored.

All you're doing is storing that memory address, not the data itself.

Instead you need to iterate over your string. You should also store the length of the string if it's going to be variable.

For example:

```

void storeString(const char *str) {
    EEPROM.write(0, strlen(str)); // Store the string length
    for (int i = 0; i < strlen(str); i++) {
        EEPROM.write(i + 1, str[i]);
    }
}

void getString(char *str) {
    int len = EEPROM.read(0);
    for (int i = 0; i < len; i++) {
        str[i] = EEPROM.read(i + 1);
    }
}

```

---
Tags: string, eeprom, memory, data
---


# Question
Title: _delay_ms() is much slower than expected (by a factor of 6) on TinyAVR 0/1 (ATTiny1604)
I designed a custom AVR development board using the Atmel ATTiny1604 microcontroller. It belongs to the new Tiny-0 family, due to its recentness, some required changes to relevant toolchains have yet to be included into the stable version (I prefer to use the original upstream toolchains instead of Atmel/Microchip's SDK). Thus, I compiled the latest versions of toolchains from source. They include...

After I installed the toolchains, I wrote a LED blinking program to verify whether my toolchain was working properly. The program was built with `avr-gcc -mmcu=attiny1604 -Wall -Os -o blink.elf blink.c -Wl,--section-start=.text=0x200` and uploaded via the Optiboot\_X bootloader.

```
#define F_CPU 20000000UL
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
    PORTB.DIRSET = 0b00000001;

    while (1) {
        PORTB.OUTSET = 0b00000001;
        _delay_ms(500);
        PORTB.OUTCLR = 0b00000001;
        _delay_ms(500);
    }
}

```

However, I found that `_delay_ms(500)` doesn't work as expected. Instead of a 500-millisecond delay, the actual delay is closer to 3000 milliseconds as seen on the oscilloscope, it has been slowed down by a factor of 6.

I've double-checked my fuse settings.

```
$ pyupdi -d tiny1604 -c /dev/ttyUSB0 -fr
Device info: {'family': 'tinyAVR', 'nvm': 'P:0', 'ocd': 'D:0', 'osc': '3', 'device_id': '1E9425', 'device_rev': '0.0'}
Fuse:Value
0:0x00
1:0x00
2:0x02
3:0xFF
4:0x00
5:0xF6
6:0x07
7:0x00
8:0x02
9:0xFF
10:0xC5

```

I saw `pyupdi` reported that the fuse `OSCCFG` (No. 2) has been programmed to `0x02`, which according to the datasheet, means "Run at 20 MHz with corresponding factory calibration". Why do I get incorrect delays even when the system clock is running at the correct speed? Is my toolchain broken?

**Note: This is a question I already solved. But consider there are relatively few tutorials about the new TinyAVR 0/1 on the web, I posted the question and answer here to serve as a reference for the community.**

# Answer
Your toolchain is not broken. In the ATTiny804/1604 datasheet, page 77, it shows the CPU clock is divided from the 20/16 MHz oscillator by a prescaler (the ATTiny1614 datasheet shows the same clock prescaler in page 80. So it's a feature found in both tinyAVR 0/1 microcontrollers).

Source: Microchip ATTiny804/1604 datasheet, fair use.

The datasheet says...

> **10.3.3 Main Clock After Reset** After any Reset, `CLK_MAIN` is provided by the 16/20 MHz Oscillator (`OSC20M`) and **with a prescaler division factor of 6**. Since the actual frequency of the `OSC20M` is determined by the Frequency Select bits (`FREQSEL`) of the Oscillator Configuration fuse (`FUSE.OSCCFG`), these frequencies are possible after Reset:
>
> * 16 MHz ---\> 2.66 MHz
> * 20 MHz ---\> 3.3 MHz

By default, the division factor is 6. It means the CPU is actually running at 3.333 MHz when the `OSCCFG` fuse is programmed to 20 MHz.

## Solution

### Use the correct `F_CPU`

If a slower CPU is not a problem to you, you can simply report the correct CPU frequency to the compiler by change `#define F_CPU 20000000UL` to `#define F_CPU 3333333UL`.

### Or disable frequency division

Alternatively, you can disable the frequency division and run the CPU at its 20 MHz full speed.

```
#define F_CPU 20000000UL

int main(void)
{
    /* Set CPU clock to 20 MHz */
    _PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0);

    /* your code */
}

```

### But don't overclock the CPU

Nevertheless, you should note that 20 MHz operation is only guaranteed by Atmel at 4.5 V and above. If you are running the microcontroller at a lower voltage, such as 3.3 V, you are overclocking the CPU by putting it outside the safe operating area designated by Atmel. See datasheet page 473.

Source: Microchip ATTiny804/1604 datasheet, fair use.

Although an overclocked microcontroller will probably work, and in a hobby project, you are unlikely to see any issue. But still, at this point there is no guarantee of stability from the manufacturer. For example, the microcontroller is officially rated at 105°C, but an overclocked microcontroller may start crashing. Increased power consumption is also likely. The worst possible problem could be mysterious malfunction under certain rare conditions. Thus, if reliability and stability is important, you should not overclock the microcontroller.

At 3.3 V, given a 20 MHz system clock, the CPU should only operate at 10 MHz by setting the prescaler to 2x. And at 1.8 V, at 5 MHz with a 4x prescaler.

```
/* Set CPU clock to 10 MHz */
_PROTECTED_WRITE(CLKCTRL_MCLKCTRLB,
                 CLKCTRL_PDIV_2X_gc | CLKCTRL_PEN_bm);

/* Set CPU clock to 5 MHz */
_PROTECTED_WRITE(CLKCTRL_MCLKCTRLB,
                 CLKCTRL_PDIV_4X_gc | CLKCTRL_PEN_bm);

```
> 17 votes

---
Tags: attiny, oscillator-clock, timing, avr-toolchain
---


# Question
Title: Uploading sketch to ATTiny84 with Nano as "Arduinio as ISP" stopped working
Update 12/11 Working through the answer posted.

* Upload reset appearance - \[Works blinks correctly.\]
* Convince yourself that reset appearance code reliable indicates DTR resets. \[Opened the serial monitor 5-6 times, nothing changed or blinked\]
* 10uF cap between Arduino Nano RESET and adjacent GND. \[Done\]
* Plug the board back in and you should see the LED Blink rapidly for the power-on (not DTR) reset. \[Blinks rapidly same as after upload of sketch in Step one\]
* Open (or Reopen) the serial monitor and see that the LED remains OFF. \[No LED's\]
* Break the RESET leg of whatever circuit you chose for defeating DTR reset. Upload the ArduinoISP sketch \[Uploaded and verified, no problem\]
* You should see a signature check error like this: \[Yes this error occured same message as you posted\]
* Upload Empty sketch \[ IT WORKS !!!!!\]
* Check using one of my previous sketchs \[WOOT! It works\]

Thanks, that resolved the issue!! (although I've aready bought a universal programmer because I didn't think I would ever get it working).

Update - 11/Nov

As suggested, I have taken the nano out of any board and it is dangling from the USB cable. I have tried to upload the default sketch.

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

}

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

}

```

using the settings:

* Board Attiny22/44/84
* Processor Attiny84
* Programmer Arduino as ISP

I still get the problem of programmer not responding. Did this for all 3 nanos I have available.

===

Update - 11/nov I have now wiped all the IDE from my machine and reloaded. I have attempted to program an ATmega168PA instead of the tiny. Same problem.

Update - 10/nov:

After swapping between 2 different nanos and different capacitors to check that the cap is working. I noticed some different behavour. Nano A fails as below, however Nano B fails, but the message is slightly different. Instead of resp=0x00 I have resp=0xFF

Also on Nano B the L light doesn't flash it is on constantly and the 10 getsync messages go really fast.

---

I really could do with a solution if anyone has one.

I am trying to upload a sketch into a ATTiny84 with Nano as "Arduinio as ISP". This worked last week, same sketch, no changes. I have attempted to troubleshoot:

Changed ATTiny chips, changed between 3 different Nanos (and even bought another which also failed), I have changed all the USB cables, changed all the wires. I have installed the IDE on different machines.

In summary, I have tried:

* 3 different machines: Linux, Raspberry Pi, Windows 10
* 7 different ATTiny84 chips (I have ten, but don't want to use the other 3 in case this is bricking them!)
* 4 different Nanos
* different USB cables, different wires, replaced the capacitors

I have triple checked the configuration. Nothing seems to fix the problem.

I have no issue with any of the Nanos, I can use them directly, but just can't seem to use them to push into the AVR. It worked with the same configuration for weeks, now it doesn't. I'm really scratching my head.

I'm using:

* ATTiny core by David A. Mellis
* Boards: Attiny24/44/84
* Processor: Attiny84
* Clock: Internal 1 Mhz
* Programmer: Arduinio as ISP
* "Upload using Programmer"

Verbose Error messages:

```
Arduino: 1.8.13 (Linux), Board: "ATtiny24/44/84, ATtiny84, Internal 1 MHz"

/home/rick/arduino-1.8.13/arduino-builder -dump-prefs -logger=machine -hardware /home/rick/arduino-1.8.13/hardware -hardware /home/rick/.arduino15/packages -hardware /home/rick/Arduino/hardware -tools /home/rick/arduino-1.8.13/tools-builder -tools /home/rick/arduino-1.8.13/hardware/tools/avr -tools /home/rick/.arduino15/packages -built-in-libraries /home/rick/arduino-1.8.13/libraries -libraries /home/rick/Arduino/libraries -fqbn=attiny:avr:ATtinyX4:cpu=attiny84,clock=internal1 -vid-pid=1A86_7523 -ide-version=10813 -build-path /tmp/arduino_build_476590 -warnings=default -build-cache /tmp/arduino_cache_440110 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avrdude.path=/home/rick/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17 -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=/home/rick/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17 -prefs=runtime.tools.arduinoOTA.path=/home/rick/.arduino15/packages/arduino/tools/arduinoOTA/1.3.0 -prefs=runtime.tools.arduinoOTA-1.3.0.path=/home/rick/.arduino15/packages/arduino/tools/arduinoOTA/1.3.0 -prefs=runtime.tools.avr-gcc.path=/home/rick/arduino-1.8.13/hardware/tools/avr -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=/home/rick/arduino-1.8.13/hardware/tools/avr -verbose /home/rick/Arduino/Light_detector_Example/Light_detector_Example.ino
/home/rick/arduino-1.8.13/arduino-builder -compile -logger=machine -hardware /home/rick/arduino-1.8.13/hardware -hardware /home/rick/.arduino15/packages -hardware /home/rick/Arduino/hardware -tools /home/rick/arduino-1.8.13/tools-builder -tools /home/rick/arduino-1.8.13/hardware/tools/avr -tools /home/rick/.arduino15/packages -built-in-libraries /home/rick/arduino-1.8.13/libraries -libraries /home/rick/Arduino/libraries -fqbn=attiny:avr:ATtinyX4:cpu=attiny84,clock=internal1 -vid-pid=1A86_7523 -ide-version=10813 -build-path /tmp/arduino_build_476590 -warnings=default -build-cache /tmp/arduino_cache_440110 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avrdude.path=/home/rick/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17 -prefs=runtime.tools.avrdude-6.3.0-arduino17.path=/home/rick/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17 -prefs=runtime.tools.arduinoOTA.path=/home/rick/.arduino15/packages/arduino/tools/arduinoOTA/1.3.0 -prefs=runtime.tools.arduinoOTA-1.3.0.path=/home/rick/.arduino15/packages/arduino/tools/arduinoOTA/1.3.0 -prefs=runtime.tools.avr-gcc.path=/home/rick/arduino-1.8.13/hardware/tools/avr -prefs=runtime.tools.avr-gcc-7.3.0-atmel3.6.1-arduino7.path=/home/rick/arduino-1.8.13/hardware/tools/avr -verbose /home/rick/Arduino/Light_detector_Example/Light_detector_Example.ino
Using board 'ATtinyX4' from platform in folder: /home/rick/.arduino15/packages/attiny/hardware/avr/1.0.2
Using core 'arduino' from platform in folder: /home/rick/arduino-1.8.13/hardware/arduino/avr
Detecting libraries used...
/home/rick/arduino-1.8.13/hardware/tools/avr/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=attiny84 -DF_CPU=1000000L -DARDUINO=10813 -DARDUINO_attiny -DARDUINO_ARCH_AVR -I/home/rick/arduino-1.8.13/hardware/arduino/avr/cores/arduino -I/home/rick/.arduino15/packages/attiny/hardware/avr/1.0.2/variants/tiny14 /tmp/arduino_build_476590/sketch/Light_detector_Example.ino.cpp -o /dev/null -DARDUINO_LIB_DISCOVERY_PHASE
Alternatives for SendOnlySoftwareSerial.h: [SendOnlySoftwareSerial]
ResolveLibrary(SendOnlySoftwareSerial.h)
  -> candidates: [SendOnlySoftwareSerial]
/home/rick/arduino-1.8.13/hardware/tools/avr/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=attiny84 -DF_CPU=1000000L -DARDUINO=10813 -DARDUINO_attiny -DARDUINO_ARCH_AVR -I/home/rick/arduino-1.8.13/hardware/arduino/avr/cores/arduino -I/home/rick/.arduino15/packages/attiny/hardware/avr/1.0.2/variants/tiny14 -I/home/rick/Arduino/libraries/SendOnlySoftwareSerial /tmp/arduino_build_476590/sketch/Light_detector_Example.ino.cpp -o /dev/null -DARDUINO_LIB_DISCOVERY_PHASE
Using cached library dependencies for file: /home/rick/Arduino/libraries/SendOnlySoftwareSerial/SendOnlySoftwareSerial.cpp
Generating function prototypes...
/home/rick/arduino-1.8.13/hardware/tools/avr/bin/avr-g++ -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=attiny84 -DF_CPU=1000000L -DARDUINO=10813 -DARDUINO_attiny -DARDUINO_ARCH_AVR -I/home/rick/arduino-1.8.13/hardware/arduino/avr/cores/arduino -I/home/rick/.arduino15/packages/attiny/hardware/avr/1.0.2/variants/tiny14 -I/home/rick/Arduino/libraries/SendOnlySoftwareSerial /tmp/arduino_build_476590/sketch/Light_detector_Example.ino.cpp -o /tmp/arduino_build_476590/preproc/ctags_target_for_gcc_minus_e.cpp -DARDUINO_LIB_DISCOVERY_PHASE
/home/rick/arduino-1.8.13/tools-builder/ctags/5.8-arduino11/ctags -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives /tmp/arduino_build_476590/preproc/ctags_target_for_gcc_minus_e.cpp
Compiling sketch...
/home/rick/arduino-1.8.13/hardware/tools/avr/bin/avr-g++ -c -g -Os -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=attiny84 -DF_CPU=1000000L -DARDUINO=10813 -DARDUINO_attiny -DARDUINO_ARCH_AVR -I/home/rick/arduino-1.8.13/hardware/arduino/avr/cores/arduino -I/home/rick/.arduino15/packages/attiny/hardware/avr/1.0.2/variants/tiny14 -I/home/rick/Arduino/libraries/SendOnlySoftwareSerial /tmp/arduino_build_476590/sketch/Light_detector_Example.ino.cpp -o /tmp/arduino_build_476590/sketch/Light_detector_Example.ino.cpp.o
Compiling libraries...
Compiling library "SendOnlySoftwareSerial"
Using previously compiled file: /tmp/arduino_build_476590/libraries/SendOnlySoftwareSerial/SendOnlySoftwareSerial.cpp.o
Compiling core...
Using precompiled core: /tmp/arduino_cache_440110/core/core_attiny_avr_ATtinyX4_cpu_attiny84,clock_internal1_8328ca5f502560caf6997d9e8039b097.a
Linking everything together...
/home/rick/arduino-1.8.13/hardware/tools/avr/bin/avr-gcc -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -mmcu=attiny84 -o /tmp/arduino_build_476590/Light_detector_Example.ino.elf /tmp/arduino_build_476590/sketch/Light_detector_Example.ino.cpp.o /tmp/arduino_build_476590/libraries/SendOnlySoftwareSerial/SendOnlySoftwareSerial.cpp.o /tmp/arduino_build_476590/../arduino_cache_440110/core/core_attiny_avr_ATtinyX4_cpu_attiny84,clock_internal1_8328ca5f502560caf6997d9e8039b097.a -L/tmp/arduino_build_476590 -lm
/home/rick/arduino-1.8.13/hardware/tools/avr/bin/avr-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 /tmp/arduino_build_476590/Light_detector_Example.ino.elf /tmp/arduino_build_476590/Light_detector_Example.ino.eep
/home/rick/arduino-1.8.13/hardware/tools/avr/bin/avr-objcopy -O ihex -R .eeprom /tmp/arduino_build_476590/Light_detector_Example.ino.elf /tmp/arduino_build_476590/Light_detector_Example.ino.hex
Using library SendOnlySoftwareSerial in folder: /home/rick/Arduino/libraries/SendOnlySoftwareSerial (legacy)
/home/rick/arduino-1.8.13/hardware/tools/avr/bin/avr-size -A /tmp/arduino_build_476590/Light_detector_Example.ino.elf
Sketch uses 1666 bytes (20%) of program storage space. Maximum is 8192 bytes.
Global variables use 152 bytes (29%) of dynamic memory, leaving 360 bytes for local variables. Maximum is 512 bytes.
/home/rick/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude -C/home/rick/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf -v -pattiny84 -cstk500v1 -P/dev/ttyUSB0 -b19200 -Uflash:w:/tmp/arduino_build_476590/Light_detector_Example.ino.hex:i

avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "/home/rick/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf"
         User configuration file is "/home/rick/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/ttyUSB0
         Using Programmer              : stk500v1
         Overriding Baud Rate          : 19200
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

avrdude done.  Thank you.

Problem uploading to board.  See http://www.arduino.cc/en/Guide/Troubleshooting#upload for suggestions.

```
* VCC & GND connected
* White wire (Pin 9) -\> D13
* Yellow wire 1 (Pin 8) -\> D12
* Red wire (Pin 7) -\> D11
* Yellow wire 2 (Pin 4) -\> D10
* 10 Capacitor between RST & Gnd

The only change I can remember making was adding a library for SerialOutOnly. But I did a clean install on the Windows and Rasberry with only the ATTiny libraries and it still does the same time.

People missed my comment, so I've uploaded a second photo of the entire breadboard. It is powered there are two wires which were out of frame in the first photo.

# Answer
# Differences in my environment

I don't have a normal Nano on a ATTiny84 on hand at this moment.

For our purposes, I'm using the ATTiny44, which is essentially what you have, only with smaller memories. The Nano that I'm using is Nano Clone that I have retrofitted with a ATMega328PB rather than the regular 328P. To make matters slightly more confusing it is running the regular UNO (rather than NANO) bootloader. The bootloader lies about the chip signature (saying it is 328P) and uses the UNO baudrate 115200 rather than the Nano's 57600. So you will see in my screenshots/examples and menu selections "UNO" rather than "Nano", "328PB" rather than "328P", and "ATTiny44" rather than "ATTiny84."

These differences are inconsequential.

# Build trust in your RESET-defeating mechanism

## Upload reset appearance code

Remove all external circuitry from your Nano. All means ALL. That includes whatever you did to defeat reset as well.

Choose Arduino Nano from the Tools/Boards menu. Choose your Arduino Nano's port from the Tools/Port menu.

Upload the following sketch:

```

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  static bool led_state;
  static size_t toggle_counter;

  if (toggle_counter < 20LU * 6) {
    led_state = !led_state;
    digitalWrite(LED_BUILTIN, led_state);
    delay(50);
    ++toggle_counter;
  }
}

```

The LED should blink rapidly for 6 seconds and then remain off indefinitely.

The Nano's optiboot bootloader blinks the builtin pin 13 LED three times, but it is a very short event and maybe difficult to distinguish form SPI clock action (which also happens on pin 13). By contrast, it's hard to miss the blinking that this code produces.

## Convince yourself that reset appearance code reliable indicates DTR resets.

Open (or Reopen) the serial monitor and see that it does this again. Close and Reopen the serial monitor however many times you want until you feel comfortable that you're seeing clear indication of the board having reset.

## Install your DTR RESET-defeat circuitry for a test.

Unplug your board and install your choice of reset defeating circuitry.

The typical suggestion is a 10uF cap between Arduino Nano RESET and adjacent GND. Make sure you don't have your electrolytic cap backwards.

I frequently use a hard pullup of about 60 Ohms.

Plug the board back in and you should see the LED Blink rapidly for the power-on (not DTR) reset.

## Convince yourself that DTR reset has been defeated.

Open (or Reopen) the serial monitor and see that the LED remains OFF. Reopen the serial monitor however many times and see that the LED stays OFF.

# Upload the arduinoisp.ino sketch

NOTE: At time of writing the current IDE version is 1.8.13. Though, everything said here should be find for old and likely future IDE/arduinoisp.ino releases.

In the IDE, from menu File/Examples/11.ArduinoISP, choose the ArduinoISP sketch. In its current from in IDE 1.8.13 it requires no modifications for a factory-fresh ATTiny84(A) (or pretty much any AVR), that is with its default configuration fuse values.

Break the RESET leg of whatever circuit you chose for defeating DTR reset.

Upload the ArduinoISP sketch.

You should see that the LED does NOT blink rapidly for 6 seconds as it had previously. This should indicate that you have successfully uploaded the arduinoisp.ino sketch.

Reconnect RESET leg of whatever circuit you chose for defeating DTR reset.

# Attempt to program (without target chip attached) to see that you do not get SYNC errors.

Open a new empty sketch.

Choose your target chip's settings from the Boards menu. That is your D. Mellis ATTiny84 "board" should be selected. Or more generally: any compatible "board" from any board support package that supports whatever AVR you want to do this with.

Verify that your Arduino Nano's port is still selected in Tools/Port menu.

From the Tools/Programmer select "Arduino as ISP". Barring some internationalization effort, it should say exactly that. It should NOT say "ArduinoISP" or "ArduinoISP.org". Yes, the Arduino people are usually BAD at picking names.

Choose "Upload using programmer".

You should see a signature check error like this:

```
avrdude: AVR device initialized and ready to accept instructions

An error occurred while uploading the sketch
Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x00ffff
avrdude: Expected signature for ATtiny44 is 1E 92 07
         Double check chip, or use -F to override this check.

avrdude done.  Thank you.

```

You may need to turn on "Verbose" for uploading in preferences.

Because you have not wired anything to the SPI pins the returned device signature will be pure junk. The important thing here is you got a device signature failure and NOT a sync error. A sync error represents failure of avrdude to talk to the arduinoisp.ino sketch's implementation of the STK500v1 programming protocol. What you're seeing here is successful STK500v1 communication (to arduinoiso.ino) reporting a perfectly reasonable failure to identify the chip (that you have not even attached yet).

# Wire your ATTiny84 (or whatever)

Unplug your Nano and wire AVR to it. With the exception of your attempt to use VIN, I didn't notice anything wrong with your wiring.

The ATTiny84 should be wired as:

```
Nano 5V (not VIN) to ATTiny84 pin  1
Nano GND          to ATTiny84 pin 14
Nano PIN 13       to ATTiny84 pin  9
Nano PIN 12       to ATTiny84 pin  8
Nano PIN 11       to ATTiny84 pin  7
Nano PIN 10       to ATTiny84 pin  4

```

Or more broadly for any ISP supporting AVR tiny/mega:

```
Nano 5V (not VIN) to ALL AVR (A)VCCs.
Nano GND          to ALL AVR GNDs
Nano PIN 13       to AVR (U)SCK
Nano PIN 12       to AVR MISO
Nano PIN 11       to AVR MOSI
Nano PIN 10       to AVR RESET

```

You may want to add a pull-up resistor from the target AVR's RESET to its VCC. This should be not needed for use with arduinoisp.ino sketch, but you might want it for running on the breadboard. You may also want to add a decoupling cap between your AVR's VCCs and GND. I've never needed this for just programming on solderless breadboard though.

I don't typically use breadboard power rails when programming AVR devices with single VCC an GND pins.

Generally keep your connection short in any case. They should not be longer than 20 cm really, and can usually be less than half that. Keep them together with the GND where possible. Your SCK signal should probably receive the most care. I don't see anything wrong with the length of your connections.

# Upload

Plug your Nano (and AVR wired to it) back into USB.

Make sure you power light hasn't gone out on the Nano, that it doesn't drop off the USB bus, and nothing feels hot to the touch. That nothing smells odd.

Choose whatever you want to upload. An empty sketch is fine for testing uploading.

Verify that Tools/Port is the port of the Nano. Verify that the programmer is still "Arduino as ISP". Verify that the "board" is still whatever it should be for your target chip (not the Nano).

Choose "Upload using Programmer".

You should get a successful output, that would look something like:

```
/home/user/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/bin/avrdude -C/home/user/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf -v -pattiny44 -cstk500v1 -P/dev/ttyUSB0 -b19200 -Uflash:w:/tmp/arduino_build_656744/sketch_nov12b.ino.hex:i

avrdude: Version 6.3-20190619
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "/home/user/.arduino15/packages/arduino/tools/avrdude/6.3.0-arduino17/etc/avrdude.conf"
         User configuration file is "/home/user/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/ttyUSB0
         Using Programmer              : stk500v1
         Overriding Baud Rate          : 19200
         AVR Part                      : ATtiny44
         Chip Erase delay              : 4500 us
         PAGEL                         : P00
         BS2                           : P00
         RESET disposition             : possible i/o
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65     6     4    0 no        256    4      0  4000  4500 0xff 0xff
           flash         65     6    32    0 yes      4096   64     64  4500  4500 0xff 0xff
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00
           lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00

         Programmer Type : STK500
         Description     : Atmel STK500 Version 1.x firmware
         Hardware Version: 2
         Firmware Version: 1.18
         Topcard         : Unknown
         Vtarget         : 0.0 V
         Varef           : 0.0 V
         Oscillator      : Off
         SCK period      : 0.1 us

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x1e9207 (probably t44)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "/tmp/arduino_build_656744/sketch_nov12b.ino.hex"
avrdude: writing flash (286 bytes):

Writing | ################################################## | 100% 0.46s

avrdude: 286 bytes of flash written
avrdude: verifying flash memory against /tmp/arduino_build_656744/sketch_nov12b.ino.hex:
avrdude: load data flash data from input file /tmp/arduino_build_656744/sketch_nov12b.ino.hex:
avrdude: input file /tmp/arduino_build_656744/sketch_nov12b.ino.hex contains 286 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.22s

avrdude: verifying ...
avrdude: 286 bytes of flash verified

avrdude done.  Thank you.

```

The above was generated using the process described with my slightly different setup.

With everything being correct in the IDE, if you get SYNC error now you probably have a wiring issue that's causing the Nano to fail, interfering with its ability to execute the stk500v1 implementation. This was part of the thinking behind pointing out your VIN connection in the original post:
> 0 votes

# Answer
From your picture, it looks like your ATtiny84 is not powered (connected to unpowered power rails).

The positive (red) and negative (blue) rails on both sides of a breadboard are usually not connected. You should either manually connect the power rails on opposite sides of your breadboard or connect your ATtiny power pins (1 and 14) to the corresponding rail on the other side of your board. See below (apologies for the crude drawing).
> 2 votes

---
Tags: attiny, uploading, arduino-as-isp
---


title: Float array to comma separated string

text:
# Question
Title: Float array to comma separated string
I have a loop command reading temperature sensor data from 8 thermistors and are storing them as floats into an array. Instead of printing to Serial on each iteration, I would like to create a comma separated string of these values and send to serial (in one instance, versus 8). What would be the best way to do this? I have tried `sprintf` commands to no avail.

Thanks in advance!

*Edit:* I would like to also write this string of comma separated values to a MicroSD card slot so I am under the assumption that creating the string once and printing to Serial AND saving to MicroSD card is more efficient than 8 separate iterations

# Answer
> 3 votes
Basic Arduinos have no support for floating point in `sprintf` and related functions.

Instead you have to use `dtostrf()` to build up a string block by block.

However there is no benefit to building a string then outputting to serial "in one instance" compared to outputting the data a bit at a time. Serial is slow. Very slow. When you "output" data to serial you aren't outputting data. You're merely putting the data into a buffer to be sent when it's possible.

In effect, by using multiple `Serial.print()` calls, you're building up the string to send in the Arduino's internal serial TX buffer.

By building the string first all you're doing is creating a buffer to copy data into a buffer to send it through serial. It's redundant, wasteful, and utterly pointless.

# Answer
> 0 votes
Here's a sample program using sprintf() to convert some float data to ASCII in a buffer, format an output string containing that data into another buffer and print the result on the terminal. It's not quite as neat as

```
   "sprintf(buffer, "i=%2d, T=%f\n", i, Temp);

```

It takes three lines and two buffers but it gets the job done:

```
#include <Arduino.h>

float getTemp(void);

void setup()
{
   char tempBuf[10+1], outputBuf[50+1];

   // Open console
   Serial.begin(115200);

   // Print 20 successive temperatures to the terminal
   for( uint8_t i = 1;  i <= 20;  ++i){
      float Temp;

      Temp = getTemp();                 // get the next value
      dtostrf(Temp, 6, 2, tempBuf);     // Convert float to ASCII
      sprintf(outputBuf, "i=%2d, T=%s\n", i, tempBuf); // format the value for printing
      Serial.print(outputBuf);          // print the line to the terminal

      delay(1000L);
   }

}

// Function to return temperatures.
// STUB: The data is made-up.
float getTemp(void){
   static uint8_t n = 0;        // count of results returned

   return( (float)n++ * 1.7 );  // index 'n' times an arbitrary multiplier
}

void loop(void)
{
   ;
}

```

---
Tags: string, array
---


# Question
Title: Issue using micros() instead of millis()
I have two function implementations that I expected to work the same:

```
#define HEAD_STEP_DELAY 1000
unsigned long HeadLastMicros;
void HeadUpdate()
{
    if ((micros()>=HeadLastMicros) && ((micros()-HeadLastMicros)<HEAD_STEP_DELAY)) {
        return;
    }
    HeadLastMicros = micros();
    HeadStep(true);
}

```

and

```
#define HEAD_STEP_DELAY 1
unsigned long HeadLastMillis;
void HeadUpdate()
{
    if ((millis()>=HeadLastMillis) && ((millis()-HeadLastMillis)<HEAD_STEP_DELAY)) {
        return;
    }
    HeadLastMillis = millis();
    HeadStep(true);
}

```

I know that the resolution of `micros()` is limited to about 8us, but I figure given that I have a 1000us wait, both of the above ought to be relatively close to the same behavior. I'm driving a stepper motor from this code, and the stepper that used `micros()` was behaving erratically. I haven't put the scope on it yet, so I don't know for sure, but the torque was significantly less (motor stalled easily) and it sounded wonky.

I'm using an ATMEGA324A together with the MightyCore library.

Is there anything wrong with my approach? Thanks.

EDIT: I did put the scope on it after my initial post, and the period of the micros() code is approximately half the period of the millis() code.

# Answer
> 4 votes
First off, when dealing with a time system that wraps around, don't compare two times. Compare the differences.

Second, cache your function call results if you are going to use it more than once.

Third, if you want a consistent time interval, ask for it. Your current micros() based code could well take 1990µs on some iterations and 1001µs on others.

Fourth, don't use the current time more than once...

Do something like (not specifying millis() or micros()):

```
unsigned long HeadLast; /* This should be initialized somewhere (HeadStart()?),
                           as otherwise things could go weird.
                           On the Arduino platform, initializing to 0
                           may work.  On other systems, time can start anywhen.
                           This caused Microsoft Windows to have trouble after
                           being up for 49 days (started at 0), while X Windows
                           has no such issue (start anywhen).
                           */
void HeadUpdate()
{
    /* compile with -O and this will optimize to a register. */
    unsigned long now = get_time_function();

    /* We don't need to test now >= HeadLast, as time is monotonic. */
    if ((now-HeadLast)<HEAD_STEP_DELAY)) {
        return;
    }
    /* Select the time we consider this to have started at.
       This may well be before the current time. */
    HeadLast += HEAD_STEP_DELAY;
    HeadStep(true);
}

```

---
Tags: timing
---


title: Arduino Connect Long Wires/Cables

text:
# Question
Title: Arduino Connect Long Wires/Cables
i am completely new to hardware programming and micro controllers and i am unable to figure out what search-engine search-term to use to find the answer i am looking for.

# the project

i am working on a project that will use an arduino to control the opening and closing of a window; in a shed. the project i am trying to achieve is further described here.

# the question

i want to know what are the limitations of wire length in an arduino project and what do i need to have to be able to extend that wire length capacity?

i currently have those "common" 20cm wires you get off ebay... which i dont think will be long enough.

# Answer
The stepper motor 28byj-48 seems to be a 5V motor (datasheet). I've seen it being used with a A3967 driver, which means that it does not draw more than 750 mA of current.

I'll go with the length you mentioned in the comments:

> for this example lets say 3m

The rest is Physics: the resistance of a wire is

```
R = p * l/A

```

where l is the length of the wire and A is the area (dependent on the diameter).

A voltage drop calculator can now tell you how much voltage is left at the end of the wire.

I would have estimated a 0.75 mm² (AWG 18), but you might even be fine with 0.5mm² (AWG 20) according to the calculator. But: better safe than sorry.

---

Also from the comments:

> i have micro servo SG90 working as expected. my expectation is that the large one will work similarly (of course with more power requirements)

A stepper motor needs a totally different setup than a servo. The servo is connected with simple 4 pins, the stepper needs a motor driver (H-bridge). Connecting the stepper motor directly to the Arduino may destroy your board.
> 1 votes

# Answer
Wire length is hard to define. It depends if it is in your case powering a motor or has control signals connected directly to the Arduino. Take a good look at the answer provided by Thomas Weller, by sizing the wire appropriately you can get extremely long lines for motors and other types of loads, you have some voltage to work with. The wires connected to the Arduino are also antennas and can pick up a lot of nasties in a very short run, especially around motors. These antennas on the inputs are high impedance making them more sensitive to noise. Regardless of which wires you are looking at they need to be properly conditioned for your environment and application.
> 0 votes

---
Tags: arduino-uno, wires
---


# Question
Title: Best way to determine if a 5 gallon water jug is getting empty
I have an espresso machine that gets its water from one of those 5 gallon blue water bottles (I would plumb it, but our water here is WAAAAY too hard).

If I ever accidentally let the bottle run out of water, the rotary pump in the espresso machine will be ruined, which would be a costly mistake.

I know that I can install some sort of magnetic float sensor inside the water bottle, but since I have to change it out once every few weeks, having another thing inside the bottle would make changing it out harder, and microbial contamination more likely. The pump that pumps water out of the bottle forms a tight seal at the lid, and anything running under it or through it would compromise that seal.

Is there something I could use to detect if the water level is low from the outside of the bottle? Like a laser sensor?

# Answer
**Using a Force Sensor to Measure a Quantity of Water**

To satisfy your requirement of having the sensor on the exterior of the water container, I would recommend using a force sensor to weigh the bottle at set intervals. A force sensor, such as the FlexiForce A401, is a type of resistor that changes resistance in response to the amount of force applied. While not as accurate as a scale, it should provide enough accuracy (+-3% according to the datasheet) for the application described.

The basic procedure would be to hook up the force sensor to the Arduino and first measure the resistance with an empty bottle, then measure again with a full bottle. This will give you an idea of the force that your specific platform is actually applying to the sensor, and you can then fine tune the voltage (as per the datasheet) for your installation.

A basic tutorial using a similar force sensor with an Arduino can be found here.

**Other Possibilities**
> 10 votes

# Answer
Another option is to measure the current going into the pump; when it runs dry, the current goes up, which generates the heat that fries the pump.

Or measure the temperature on the pump, but measuring the current will detect the beginning of the pump's meltdown, while the temperature may only detect the middle or end of the meltdown. :-(

Or install a current limiter or breaker inline with the pump, just in case everything else fails. :-)
> 5 votes

# Answer
I think you want a "liquid level switch", possibly also known as a "fluid switch" ... I realize this may not satisfy your requirements, but this is one way to solve the problem for \>$10. I would probably hack something together that would put this sensor inline to the bottle. it's probably too hacky, but you could have a disc of plywood the same diameter as the water bottle, with a pipe fitting in the middle where you could mount the switch, so that the water bottle routes water through it so that when it runs low, it would trigger the switch before it runs to the pump.
> 4 votes

# Answer
Whenever light follows a path that takes it from one material to the next, it makes a sharp turn. However, the angle of deviation is different based on the characteristics of the materials.

You can use this principle.

Set a LED on the level that you want to be your lowest. When the water is full, its light will follow a certain path across the container and reach its light sensor. When the water gets bellow the level, it will miss it (or you could set up a second sensor if you really wanted to).

Based on this info, you can know when the water gets too low. Just take appropriate action.

Watch out on the recommendation to measure the water used. This could be dangerous. You may have a leakage (either now or later) or somebody might tip the machine and spill some water. In either case your water level would be lower than the level you calculate, which would certainly result in your espresso machine be ruined.
> 4 votes

# Answer
It seems to me that if you have pumped out 4.9 gallons you know the jug is close to empty. If an inline flow meter between the pump and the espessso maker is out due to water contact, then maybe you know that an espresso shot takes x amount of water, and once one has called for y shots (and calculated x times y) one is in the danger zone of running out of water?
> 3 votes

# Answer
Honestly - you're overthinking this.

A dipstick or a float would be all you need. Once the water level drops below your minimum, the float moves down with the water level and pulls a switch or allows a LDR to see through a hole. Then do something like turn on a light.

Less is more.
> 3 votes

# Answer
**Lasers**

If your blue water bottles are like mine, they are transparent.

Here's what I would try first:

I would get a cheap laser, and shine the light horizontally through the bottle. I would aim the laser through a short chord -- not pointed directly through the middle of the bottle; perhaps 1/8 turn to the left of center.

```
    -------
L../.......\..........S1
  /         \
 |     o     |        S2
  \         /
   \       /
    -------
top-down view

```

When the bottle is empty, the laser beam will shoot pretty much straight through the bottle -- I would put one photo-sensor S1 there.

When the bottle is not quite empty, the laser beam will bend (refract) -- for redundancy, I would put another photo-sensor S2 there.

As long as the Arduino sees the laser hitting S2 alone, there's still some water in the bottle, at least up to the level of the laser -- turn on the green light.

Anything else -- light detecting only at S1, or nothing detected at either sensor, or light detected at both sensors (yes, it can happen) -- something doesn't seem right, better have the Arduino turn off the green light and turn on the red light.

I would start with the simplest thing that could possibly work. If I'm lucky, it might work. If not, there's lots of little tricks involved in getting the light where you want it to go. There's also lots of tricks for blocking sunlight, etc. from going where you don't want it to go. Little black tubes, red plastic filters, pulsing the laser at a few kHz, collimating lenses, lock-in amplifiers, etc.

There seem to be lots of tutorials that describe how to detect a laser using Arduino -- see

(This would probably work just as well with a medium-power LED or "infrared LED" and some careful optical focusing and alignment. But -- lasers!)
> 3 votes

# Answer
you can use a metal detector like setup using the fact that electronic permittivity of water is different than that of air

have a coil with AC next to the bottle and an unpowered coil inside it

then by measuring the current and/or voltage generated by the second coil you can sense the difference between with water next to it and without
> 3 votes

# Answer
Try a non contact water sensor: https://www.dfrobot.com/product-1493.html I use them and they work very well. You stick it on the outside of the jug, If it falls off the jug will show empty protecting your pump. The ones I use are similar and have an open collector, so no micro is required. I think I paid about $6 a year or so ago. They make adjustable ones. Nice point nothing touches the water or can contaminate it.
> 0 votes

---
Tags: sensors, system-design
---


title: UltraSonic sensor in rain?

text:
# Question
Title: UltraSonic sensor in rain?
I am onto a simple project with Arduino, SR04 and a buzzer for "Car reverse parking assistance". The aim here is to make a buzz when the car gets too close to the objects.

I was thinking what if it's raining when a person is driving (assuming I somehow achieved to water proof the sensor) - will the buzzer make continuous sounds?

Is there any alternative solution for ultrasonic sensors?

# Answer
> 6 votes
> will the buzzer make continuous sounds

If you mean the sensor will detect the rain drops in the air Nop it's tiny to read it in the air But if there is drops on the sensor your sensor will not gives you the right reading

There is a water proof ultrasonic sensors available.

I am working on water level devices, after long path of searching in different ultrasonic sensors and after I tried a lot of method like using water proof Cloth, I found the best way is using water proof sensors PLUS water proof cloth.

water proof sensors work perfectly in high humidity but at the same time if there is a water drop on the sensor the reading will be different, and for that some cars manufacturers used not only one sensor, to avoid the errors. and calculate the differences.

The left car used old technology with separate sensors, but that's make errors the only good thing was to detect more things, in the next generation they mix them together.

water proof cloth will make the water drops not stuck at the sensor, but you will need to replace it every 5-6 months. "in your case because the sun will destroy the cloth" in my case and because my sensor inside tanks that's will least more.

I tried to spray the sensor with a different material to make my sensor not catch any water drops, it dose not work too.

And to make my cheap sensor water proof, I tried to use ceramic layers, and that's not work too, they use it with ultrasonic fog maker, these layers not work with cheap ultrasonic sensors, it's need a lot of power to vibrate it and different frequency. and of course you need to replace the layers "depending on the environment"

If you find ultrasonic car sensor with special material for water drops just let me know, I am searching on that too.

**NOTE** These days car manufacturer use different ways, in the past the cover was vibrate itself and made from aluminum, now they cover it and make different filters to ignore the plastic cover, How?! maybe it's different plastic or material maybe they find away to vibrate the plastic! sorry I could not find the secret.

# Answer
> 1 votes
It would probably be easier to use an IR distance sensor. That would also be easier to waterproof.

# Answer
> 0 votes
Just a thought, a lot of cars use them, why not try your local salvage yard you may be able to get them on the cheap.

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