# Question
Title: Arduino FIFO queue for with potentiometer values and 7 segment display
As of now I have code that takes a value from a potentiometer and maps it from 0-9. Based on this mapped value a number will be displayed on the seven segment display.

Currently, if I quickly turn the pot completely then back to zero it will show everything very quickly and then show 0 until I change the pot value again. What I am trying to do is make it so if it's quickly turned completely then back to 0, after a second it will display all the number from 0-9 then back down to 0, each for a second.

I was given a hint to use arrays to create a FIFO queue but I am not sure how to go about doing this and I have been stuck on this for a while. Here's my code:

```
// Pin 2-8 is connected to the 7 segments of the display.
// Pin 0 is for potentiometer
int potval;
int pinA = 2;
int pinB = 3;
int pinC = 4;
int pinD = 5;
int pinE = 6;
int pinF = 7;
int pinG = 8;
int i;

// the setup routine runs once when you press reset:
void setup() {
  // initialize the digital pins as outputs.
  pinMode(pinA, OUTPUT);
  pinMode(pinB, OUTPUT);
  pinMode(pinC, OUTPUT);
  pinMode(pinD, OUTPUT);
  pinMode(pinE, OUTPUT);
  pinMode(pinF, OUTPUT);
  pinMode(pinG, OUTPUT);
}

void loop() {
  potval=map(analogRead(A0),0,921,0,9);
  if (potval==0){
    //0
    digitalWrite(pinA, LOW);
    digitalWrite(pinB, LOW);
    digitalWrite(pinC, LOW);
    digitalWrite(pinD, LOW);
    digitalWrite(pinE, LOW);
    digitalWrite(pinF, LOW);
    digitalWrite(pinG, HIGH);
  }
  if (potval==1){
    //1
    digitalWrite(pinA, HIGH);
    digitalWrite(pinB, LOW);
    digitalWrite(pinC, LOW);
    digitalWrite(pinD, HIGH);
    digitalWrite(pinE, HIGH);
    digitalWrite(pinF, HIGH);
    digitalWrite(pinG, HIGH);
  }
  if (potval==2){
    //2
    digitalWrite(pinA, LOW);
    digitalWrite(pinB, LOW);
    digitalWrite(pinC, HIGH);
    digitalWrite(pinD, LOW);
    digitalWrite(pinE, LOW);
    digitalWrite(pinF, HIGH);
    digitalWrite(pinG, LOW);
  }
  if (potval==3){
    //3
    digitalWrite(pinA, LOW);
    digitalWrite(pinB, LOW);
    digitalWrite(pinC, LOW);
    digitalWrite(pinD, LOW);
    digitalWrite(pinE, HIGH);
    digitalWrite(pinF, HIGH);
    digitalWrite(pinG, LOW);
  }
  if (potval==4){
    //4
    digitalWrite(pinA, HIGH);
    digitalWrite(pinB, LOW);
    digitalWrite(pinC, LOW);
    digitalWrite(pinD, HIGH);
    digitalWrite(pinE, HIGH);
    digitalWrite(pinF, LOW);
    digitalWrite(pinG, LOW);
  }
  if (potval==5){
    //5
    digitalWrite(pinA, LOW);
    digitalWrite(pinB, HIGH);
    digitalWrite(pinC, LOW);
    digitalWrite(pinD, LOW);
    digitalWrite(pinE, HIGH);
    digitalWrite(pinF, LOW);
    digitalWrite(pinG, LOW);
  }
  if (potval==6){
    //6
    digitalWrite(pinA, LOW);
    digitalWrite(pinB, HIGH);
    digitalWrite(pinC, LOW);
    digitalWrite(pinD, LOW);
    digitalWrite(pinE, LOW);
    digitalWrite(pinF, LOW);
    digitalWrite(pinG, LOW);
  }
  if (potval==7){
    //7
    digitalWrite(pinA, LOW);
    digitalWrite(pinB, LOW);
    digitalWrite(pinC, LOW);
    digitalWrite(pinD, HIGH);
    digitalWrite(pinE, HIGH);
    digitalWrite(pinF, HIGH);
    digitalWrite(pinG, HIGH);
  }
  if (potval==8){
    //8
    digitalWrite(pinA, LOW);
    digitalWrite(pinB, LOW);
    digitalWrite(pinC, LOW);
    digitalWrite(pinD, LOW);
    digitalWrite(pinE, LOW);
    digitalWrite(pinF, LOW);
    digitalWrite(pinG, LOW);
  }
  if (potval==9){
    //9
    digitalWrite(pinA, LOW);
    digitalWrite(pinB, LOW);
    digitalWrite(pinC, LOW);
    digitalWrite(pinD, HIGH);
    digitalWrite(pinE, HIGH);
    digitalWrite(pinF, LOW);
    digitalWrite(pinG, LOW);
  }
}

```

# Answer
> 1 votes
Without seeing the code it is bit difficult to help. Please edit your answer and include the relevant parts of the code, otherwise we will end up (re)writing your code for you.

Hint: why not, when you detect a change in the pot, take the new reading, and then count down/up *slowly* (at the rate that you desire) from the currently displayed reading to the new measured reading - using a `for` loop, which contains a `delay()`? With each iteration of the loop you can display the new value. Easy!

### However, this sounds like a terrible idea

Note that your code won't do anything else whilst the display is incrementing and decrementing, using this method. So, if you were to spend a lot of time twiddling with the knob, then the code wouldn't get much time to actually do any real work, apart from displaying the updated value.

In order for your code to do real work, whilst displaying the new updated value, you would either need interrupts, or integrate the display updating procedure into the `loop()`, such that each iteration of the `loop()` updates the display (or upon each *n* iterations of `loop()`, as `loop()` will probably be looping to quickly. You will probably need to use `millis()`).

NOTE: From a UX aspect, although it all sounds very 1960's-James-Bond-evil-guy-equipment, the whole notion of the displayed value slowly following the actual location of the knob sounds, at best, extremely infuriating, if not down right dangerous (depending upon the context). Human feedback should be as fast as possible. Else the user will constantly be turning the knob to reach the value that they which to achieve, when in fact they have already passed that value, and may be over compensating, and it is just the fancy display graphics that is showing the wrong value.

Assuming that the knob is controlling something else (actuator, motor, heater, etc.), and not just a pretty display in itself, *unless*, you are actually outputting the delayed displayed digital value, and not the knob's actual current analogue value, I would seriously recommend against doing this.

I may be wrong, and it would probably require a separate question on SE.UX, although, I would imagine that it has been asked already.

# Answer
> 0 votes
First of all, that way of writing the displays is quite horrible to me ;) Better to use a matrix (and, please, no ints for small variables like pin numbers, and make them constant). This is the code fixed with these improvements:

```
// Pin 2-8 is connected to the 7 segments of the display.
// Pin 0 is for potentiometer
int potval;
const byte pinA = 2;
const byte pinB = 3;
const byte pinC = 4;
const byte pinD = 5;
const byte pinE = 6;
const byte pinF = 7;
const byte pinG = 8;

byte Matrix[][7] = { { LOW , LOW , LOW , LOW , LOW , LOW , HIGH}, // potval 0
                     { HIGH, LOW , LOW , HIGH, HIGH, HIGH, HIGH}, // potval 1
                     ... fill with the other rows ...
                     { LOW , LOW , LOW , HIGH, HIGH, LOW , LOW }  // potval 9
                    };

// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pins as outputs.
pinMode(pinA, OUTPUT);
pinMode(pinB, OUTPUT);
pinMode(pinC, OUTPUT);
pinMode(pinD, OUTPUT);
pinMode(pinE, OUTPUT);
pinMode(pinF, OUTPUT);
pinMode(pinG, OUTPUT);
}

void loop() {
    potval=map(analogRead(A0),0,921,0,9);

    digitalWrite(pinA, Matrix[potval][0]);
    digitalWrite(pinB, Matrix[potval][0]);
    digitalWrite(pinC, Matrix[potval][0]);
    digitalWrite(pinD, Matrix[potval][0]);
    digitalWrite(pinE, Matrix[potval][0]);
    digitalWrite(pinF, Matrix[potval][0]);
    digitalWrite(pinG, Matrix[potval][0]);
}

```

You can further improve it by not having seven variables but only an array to iterate over, but .. ok, let's keep this.

Ok, now you want to do a "slow movement". In order to do this you can use a variable to track the current position, and let it move towards the target value once every XX ms. This is the approach used, for instance, in CNCs and 3d printers movements.

```
// Pin 2-8 is connected to the 7 segments of the display.
// Pin 0 is for potentiometer
int potval;
const byte pinA = 2;
const byte pinB = 3;
const byte pinC = 4;
const byte pinD = 5;
const byte pinE = 6;
const byte pinF = 7;
const byte pinG = 8;

unsigned long int prevMillis;
const int delayBetweenMovement = 200;

byte Matrix[][7] = { { LOW , LOW , LOW , LOW , LOW , LOW , HIGH}, // potval 0
                     { HIGH, LOW , LOW , HIGH, HIGH, HIGH, HIGH}, // potval 1
                     ... fill with the other rows ...
                     { LOW , LOW , LOW , HIGH, HIGH, LOW , LOW }  // potval 9
                    };

// the setup routine runs once when you press reset:
void setup() {
// initialize the digital pins as outputs.
pinMode(pinA, OUTPUT);
pinMode(pinB, OUTPUT);
pinMode(pinC, OUTPUT);
pinMode(pinD, OUTPUT);
pinMode(pinE, OUTPUT);
pinMode(pinF, OUTPUT);
pinMode(pinG, OUTPUT);
prevMillis = millis() - delayBetweenMovement;
}

void loop() {
    if ((millis() - prevMillis) >= delayBetweenMovement)
    {
        prevMillis += delayBetweenMovement;

        potval=map(analogRead(A0),0,921,0,9);
        static int CurrentPotVal = potval;

        if (potval > CurrentPotVal)
            CurrentPotVal++;
        if (potval < CurrentPotVal)
            CurrentPotVal--;

        digitalWrite(pinA, Matrix[CurrentPotVal][0]);
        digitalWrite(pinB, Matrix[CurrentPotVal][0]);
        digitalWrite(pinC, Matrix[CurrentPotVal][0]);
        digitalWrite(pinD, Matrix[CurrentPotVal][0]);
        digitalWrite(pinE, Matrix[CurrentPotVal][0]);
        digitalWrite(pinF, Matrix[CurrentPotVal][0]);
        digitalWrite(pinG, Matrix[CurrentPotVal][0]);
    }
}

```

The `delayBetweenMovement` constant makes a delay between the readings. With this method, if you quickly turn it to 9 and then to 0 you will not arrive to 9. For instance you put a 9, the display starts doing 0..1..2..3, then you switch to 0 and the count will not reach 9, but start going back to 0. Reaching 9 will require some more structures; if you need it ask and I'll make some modifications

EDIT: as requested, here is a version that can memoryze up to 20 states and reproduce them. If you need them just increase the FIFO size.

Note: I haven't tested these programs. In the other two I was pretty confident I hadn't made any major bug, but this one is a bit more complicated. There can be some bugs left..

```
// Pin 2-8 is connected to the 7 segments of the display.
// Pin 0 is for potentiometer
const byte pinA = 2;
const byte pinB = 3;
const byte pinC = 4;
const byte pinD = 5;
const byte pinE = 6;
const byte pinF = 7;
const byte pinG = 8;

unsigned long int prevMillis;
const int delayBetweenMovement = 200;

byte Matrix[][7] = { { LOW , LOW , LOW , LOW , LOW , LOW , HIGH}, // potval 0
                     { HIGH, LOW , LOW , HIGH, HIGH, HIGH, HIGH}, // potval 1
                     ... fill with the other rows ...
                     { LOW , LOW , LOW , HIGH, HIGH, LOW , LOW }  // potval 9
                    };

const byte FifoSize = 20;
byte TargetFifo[FifoSize];
byte FifoHead = 0, FifoTail = 0;

byte potval;

// the setup routine runs once when you press reset:
void setup() {
    // initialize the digital pins as outputs.
    pinMode(pinA, OUTPUT);
    pinMode(pinB, OUTPUT);
    pinMode(pinC, OUTPUT);
    pinMode(pinD, OUTPUT);
    pinMode(pinE, OUTPUT);
    pinMode(pinF, OUTPUT);
    pinMode(pinG, OUTPUT);
    prevMillis = millis() - delayBetweenMovement;
}

byte FifoAvailableForWrite()
{
    if (FifoTail > FifoHead)
        return (FifoSize - FifoTail + FifoHead);
    else
        return (FifoHead - FifoTail);
}

void loop() {
    potval=map(analogRead(A0),0,921,0,9);
    static byte prevPotVal = potval;
    static int CurrentPotVal = potval;

    if ((prevPotVal != potval) && (FifoAvailableForWrite() > 1))
    {
        TargetFifo[FifoTail] = potval;
        prevPotVal = potval;
        FifoTail = (FifoTail + 1) % FifoSize;
    }

    if ((millis() - prevMillis) >= delayBetweenMovement)
    {
        prevMillis += delayBetweenMovement;

        if (FifoHead != FifoTail)
        {
            if (TargetFifo[FifoHead] > CurrentPotVal)
                CurrentPotVal++;
            if (TargetFifo[FifoHead] < CurrentPotVal)
                CurrentPotVal--;
            while (TargetFifo[FifoHead] == CurrentPotVal)
                FifoHead = (FifoHead + 1) % FifoSize;
        }

        digitalWrite(pinA, Matrix[CurrentPotVal][0]);
        digitalWrite(pinB, Matrix[CurrentPotVal][0]);
        digitalWrite(pinC, Matrix[CurrentPotVal][0]);
        digitalWrite(pinD, Matrix[CurrentPotVal][0]);
        digitalWrite(pinE, Matrix[CurrentPotVal][0]);
        digitalWrite(pinF, Matrix[CurrentPotVal][0]);
        digitalWrite(pinG, Matrix[CurrentPotVal][0]);
    }
}

```

---
Tags: arduino-nano, potentiometer
---


# Question
Title: How do I measure speed and manipulate the speed based on distance covered?
I'm doing a project on arduino. I'm using a online simulator to design the circuit. I have a dc motor. How do we measure the rpm,speed at that rpm,distance covered by the motor in a given time. For example,

When motor starts, it starts rotating slowly and gradually increases it's RPM. When it covered a distance of 50 meters, the motor slows down and stops. After 10 seconds, the motor starts again at that 50 meter point and goes to 100 meters point and stops. Like this it stops for every 50m. For this we need to keep track of the distance travelled by motor and control it's speed.

How do I achieve the above working. I have tried alot and verified many tutorials but couldn't understand what to do. Please help me out. (The online simulator I'm using has a L293D motor driver, IR sensor and a ultrasonic distance sensor in it's component list.)

# Answer
> 0 votes
They key point here is to know the distance. The simplest way of finding that distance is to know how many times the wheel has completed an entire revolution. Multiply that number of revolutions by the circumference of your wheel and you have the distance the wheel has covered.

Depending on how precisely you want to measure that distance you may get away with a simple magnet and hall effect sensor. Place the magnet on the wheel, and locate the hall effect sensor so the magnet passes it close enough to trigger. Each pulse from the sensor is one rotation of the wheel.

You could increase the resolution by adding more magnets - 4 magnets set at 90° points around the wheel will give you a pulse for each quarter of a revolution (so multiply pulses by a quarter of your circumference).

If you want better resolution and accuracy you could attach a rotary encoder to the axle of the wheel. This, depending on the encoder, can give you far better resolution than simple magnets. Some will also give you the angle the wheel is at (not that such information would be of interest in this project).

---
Tags: arduino-uno, sensors, arduino-ide, motor
---


# Question
Title: sizeof() on custom library constructor returns wrong result
I made a custom library (let's call it `DigitalOutput.h`) to learn a bit about librairies and to simplify my work. Here is the basic constructor in the *.h* file:

```
DigitalOutput(uint8_t pin);

```

Here is the code in the *.cpp* file :

```
DigitalOutput::DigitalOutput(uint8_t pin)
{
    _pin    = pin;
    _status = LOW;
    pinMode(pin, OUTPUT);
}

```

So very simple stuff. Now, in my program, I call the function the usual way:

```
DigitalOutput LED(7); // pin #7 will be configured
                      // as an output pin to control the LED

```

Now the issue comes when I create an array and then use the `sizeof()` function.
Here is the code from my program (using an Arduino Mega):

```
DigitalOutput   LED_array[] = {22,23,24,25,26,27,28,29,
                               30,31,32,33,34,35,36,37};

```

So, the array contains **16** elements. But when I do for instance...

```
#define         LED_NUMBER    sizeof(LED_array)
//...
void setup(){
    //...
    Serial.println(sizeof(LED_array));
    Serial.println(LE_NUMBER);
}

```

...I get **160** as a result in both cases instead of **16**...

So I end up doing a weird `#define LED_NUMBER sizeof(LED_array) / 10` in order to get the proper result which is then used throughout the program. Any idea of why this isn't working right?

# Answer
> 4 votes
It is working perfectly correctly.

`sizeof` doesn't return the number of elements in an array, it returns *the number of bytes the array takes up*. Since each entry in your array is an instance of your DigitalOutput class, the size is the number of elements multiplied by the size of the class - in this case 10 bytes.

To get the number of elements you must divide the number of bytes by the size of one element:

```
int numEles = sizeof(LED_array) / sizeof(DigitalOutput);

```

or

```
int numEles = sizeof(LED_array) / sizeof(LED_array[0]);

```

# Answer
> 0 votes
You are checking the size of the object (DigitalOutput). This object contains:

* \_pin
* \_status

And this probably results in 10 bytes per object, times 16 objects = 160 bytes.

So you are not creating an (unsigned byte) array which is 16 bytes.

---
Tags: library, array
---


# Question
Title: MIDI output circuit behaving incorrectly when not connecting with USB
I recreated this circuit to send MIDI notes to my MIDI-USB adapter to my computer.

It works fine when the Arduino is powered via USB. When I power the Arduino Nano with 9v on Vin however, the output is gibberish. It just spams the input monitor on my computer with random midi commands. For testing I used this code:

```
    #include <MIDI.h>

    MIDI_CREATE_DEFAULT_INSTANCE();

    static const unsigned ledPin = 13;
    bool on = false;
    void setup()
    {
        pinMode(ledPin, OUTPUT);
        MIDI.begin(MIDI_CHANNEL_OFF);
    }

    void loop()
    {
        digitalWrite(ledPin, on);
        on = !on;
        MIDI.sendControlChange(12, 127, 1);
        delay(1000);
    }

```

The Arduino itself seems to be working fine when powered with 9v (note that I tested with both a wall power supply as well as a 9v battery) as the TX-led still flashes briefly and the built-in led also toggles nicely.

At first I blamed my power supply and/or my power supply, but both work fine on my MIDI-keyboard so I don't think they are to blame.

Worth mentioning: When the Arduino was powered by Vin, I also as a test plugged in the USB-cable in the Arduino, But only touched the connector on the USB-port on my computer. I then received the correct notes.

Because of this I think it is an issue with the grounding. What am I doing wrong?

EDIT: Thanks for the response guys. I think I diagnosed my problem incorrectly. I'm using a cheap Chinese MIDI-adapter which I pried open, and it lacks an optocoupler. I'm getting a decent MIDI adapter now. Thanks!

# Answer
> 1 votes
If you are connecting multiple devices then they have to share a common ground.

I only know about British mains sockets, they all have an earth pin connecting to a common ground, so usually you are OK.

Plug in transformers 'wall warts' sometimes don't connect to ground, the give away is the plastic pin. In this case you need to provides a separate earth and connect it to the rest of the equipment.

PCs normally have a good earth and this is passed by the USB to connected devices. So "the Arduino always works when it is connected to the PC" is usually a good indicator of an earthing issue.

I think your keyboard uses a wall wart and therefore when you remove the USB they both float. Touching the USB lead to the Arduinos USB socket grounds it all again.

So it looks like you diagnosed the fault correctly :)

---
Tags: serial, power, usb, midi
---


# Question
Title: Using SoftwareSerial library with EnableInterrupt
I'm working on a project that involves both serial communication and GSM transmission. I'm using the SoftwareSerial library for RS232 communication, and GSM (SMS) transmission:

* TX and RX for RS232 : Arduino Uno D3 and D4 pins
* TX and RX for GSM module : Arduino Uno D7 and D8 pins

The project requires also the use of the EnableInterrupt library to enable interrupt in Arduino's analog pins, meaning that I DON'T USE EnableInterrupt for all of the Arduino's digital pins including D3, D4, D7 and D8.

However when running the program that includes the two libraries, this long error message shows up :

```
libraries\SoftwareSerial\SoftwareSerial.cpp.o (symbol from plugin): In function `SoftwareSerial::read()':

(.text+0x0): multiple definition of `__vector_3'

sketch\sketch_jun14a.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here

libraries\SoftwareSerial\SoftwareSerial.cpp.o (symbol from plugin): In function `SoftwareSerial::read()':

(.text+0x0): multiple definition of `__vector_5'

sketch\sketch_jun14a.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here

libraries\SoftwareSerial\SoftwareSerial.cpp.o (symbol from plugin): In function `SoftwareSerial::read()':

(.text+0x0): multiple definition of `__vector_4'

sketch\sketch_jun14a.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here

collect2.exe: error: ld returned 1 exit status

exit status 1
Erreur de compilation pour la carte Arduino/Genuino Uno

```

Clearly, there is a conflict between the two libraries, Is there any solution to remove this conflict and run the two libraries together ?

Thanks in advance !

# Answer
* SoftwareSerial uses *all* PinChange interrupts.
* EnableInterrupts uses *all* PinChange interrupts.

You can see the conflict.

All you can do is to modify *both* libraries to remove support for the interrupts you don't need it to support - that way you share out the responsibility for handling the different interrupts between the two libraries.
> 1 votes

# Answer
I would suggest using different software serial libraries and pins. To apply this answer, I would suggest this configuration:

* Connect your RS232 device to pins 0 & 1 and use `Serial`
* Connect your GSM device to pins 8 & 9 and use `AltSoftSerial` (it must use those pins).

If you do not send anything *to* the RS232 device, you can still use `Serial` for debug statements. Don't even connect the TX pin to the RS232 device. You will have to disconnect the RX pin to upload new sketches over USB. Or, if the RS232 device receives formatted commands, it would ignore debug statments that don't look like commands. This has the added benefit that the Serial Monitor window will display the commands you do send to the RS232 device.

If you *really* need to use 3 serial ports, you will have to use this configuration:

* Use `Serial` for whatever
* Connect the RS232 or GSM device to pins 8 & 9 and use `AltSoftSerial`
* Connect the other device to any two pins and use my NeoSWSerial.

`AltSoftSerial` is more efficient at transmitting than `NeoSWSerial`, so use `AltSoftSerial` for the device to which you send the most data. `NeoSWSerial` is limited to baud rates 9600, 19200 and 38400, so that may be a consideration.

`SoftwareSerial` is a terrible choice, because it disables interrupts for long periods of time, it can only listen to one port at a time, and it cannot transmit and receive at the same time.

`AltSoftSerial` and `NeoSWSerial` do not have these limitations, and they can co-exist to give you 2 extra serial ports. You should also be aware the `NeoSWSerial` disables interrupts while transmitting (not receiving). `AltSoftSerial` uses one of the TIMER resources, while `NeoSWSerial` simply uses the `millis()` timer.

### ADDENDUM

To answer your original question about using the `EnableInterrupt` library at the same time as a software serial library:

If you are using the first configuration above, `AltSoftSerial` will not conflict with `EnableInterrupt`.

If you are using the second configuration, `NeoSWSerial` **will** conflict with `EnableInterrupt`. For this possibility, `NeoSWSerial` has an option to disable using all the Pin Change Interrupt ISRs. Uncomment this line and call the NeoSWSerial::rxISR from the appropriate `enableInterrupt()` callback function:

```
#include <NeoSWSerial.h>
NeoSWSerial oneDevice( RX_PIN, TX_PIN );

void myISR()
{
  NeoSWSerial::rxISR( *portInputRegister( digitalPinToPort( RX_PIN ) ) );
}

void setup()
{
  enableInterrupt( RX_PIN, myISR, CHANGE );
}

```

This puts `EnableInterrupt` in charge of the ISRs. If you want to try `NeoSWSerial`, it is available from the Arduino IDE Library Manager, under the menu **Sketch -\> Include Library -\> Manage Libraries**.
> 0 votes

---
Tags: arduino-uno, interrupt, softwareserial
---


# Question
Title: What datatype is the names of the analog inputs?
I am writing a code for an automatic garden, and for this, I will use an array of sensors. I want to represent each plant as a class, and so one of the private variables will then be the sensorID, the name of the input on the analog inputs. But these are called 'A0' 'A1' and so forth, so I am wondering what datatype they are?

```
class Plant{
private:
String name;
??? sensorId;
...
public:
readSensor(??? sensorId);
...
};

```

I want to standardize this so I don't have to physically write 'A0' or 'A1' each time I need to read the sensor.

# Answer
They're `uint8_t`:

```
static const uint8_t A0 = 14;
static const uint8_t A1 = 15;
static const uint8_t A2 = 16;
static const uint8_t A3 = 17;
static const uint8_t A4 = 18;
static const uint8_t A5 = 19;
static const uint8_t A6 = 20;
static const uint8_t A7 = 21;

```

Those are defined in the `pins_arduino.h` file in the board's variant folder.
> 2 votes

---
Tags: data-type
---


title: Countdown sometime stop

text:
# Question
Title: Countdown sometime stop
I've made a game with 3 countdowns and 1 global countdown.

* When we start, the global one, go from 45:00 to 00:00.
* The 1 go from 15:00 to 00:00 and if it reach 00:00:
* The 2 start and go from 15:00 to 00:00 and it if reach 00:00:
* The 3 start and go from 15:00 to 00:00

If you win little game, you can stop a countdown and start the next. If you win the 3 games, you stop the 3 countdown and the global too.

But sometime, my 2nd countdown stop itself, sometime at 13:58 or 10:54…

Is it possible that the **millis()** cause that bug ? Do you have an idea to improve my code and fix that ?

Fun fact : Sometime countdowns go from 01 to 60 instead of 00 to 59……

Sorry for my english, i'm not native speaker.

```
//14-06-17 Correctifs LED
//10-06-17 Correctif Jeu 1

#include "musical_notes.h"
#include "TM1637.h"
#include "SevenSegmentTM1637.h"
#include "OnewireKeypad.h"
#include "Password.h"

SevenSegmentTM1637    displaya(4, 5);
SevenSegmentTM1637    displayb(6, 7);
SevenSegmentTM1637    displayc(8, 9);
SevenSegmentTM1637    displayd(50, 51);

TM1637 tm1637a(50, 51); //TIMER GLOBAL 45
TM1637 tm1637b(4, 5); //TIMER 1 15
TM1637 tm1637c(6, 7); //TIMER 2 15
TM1637 tm1637d(8, 9); //TIMER 3 15

char KEYS[] = {
  '1', '4', '7', '*',
  '2', '5', '8', '0',
  '3', '6', '9', '#',
  'A', 'B', 'C', 'D'
};
OnewireKeypad <Print, 16 > KP(Serial, KEYS, 4, 4, A0, 4700, 1000, ExtremePrec );
Password password = Password( "8751" );

//PREMIER JEU
int checkbranche = 23;
int checkbrancheb = 22;
int checkbranchec = 24;
int state = HIGH;
int reading;
int readingb;
int readingc;
int previous = LOW;
int previousb = LOW;

int readingstart;
int checkstart = A1;

int speakerPin = 52;
int runOPEN = 0;
int runJEU1 = 0;
int runJEU2 = 0;
int runJEU3 = 0;
int runFAILGLOBAL = 0;

int winJEU1 = 0;
int winJEU2 = 0;
int winJEU3 = 0;
int winGLOBAL = 0;
int looseGLOBAL = 0;

int LED_jeu1_V = 30;
int LED_jeu1_R = 31;
int LED_jeu2_V = 33;
int LED_jeu2_R = 32;
int LED_jeu3_V = 35;
int LED_jeu3_R = 34;

int LED_jglobal1 = 36;
int LED_jglobal2 = 37;
int LED_jglobal3 = 38;
int LED_jglobal4 = 39;

int runcode = 0;

int second=0, minute=45, hour=0; // déclarer des variables de temps
int second1=0, minute1=15, hour1=0; // déclarer des variables de temps
int second2=0, minute2=15, hour2=0; // déclarer des variables de temps
int second3=0, minute3=15, hour3=0; // déclarer des variables de temps
long previousTime = 0;//détient temps précédent en ms
long previousTime1 = 0;//détient temps précédent en ms
long previousTime2 = 0;//détient temps précédent en ms
long previousTime3 = 0;//détient temps précédent en ms
long previousDelay = 0;//détient temps précédent en ms depuis buzzer était actif
long previousDelay1 = 0;//détient temps précédent en ms depuis buzzer était actif
long previousDelay2 = 0;//détient temps précédent en ms depuis buzzer était actif
long previousDelay3 = 0;//détient temps précédent en ms depuis buzzer était actif
long interval = 60000;//60 secondes de retard
long interval1 = 60000;//60 secondes de retard
long interval2 = 60000;//60 secondes de retard
long interval3 = 60000;//60 secondes de retard

int dismentel1 = 0; int fail1 = 0;
int dismentel2 = 0; int fail2 = 0;
int dismentel3 = 0; int fail3 = 0;
int dismentel4 = 0; int fail4 = 0;

char hour_str[4]; // Pour Convertir int en char
char minute_str[4]; // Pour Convertir int en char
char second_str[4]; // Pour Convertir int en char
char timeInt_str[0];  // Pour Convertir int en char

int accessgame = 3; //Activation de led quand les minutes arrivent à 3

unsigned char halfsecond=0;

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

  KP.SetHoldTime(3000);
  KP.SetKeypadVoltage(5.0);
  KP.ShowRange();

   displaya.begin();
   displayb.begin();
   displayc.begin();
   displayd.begin();

   tm1637a.set(4);
   tm1637a.init();
   tm1637a.point(POINT_ON);

   tm1637b.set(4);
   tm1637b.init();
   tm1637b.point(POINT_ON);

   tm1637c.set(4);
   tm1637c.init();
   tm1637c.point(POINT_ON);

   tm1637d.set(4);
   tm1637d.init();
   tm1637d.point(POINT_ON);

   pinMode(checkbranche, INPUT);
   pinMode(checkbrancheb, INPUT);
   pinMode(checkbranchec, INPUT);
   pinMode(checkstart, INPUT);
   pinMode(speakerPin, OUTPUT);

   pinMode(LED_jeu1_V, OUTPUT);
   pinMode(LED_jeu1_R, OUTPUT);
   pinMode(LED_jeu2_V, OUTPUT);
   pinMode(LED_jeu2_R, OUTPUT);
   pinMode(LED_jeu3_V, OUTPUT);
   pinMode(LED_jeu3_R, OUTPUT);

   pinMode(LED_jglobal1, OUTPUT);
   pinMode(LED_jglobal2, OUTPUT);
   pinMode(LED_jglobal3, OUTPUT);
   pinMode(LED_jglobal4, OUTPUT);

   delay(1000);

};

// run loop (forever)
void loop() {

readingstart = digitalRead(checkstart);
reading = digitalRead(checkbranche);
readingb = digitalRead(checkbrancheb);
readingc = digitalRead(checkbranchec);

if (runcode < 1) {
Serial.println("WHAT");

      if (readingstart == HIGH) {

        for (; runOPEN < 1; runOPEN++) {
          uhoh();
         }

    countdown();

Serial.print(halfsecond);
Serial.println(" ");

  if (dismentel1 == 1) {digitalWrite(LED_jglobal1, HIGH);} else {digitalWrite(LED_jglobal1, LOW);}
  if (dismentel2 == 1) {digitalWrite(LED_jglobal2, HIGH);} else {digitalWrite(LED_jglobal2, LOW);}
  if (dismentel3 == 1) {digitalWrite(LED_jglobal3, HIGH);} else {digitalWrite(LED_jglobal3, LOW);}
  if (dismentel4 == 1) {digitalWrite(LED_jglobal4, HIGH);} else {digitalWrite(LED_jglobal4, LOW);}

// GESTION DU JEU 1 //
  if (reading == LOW) {  //REVISION 1 HIGH -> LOW
      countdown1();

      if (second1 > 0 && minute1 >= 0) {
          int8_t timeDisp1[4];
          timeDisp1[0] = minute1 / 10;
          timeDisp1[1] = minute1 % 10;
          timeDisp1[2] = second1 / 10;
          timeDisp1[3] = second1 % 10;
          tm1637b.display(timeDisp1);

      if (minute1 < accessgame) {
        digitalWrite(LED_jeu1_V, LOW);
        digitalWrite(LED_jeu1_R, HIGH);
      } else {
        digitalWrite(LED_jeu1_V, HIGH);
        digitalWrite(LED_jeu1_R, LOW);
      }

          dismentel1 = 0;

      } else {
          displaya.print("FAIL");
            digitalWrite(LED_jeu1_V, HIGH);
            digitalWrite(LED_jeu1_R, LOW);
            for (; runJEU1 < 1; runJEU1++) {
              squeak();
            }
           fail1 = 1;
      }

  } else {
      displaya.print("--5-");
      digitalWrite(LED_jeu1_V, LOW);
      digitalWrite(LED_jeu1_R, HIGH);
      for (; winJEU1 < 1; winJEU1++) {
        wingame();
       }
       dismentel1 = 1;
  }

// GESTION DU JEU 1 //

// GESTION DU JEU 2 //
  if (readingb == HIGH) {
    dismentel2 = 1;
  }

  if ((dismentel1 == 1 or fail1 == 1) && dismentel2 == 0) {
    countdown2();

    if (second2 > 0 && minute2 >= 0) {
      int8_t timeDisp2[4];
      timeDisp2[0] = minute2 / 10;
      timeDisp2[1] = minute2 % 10;
      timeDisp2[2] = second2 / 10;
      timeDisp2[3] = second2 % 10;
      tm1637c.display(timeDisp2);
      if (minute2 < accessgame) {
        digitalWrite(LED_jeu2_V, LOW);
        digitalWrite(LED_jeu2_R, HIGH);
      } else {
        digitalWrite(LED_jeu2_V, HIGH);
        digitalWrite(LED_jeu2_R, LOW);
      }
      dismentel2 = 0;
    } else {
        displayb.print("FAIL");
          digitalWrite(LED_jeu2_V, HIGH);
          digitalWrite(LED_jeu2_R, LOW);
          for (; runJEU2 < 1; runJEU2++) {
            squeak();
          }
         fail2 = 1;
    }

  } else if ((dismentel1 == 1 or fail1 == 1)  && dismentel2 == 1){
      displayb.print("-7--");
      digitalWrite(LED_jeu2_V, LOW);
      digitalWrite(LED_jeu2_R, HIGH);
      for (; winJEU2 < 1; winJEU2++) {
        wingame();
       }
       dismentel2 = 1;
  } else {
    displayb.print("----");
      digitalWrite(LED_jeu2_V, HIGH);
      digitalWrite(LED_jeu2_R, HIGH);
      }

// GESTION DU JEU 2 //

// GESTION DU JEU 3 //

  if (readingc == HIGH) {
    dismentel3 = 1;
  }

  if ((dismentel2 == 1 or fail2 == 1) && dismentel3 == 0) {
    countdown3();

    if (second3 > 0 && minute3 >= 0) {
      int8_t timeDisp3[4];
      timeDisp3[0] = minute3 / 10;
      timeDisp3[1] = minute3 % 10;
      timeDisp3[2] = second3 / 10;
      timeDisp3[3] = second3 % 10;
      tm1637d.display(timeDisp3);
      if (minute3 < accessgame) {
        digitalWrite(LED_jeu3_V, LOW);
        digitalWrite(LED_jeu3_R, HIGH);
      } else {
        digitalWrite(LED_jeu3_V, HIGH);
        digitalWrite(LED_jeu3_R, LOW);
      }
      dismentel3 = 0;
    } else {
        displayc.print("FAIL");
          digitalWrite(LED_jeu3_V, HIGH);
          digitalWrite(LED_jeu3_R, LOW);
          for (; runJEU3 < 1; runJEU3++) {
            squeak();
          }
         fail3 = 1;
    }

  } else if ((dismentel2 == 1 or fail2 == 1)  && dismentel3 == 1){
      displayc.print("---1");
      digitalWrite(LED_jeu3_V, LOW);
      digitalWrite(LED_jeu3_R, HIGH);
      for (; winJEU3 < 1; winJEU3++) {
        wingame();
       }
       dismentel3 = 1;
  } else {
    displayc.print("----");
      digitalWrite(LED_jeu3_V, HIGH);
      digitalWrite(LED_jeu3_R, HIGH);
      }

      } else {

second=0; minute=45; hour=0; // déclarer des variables de temps
second1=0; minute1=15; hour1=0; // déclarer des variables de temps
second2=0; minute2=15; hour2=0; // déclarer des variables de temps
second3=0; minute3=15; hour3=0; // déclarer des variables de temps
previousTime = 0;//détient temps précédent en ms
previousTime1 = 0;//détient temps précédent en ms
previousTime2 = 0;//détient temps précédent en ms
previousTime3 = 0;//détient temps précédent en ms
previousDelay = 0;//détient temps précédent en ms depuis buzzer était actif
previousDelay1 = 0;//détient temps précédent en ms depuis buzzer était actif
previousDelay2 = 0;//détient temps précédent en ms depuis buzzer était actif
previousDelay3 = 0;//détient temps précédent en ms depuis buzzer était actif
interval = 60000;//60 secondes de retard
interval1 = 60000;//60 secondes de retard
interval2 = 60000;//60 secondes de retard
interval3 = 60000;//60 secondes de retard
runOPEN = 0;
dismentel1 = 0; fail1 = 0;
dismentel2 = 0; fail2 = 0;
dismentel3 = 0; fail3 = 0;
dismentel4 = 0; fail4 = 0;
    displaya.print("-   ");
    displayd.print("-   ");

      }

}

// GESTION DU JEU 3 //

// VALIDATION GLOBALE PAR DIGICODE //
  char Key;
  byte KState = KP.Key_State();

  if (KState == PRESSED) {
    if ( Key = KP.Getkey() ) {
      Serial << "Pressed: " << Key << "\n";
      switch (Key) {
        case '*': checkPassword(); break;
        case '#': password.reset(); break;
        default: password.append(Key);
      }
    }
  }
  else if (KState == HELD) {
    Serial << "Key:" << KP.Getkey() << " being held\n";
  }
// VALIDATION GLOBALE PAR DIGICODE //

};

void beep (int speakerPin, float noteFrequency, long noteDuration)
{
  int x;
  // Convert the frequency to microseconds
  float microsecondsPerWave = 1000000/noteFrequency;
  // Calculate how many HIGH/LOW cycles there are per millisecond
  float millisecondsPerCycle = 1000/(microsecondsPerWave * 2);
  // Multiply noteDuration * number or cycles per millisecond
  float loopTime = noteDuration * millisecondsPerCycle;
  // Play the note for the calculated loopTime.
  for (x=0;x<loopTime;x++)
          {
              digitalWrite(speakerPin,HIGH);
              delayMicroseconds(microsecondsPerWave);
              digitalWrite(speakerPin,LOW);
              delayMicroseconds(microsecondsPerWave);
          }
}

void waka() {
  for (int i=1000; i<3000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
  delay(100);
  for (int i=2000; i>1000; i=i*.95) {
    beep(speakerPin,i,10);
  }
    for (int i=1000; i<3000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
  delay(100);
  for (int i=2000; i>1000; i=i*.95) {
    beep(speakerPin,i,10);
  }
    for (int i=1000; i<3000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
  delay(100);
  for (int i=2000; i>1000; i=i*.95) {
    beep(speakerPin,i,10);
  }
    for (int i=1000; i<3000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
  delay(100);

            beep(speakerPin, note_Bb5,300); //B b
          delay(50);
          beep(speakerPin, note_C6,300); //C
          delay(50);
          beep(speakerPin, note_Ab5,300); //A b
          delay(50);
          beep(speakerPin, note_Ab4,300); //A b
          delay(50);
          beep(speakerPin, note_Eb5,500); //E b
          delay(500);
}

void squeak() {
//  for (int i=100; i<5000; i=i*1.45) {
//    beep(speakerPin,i,60);
//  }
//  delay(10);
  for (int i=3500; i>10; i=i/1.15) {
    beep(speakerPin,i,60);
  }
}
void wingame() {
  for (int i=100; i<5000; i=i*1.45) {
    beep(speakerPin,i,60);
  }

}

void uhoh() {
  for (int i=1000; i<2000; i=i*1.10) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i>500; i=i*.90) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i<2000; i=i*1.10) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i>500; i=i*.90) {
    beep(speakerPin,i,10);
  }
  delay(50);
    for (int i=1000; i<2000; i=i*1.10) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i>500; i=i*.90) {
    beep(speakerPin,i,10);
  }
  delay(50);
    for (int i=1000; i<2000; i=i*1.10) {
    beep(speakerPin,i,10);
  }
  delay(50);
  for (int i=1000; i>500; i=i*.90) {
    beep(speakerPin,i,10);
  }
  delay(50);
    for (int i=1000; i<5000; i=i*1.05) {
    beep(speakerPin,i,10);
  }
 delay(300);

  for (int i=1000; i<3000; i=i*1.03) {
    beep(speakerPin,i,10);
  }
  for (int i=3000; i>1000; i=i*.97) {
    beep(speakerPin,i,10);
  }
}

void checkPassword()
{
  if (password.evaluate()) {
    Serial.println("Success");
    runcode = 1;
    displayd.print(" YOU");
    displayd.print(" YOU");
    displaya.print(" ARE");
    displaya.print(" ARE");
    displayb.print(" THE");
    displayb.print(" THE");
    displayc.print("BEST");
    displayc.print("BEST");
    digitalWrite(LED_jglobal4, HIGH);

    for (; winGLOBAL < 1; winGLOBAL++) {
      waka();
     }
    password.reset();
  } else {
    Serial.println("Wrong");
    password.reset();

    for (; looseGLOBAL < 1; looseGLOBAL++) {
    squeak();
    looseGLOBAL = 0;
    }

  }
}
/**********************************************************************
 *                        GLOBAL                                      *
 **********************************************************************/
void countdown(){

 static unsigned long lastTick = 0; // mettre en place une variable locale pour maintenir la dernière fois que nous décrémentés une seconde
  static unsigned long currentMillis = 0;
  // (variables statiques sont initialisées une fois et conservent leurs valeurs entre les appels de fonction)
  // diminuer à une seconde tous 1000 millisecondes
  if (second > 0) {
    if (millis() - lastTick >= 1000) {
      lastTick = millis();
      second--;

      int8_t timeDisp[4];
      timeDisp[0] = minute / 10;
      timeDisp[1] = minute % 10;
      timeDisp[2] = second / 10;
      timeDisp[3] = second % 10;
      tm1637a.display(timeDisp);
      tm1637a.point(POINT_ON);

    }
  } else {
       displayd.print("FAIL");
      for (; runFAILGLOBAL < 1; runFAILGLOBAL++) {
          squeak();
      }
  }
 // décrémenter une minute toutes les 60 secondes
  if (minute > 0) {
    if (second <= 0) {
      minute--;
      second = 60; // remettre les secondes à 60
    }
  }
  // décrémenter une heure tous les 60 minutes
  if (hour > 0) {
    if (minute <= 0) {
      hour--;
      minute = 60; // réinitialiser minutes à 60
    }//closes if
  }//closes if

  //le code ci-dessous bips de la sirène une fois par minute.
  currentMillis = millis();
  if (currentMillis - previousTime > interval)
  {
    previousTime = currentMillis;
    previousDelay = currentMillis;
  }

  if (currentMillis - previousDelay > 100) {//100ms durée de chirp
  }
} //close countdown();

/**********************************************************************
 *                        JEU1                                        *
 **********************************************************************/
void countdown1(){

 static unsigned long lastTick1 = 0; // mettre en place une variable locale pour maintenir la dernière fois que nous décrémentés une seconde
  static unsigned long currentMillis1 = 0;
  // (variables statiques sont initialisées une fois et conservent leurs valeurs entre les appels de fonction)
  // diminuer à une seconde tous 1000 millisecondes
  if (second1 > 0) {
    if (millis() - lastTick1 >= 1000) {
      lastTick1 = millis();
      second1--;

    }
  }
 // décrémenter une minute toutes les 60 secondes
  if (minute1 > 0) {
    if (second1 <= 0) {
      minute1--;
      second1 = 60; // remettre les secondes à 60
    }
  }
  // décrémenter une heure tous les 60 minutes
  if (hour1 > 0) {
    if (minute1 <= 0) {
      hour1--;
      minute1 = 60; // réinitialiser minutes à 60
    }//closes if
  }//closes if

  //le code ci-dessous bips de la sirène une fois par minute.
  currentMillis1 = millis();
  if (currentMillis1 - previousTime1 > interval1)
  {
    previousTime1 = currentMillis1;
    previousDelay1 = currentMillis1;
  }

  if (currentMillis1 - previousDelay1 > 100) {//100ms durée de chirp
  }

} //close countdown1();

/**********************************************************************
 *                        JEU2                                        *
 **********************************************************************/
void countdown2(){

 static unsigned long lastTick2 = 0; // mettre en place une variable locale pour maintenir la dernière fois que nous décrémentés une seconde
  static unsigned long currentMillis2 = 0;
  // (variables statiques sont initialisées une fois et conservent leurs valeurs entre les appels de fonction)
  // diminuer à une seconde tous 1000 millisecondes
  if (second2 > 0) {
    if (millis() - lastTick2 >= 1000) {
      lastTick2 = millis();
      second2--;
    }
  }
 // décrémenter une minute toutes les 60 secondes
  if (minute2 > 0) {
    if (second2 <= 0) {
      minute2--;
      second2 = 60; // remettre les secondes à 60
    }
  }
  // décrémenter une heure tous les 60 minutes
  if (hour2 > 0) {
    if (minute2 <= 0) {
      hour2--;
      minute2 = 60; // réinitialiser minutes à 60
    }//closes if
  }//closes if

  //le code ci-dessous bips de la sirène une fois par minute.
  currentMillis2 = millis();
  if (currentMillis2 - previousTime2 > interval1)
  {
    previousTime2 = currentMillis2;
    previousDelay2 = currentMillis2;
  }

  if (currentMillis2 - previousDelay2 > 100) {//100ms durée de chirp
  }

} //close countdown2();

/**********************************************************************
 *                        JEU3                                        *
 **********************************************************************/
void countdown3(){

 static unsigned long lastTick3 = 0; // mettre en place une variable locale pour maintenir la dernière fois que nous décrémentés une seconde
  static unsigned long currentMillis3 = 0;
  // (variables statiques sont initialisées une fois et conservent leurs valeurs entre les appels de fonction)
  // diminuer à une seconde tous 1000 millisecondes
  if (second3 > 0) {
    if (millis() - lastTick3 >= 1000) {
      lastTick3 = millis();
      second3--;

    }
  }
 // décrémenter une minute toutes les 60 secondes
  if (minute3 > 0) {
    if (second3 <= 0) {
      minute3--;
      second3 = 60; // remettre les secondes à 60
    }
  }
  // décrémenter une heure tous les 60 minutes
  if (hour3 > 0) {
    if (minute3 <= 0) {
      hour3--;
      minute3 = 60; // réinitialiser minutes à 60
    }//closes if
  }//closes if

  //le code ci-dessous bips de la sirène une fois par minute.
  currentMillis3 = millis();
  if (currentMillis3 - previousTime3 > interval1)
  {
    previousTime3 = currentMillis3;
    previousDelay3 = currentMillis3;
  }

  if (currentMillis3 - previousDelay3 > 100) {//100ms durée de chirp
  }
} //close countdown2();

```

# Answer
> 1 votes
That code is a mess. I'm sure you can refactor a lot of it. To get you started here's a C++ class you can use as a countdown timer. I just whipped this up, but it should work. However, it does not handle the case where `millis()` overflows (after about 50 days).

```
class Countdown {
public:
    const uint32_t ms_per_hour = 60l * 60l * 1000l;
    const uint32_t ms_per_minute = 60l * 1000l;
    const uint32_t ms_per_second = 1000l;

    // Constructor
    Countdown(int hours, int minutes, int seconds) {
        duration = hours * ms_per_hour +
                   minutes * ms_per_minute  +
                   seconds * ms_per_second ;
        started = false;
        finished = false;
    }
    // Call this to start the countdown
    void start() {
        started = true;
        finished = false;
        start_time = millis();
    }

    // Stop the timer
    void stop() {
        finished = true;
    }

    // Is timer running?
    bool is_running() {
        return started == true && finished == false;
    }

    // Call this to check if the countdown is finished
    bool times_up() {
        if (finished) return true;
        else if (!started) return false;
        if (elapsed_time() >= duration) {
            finished = true;
            return true;
        }
        return false;
    }

    // Returns a string representation of how much time has passed
    const char * get_elapsed(const char *format="hh:mm:ss") {
        return ms_to_string(format, elapsed_time());
    }
    // Returns a string representation of how much time is left
    const char * get_remaining(const char *format="hh:mm:ss") {
        return ms_to_string(format, duration - elapsed_time());
    }

    // Returns an array of decimal digits for display of time passed
    const char * get_digits_elapsed(const char *format="mmss") {
        return ms_to_digits(format, elapsed_time());
    }
    // Returns an array of decimal digits for display of time remaining
    const char * get_digits_remaining(const char *format="mmss") {
        return ms_to_digits(format, duration - elapsed_time());
    }

protected:
    unsigned long elapsed_time() {
        return millis() - start_time;
    }

    bool started, finished;
    uint32_t duration, start_time;
    char buffer[32];

    char * ms_to_digits(const char *format, uint32_t ms) {
        uint16_t hours = ms / ms_per_hour;
        ms %= ms_per_hour;
        uint16_t minutes = ms / ms_per_minute;
        ms %= ms_per_minute;
        uint16_t seconds= ms / ms_per_second;

        int index = 0;
        for (int i = 0; 0 != format[i]; i++) {
            if ('h' == format[i] || 'm' == format[i] || 's' == format[i]) {
                uint16_t val = 'h' == format[i] ? hours : ('m' == format[i] ? minutes : seconds);
                if (format[i] == format[i+1]) {
                    buffer[index++] = (char)(val / 10);
                    i += 1;
                }
                buffer[index++] = char(val % 10);
            }
        }
        return buffer;
    }

    char * ms_to_string(const char *format, uint32_t ms) {
        uint16_t hours = ms / ms_per_hour;
        ms %= ms_per_hour;
        uint16_t minutes = ms / ms_per_minute;
        ms %= ms_per_minute;
        uint16_t seconds= ms / ms_per_second;

        buffer[0] = 0;
        int index = 0;
        for (int i = 0; 0 != format[i]; i++) {
            if ('h' == format[i] || 'm' == format[i] || 's' == format[i]) {
                uint16_t val = 'h' == format[i] ? hours : ('m' == format[i] ? minutes : seconds);
                if (format[i] == format[i+1]) {
                    index += sprintf(&buffer[index], "%02d", val);
                    i += 1;
                }
                else {
                  index += sprintf(&buffer[index], "%d", val);
                }
            }
            else {
                buffer[index++] = format[i];
            }
        }
        buffer[index] = '\0';
        return buffer;
    }
};

```

To use it, you would create 3 objects:

```
Countdown cd1(0, 45, 0);  // 45 minutes
Countdown cd2(0, 15, 0);  // 15 minutes
Countdown cd3(0, 15, 0);  // 15 minutes

```

Then, start #1 in setup:

```
void setup() {
    cd1.start();
}

```

And in loop:

```
void loop() {
    if (cd3.times_up()) {
       // game over
    }
    else if (cd2.times_up()) {
        // 2nd timer expired, do something
        if (!cd3.is_running()) cd3.start();  // Start #3
        // update display
        tm1637d.display(c3.get_digits_remaining());
    }
    else if (cd1.times_up()) {
        // 1st timer expired, do something
        if (!cd2.is_running()) cd2.start();  // Start #2
        // update display
        tm1637c.display(c2.get_digits_remaining());
    }
    else {
        // update display
        tm1637b.display(c1.get_digits_remaining());
    }
}

```

---
Tags: timers, millis, code-review
---


# Question
Title: compiler says I have to declare my hexidacimal I try to compare
```
#include <IRremote.h>

int RECV_PIN = 11; // IR Receiver - Arduino Pin Number 11
IRrecv irrecv(RECV_PIN);
decode_results results;

int led = 12;

void setup() {
  pinMode(led, OUTPUT);
  digitalWrite(led, LOW);
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}

void loop() {
  if(irrecv.decode(&results)) //this checks to see if a code has been received
{
    if(results.value == FF6897) //if the button press equals the hex value FF6897
    {
        digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
        delay(1000);               // wait for a second
        digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
        delay(1000);               // wait for a second//do something useful here
    }
    irrecv.resume(); //receive the next value
}
  }

```

The issue is in the second if in the void loop the error I get is

> exit status 1 'FF6897' was not declared in this scope

why does he do this? Why doesnt it just accept my IRcode for comparison.

# Answer
> 0 votes
Nothing here that hasn't been covered in comments already but just putting it in the form of an answer to save digging...

How is the compiler supposed to know that a number is hex rather than decimal?

Sure 1234beef is obviously hex but what about 12345678? Is that hex or decimal?

You need some method for the compiler to know.

You also need some way for the compiler to know if something is a number or a variable. Take the code `if (x == deadbeef) {...}` is `deadbeef` a hex number or a variable name?

C uses a very simple convention. If it starts with a number it's a number, if it starts with a letter it's a variable. This is why variable names can contain numbers but can't start with them.

If an integer starts with an 0 e.g. 0123 then it's in octal.
If an integer starts with 0x e.g. 0x123 then it's in hex.
If an integer starts with something other than a 0 e.g. 123 then its in decimal.
e.g.

```
printf("123 = %d\r\n0x123 = %d\r\n0123 = %d\r\n", 123 , 0x123 , 0123);

```

returns

```
123 = 123
0x123 = 291
0123 = 83

```

This convention, especially the 0x prefix for hexadecimal, is very widely used in other programming languages.

# Answer
> -1 votes
By comparing my code to another one, I found out that putting `0x` in front of the hex will fix it, I don't have a clue why this is though.

---
Tags: arduino-uno, ir, remote-control
---


# Question
Title: Diffrence between running once and infinite
```
const int ledPin = 12;

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

void loop(){
    if (Serial.available()) {
        light(Serial.read() – '0');
    }
    delay(500);
}

void light(int n){
    for (int i = 0; i < n; i++) {
        digitalWrite(ledPin, HIGH);
        delay(100);
        digitalWrite(ledPin, LOW);
        delay(100);
    }
}

```

by Oscar Liang

awesome little piece of code which taught me how to setup connection by serial. yet one part I don't understand fully. Why does this line:

> light(Serial.read() – '0');

make the code run once, and this line an infinite times.

> light(Serial.read());

has this something to do with binary? I don't get why subtracting the string 0 would run the code once.

Thanks in Advance!

# Answer
> 3 votes
Serial.read() -'0'

Such code is often used to convert a character to a digit (e.g. int).

Like if the character is '2', than '2' - '0' = ascii 50 - ascii 48 = 2

However, if you use

```
Serial.read()

```

the value will be 50 instead of 2.... maybe looping 50 times (or 48 to 58, for values 0 to 9) will give you the impression it runs infinite?

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


# Question
Title: Using chipKIT WiFi Shield with an Arduino
I'm beginning with Arduino and I have to make two of them communicate via WiFi. I'm going to implement the examples for a WiFi Client and WiFi Server in their tutorials page.

The problem is I only have one Arduino WiFi Shield which is working fine. But I also have a chipKIT WiFi Shield.

My question is: Can I use this other shield to do what I want with one of my Arduinos (I have Uno, Mega and Due) and how? Because I've plugged the shield and I've uploaded the code but it didn't seem to work.

# Answer
> 0 votes
No, you can't. The only libraries available for the chipKIT WiFi Shield are written specifically for the chipKIT boards.

Also, how have you plugged the board into an Arduino? The chipKIT WiFi Shield has Digilent's own header layout with a double row of headers where the Arduino only has a single row. Half the pins won't be plugged into anything.

---
Tags: wifi, shields, chipkit
---


# Question
Title: Output frequency from an SPI DAC (MCP4922) is lower than expected
I'm using a 2-channel, 12-bit DAC (MCP4922, datasheet) with an Arduino Uno, using the library written for it here. With the clock divider set to 2, I should have the SPI clock frequency at 8MHz. If each value sent to the DAC takes about 12 of these clock cycles, that leaves me with about 650kHz as my output frequency (when I'm sending a simple on-off signal like below), but the fastest I see is about 25kHz.

> void loop() { dac.output2(4095, 0); dac.output2(0, 4095); }

Am I misunderstanding how the transfer protocol works? How can I make this faster? I'd like to both understand why this is so slow, and also to get an output frequency of at least 50kHz.

# Answer
Let's do some maths...

* 16MHz master clock / 2 = 8MHz SPI clock
* 2 transactions = 16 bits (not 12!)
* 8,000,000 / 16 = 500,000
* 2 transitions per cycle
* 2 channels
* 2 + 2 = 4
* 500,000 / 4 = 125,000Hz

So in a *perfect* world you could expect 125kHz from the DAC. However the world is *far from* perfect.

Let's look at what it's *actually* doing when you use `output2()`:

```
void DAC_MCP49xx::output2(unsigned short data_A, unsigned short data_B) {
  this->_output(data_A, CHANNEL_A);
  this->_output(data_B, CHANNEL_B);

  // Update the output, if desired.
  // The reason this is only in the dual-output version is simple: it's mostly useless
  // for the single-output version, as it would make more sense to tie the \LDAC pin
  // to ground, or do it manually. However, there should be a single-call method
  // to update *both* channels in sync, which wouldn't be possible with multiple
  // separate DACs (for which there is latch()).
  if (automaticallyLatchDual) {
    this->latch();
  }
}

```

Assuming `automaticallyLatchDual` is false we can pretty much ignore that section. So it's calling `_output()` twice - once for each channel. And what does that do?

```
void DAC_MCP49xx::_output(unsigned short data, Channel chan) {
  // Truncate the unused bits to fit the 8/10/12 bits the DAC accepts
  if (this->bitwidth == 12)
    data &= 0xfff;
  else if (this->bitwidth == 10)
    data &= 0x3ff;
  else if (this->bitwidth == 8)
    data &= 0xff;

  // Drive chip select low
  if (this->port_write)
    PORTB &= 0xfb; // Clear PORTB pin 2 = arduino pin 10
  else
    digitalWrite(ss_pin, LOW);

  // bit 15: 0 for DAC A, 1 for DAC B. (Always 0 for MCP49x1.)
  // bit 14: buffer VREF?
  // bit 13: gain bit; 0 for 1x gain, 1 for 2x (thus we NOT the variable)
  // bit 12: shutdown bit. 1 for active operation
  // bits 11 through 0: data
  uint16_t out = (chan << 15) | (this->bufferVref << 14) | ((!this->gain2x) << 13) | (1 << 12) | (data << (12 - this->bitwidth));

  // Send the command and data bits
  SPI.transfer((out & 0xff00) >> 8);
  SPI.transfer(out & 0xff);

  // Return chip select to high
  if (this->port_write)
    PORTB |= (1 << 2); // set PORTB pin 2 = arduino pin 10
  else
    digitalWrite(ss_pin, HIGH);
}

```

That's quite a lot. All those boolean mathematics operations and decision making slows things down a lot. So does hopping from function to function (yes, the compiler will possibly try and inline some things).

Even the `SPI.transfer()` isn't that efficient with checks and while loops, etc.

To get anywhere near the kind of speed you are looking for you would need to use non-blocking SPI code so you can be transferring a byte out of the SPI port at the same time as getting the next byte ready to send. You don't need to *wait* for the current SPI transfer to finish (as the SPI library does), you just need to be sure that the previous one has finished before you start the next one.
> 2 votes

---
Tags: arduino-uno, spi, digital-analog-conversion
---


# Question
Title: Arduino Upgrading from 1.0.6 to 1.6, code doesn't work anymore
I'm using Arduino UNO, and today I upgraded my IDE from 1.0.6 to 1.6, just to upgrade, nothing special.

I got my libraries again but I got an error with a code that was working OK.

The error was:

```
In file included from C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/Arduino.h:223:0,
                 from C:\Program Files (x86)\Arduino\libraries\ModbusMaster-master\ModbusMaster.h:53,
                 from C:\Program Files (x86)\Arduino\libraries\ModbusMaster-master\ModbusMaster.cpp:32:
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/HardwareSerial.h: In member function 'HardwareSerial& HardwareSerial::operator=(const HardwareSerial&)':
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/HardwareSerial.h:83:7: error: non-static const member 'volatile uint8_t* const HardwareSerial::_ubrrh', can't use default assignment operator
 class HardwareSerial : public Stream
       ^
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/HardwareSerial.h:83:7: error: non-static const member 'volatile uint8_t* const HardwareSerial::_ubrrl', can't use default assignment operator
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/HardwareSerial.h:83:7: error: non-static const member 'volatile uint8_t* const HardwareSerial::_ucsra', can't use default assignment operator
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/HardwareSerial.h:83:7: error: non-static const member 'volatile uint8_t* const HardwareSerial::_ucsrb', can't use default assignment operator
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/HardwareSerial.h:83:7: error: non-static const member 'volatile uint8_t* const HardwareSerial::_ucsrc', can't use default assignment operator
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/HardwareSerial.h:83:7: error: non-static const member 'volatile uint8_t* const HardwareSerial::_udr', can't use default assignment operator
C:\Program Files (x86)\Arduino\libraries\ModbusMaster-master\ModbusMaster.cpp: In member function 'void ModbusMaster::begin(uint16_t)':
C:\Program Files (x86)\Arduino\libraries\ModbusMaster-master\ModbusMaster.cpp:139:16: note: synthesized method 'HardwareSerial& HardwareSerial::operator=(const HardwareSerial&)' first required here
       MBSerial = Serial;
                ^

```

I couldn't find the real error, can someone help me?

# Answer
Judging by the error messages you were using a ModbusMaster library from GitHub such as this one and the HardwareSerial library from the Arduino IDE.

I think the key is in the statement:

> I got my libraries again

I would suggest that you have downloaded a different library to what you originally used. Even if you did get the same repository, these libraries are also constantly changing and your code sometimes has to evolve with the library.

You have several errors (with the SoftwareSerial library): `non-static const member, can't use default assignment operator`. Essentially the program is trying to assign a value to a const or perhaps assigning a constant pointer to non-const data. Find more information on the error here and here. All of these errors stem from line 83 of HardwareSerial.h.

The last line(s) give the clue. You are assigning your instance of your Serial object to you MBSerial object.
> 1 votes

# Answer
You should not have added libraries to the Arduino files in the "C:\Program Files (x86)\Arduino" folder in the first place.
That is only for the Arduino program files and standard libraries that are included with the Arduino IDE.

Could you uninstall the Arduino and serial drivers. Remove also the "C:\Program Files (x86)\Arduino" folder, to be sure that absolutely nothing is left behind, because that will interfere with a new version that will be installed. Remove also the hidden "arduino15" folder(s). Do you know the location of your sketches, it is in the preferences and is often "Documents\Arduino". Go to that folder and go into the "libraries" folder. Remove unused libraries or libraries that have been included in the Arduino files. Do you have Java installed ? Some Java versions are not compatible with the Java files of the Arduino. If you don't need Java, then uninstall it.

Install the newest Arduino 1.8.3 from Arduino.cc Software. Use the Library Manager in the Arduino IDE, and search for modbus. Install the "ModbusMaster by Doc Walker" with the Library Manager. The modbus library that will be installed is this one: Github 4-20mA ModbusMaster.

There has been a few changes, for example with PROGMEM. All PROGMEM data must now be 'const'. You might have to make a few adjustments.
> 0 votes

---
Tags: arduino-ide, compile
---


# Question
Title: Trying to turn off fading RGB LED after 30 secs
I am trying to get something to work so that an RGB LED fades through the color spectrum, and when a button is pressed some music plays. That is not the problem. Assume I am using any loop that functions can be called at any time in. I am trying to make it so that if the button is not pressed for a certain amount of time, say 30 seconds, the light stops fading through the color spectrum and when the button is pressed in this 'sleep mode', first the light starts fading, and then the next press plays the music. I am aware this could be done somehow with millis();, but how would I approach this? I am using an Arduino Uno.

# Answer
> 1 votes
Here is a little snippet of logic that you can implement in your code :

```
if(millis() - getOutOfSleepTime >= 30000) {
    activateSleepMode();
    while(!buttonPress);
    getOutOfSleepMode();
    getOutOfSleepTime = millis();
}

if(buttonPress)
    activateSleepMode();

```

---
Tags: timers, sleep
---


title: Turning on many (30) leds arduino mega

text:
# Question
Title: Turning on many (30) leds arduino mega
I´m new working with Arduino. Right now I have a project thar requires to turn on 30 LEDs at the same time with an Arduino Mega. The problem is that it would exceed the max current that the chip can tolerate.

It is possible to do this by turning on one LED at the time, very fast?

If it is, any clue on the code to achieve that will be apreciated.

Thank you very much

P.S.: I know there are components to expand the quantity of pins that work like that, but the idea is to avoid using one.

# Answer
This page explains that the ATmega2560 could drive up to 800mA: Arduino Playground: Arduino Pin Current Limitations
There are limitations for groups of pins, so you have to be careful.
The 800mA is a lot in my opinion. I wonder how hot the chip will become.

What kind of leds do you use ? Normal 20mA leds ? Or is 10mA leds also possible ? 30\*20mA = 600mA, but 30\*10mA is only 300mA. The 300mA seems a lot safer to me.

With Charlieplexing the leds are not 'on' all the time. However, with the Arduino Mega 2560 you have enough pins, and you could just lower the current through the leds.
Turning them on for a short time (without Charlieplexing) is the same as turning them continuous on with a lower current.

The most common way to drive 30 leds is with a led strip. For example a led strip with neopixels. That led strip has to be powered seperately.

My advice is to lower the current for the leds to 10mA and hope that the ATmega2560 doesn't get too hot.

\[ADDED\] 300mA is still a lot. Start with 5mA per led for a total of 150mA when they all are on at the same time. Many modern and good quality leds are bright at 5mA.
> 1 votes

# Answer
Use external drivers, like a transistor.

If you have to tie them to the avr, use large or larger current limiting resistors. Or to multiplex so only some of them are on at a given time.
> 0 votes

# Answer
Use the MAX7919. It is a driver for multiples leds. It lets you output up to 64 leds at a high enough brightness.

https://playground.arduino.cc/Main/LEDMatrix

Its usually made to drive LED matrices or 7-segments LEDs.
> 0 votes

---
Tags: arduino-mega, led, current
---


# Question
Title: How to interface OV5640 to Arduino Mega using Embedded C?
I am trying to interface a OV5640 camera module to Arduino Mega 2560 in Eclipse IDE using C language . However I am not able to figure out the registers that need to be initialised , for the camera to start capturing pictures .

There are Arduino libraries to deal with setup and image transfer , however I do not wish to use them . I would like to code in C , without using any library . I just need to know which registers need to be accessed and modified to get the camera working .

For reference - I am trying to create a CCTV based system that will record picture based on intruder presence . The entire project is written in C language without any libraries .

Data sheet for OV5640 -https://cdn.sparkfun.com/datasheets/Sensors/LightImaging/OV5640\_datasheet.pdf

Take a look in this link to get an idea about the kind of program it'll be.
How to get 38 Khz clock from Timer 0/2 in Arduino Mega 2560?

# Answer
Arducam gives you all the info you need on the necessary register settings. The register values for each color space and resolution are defined in this header while the initialization sequence, image format selection and image capture process among other stuff, are implemented here and documented if you look closely at the variable names and compiler directives.

**EDIT: More details**

Lines 327 - 372 contain the relevant initialization sequence for this specific camera. For instance, assuming you want JPG images, line 335 marks the start of the needed settings:

```
delay(100);
wrSensorReg16_8(0x3103, 0x11);
wrSensorReg16_8(0x3008, 0x82); delay(100);
wrSensorRegs16_8(OV5640YUV_Sensor_Dvp_Init); delay(500);
wrSensorRegs16_8(OV5640_JPEG_QSXGA);
wrSensorRegs16_8(OV5640_QSXGA2QVGA);
wrSensorReg16_8(0x4407, 0x0C);  # assuming you arent using the Arducam shield or OV5640 5MP Plus

```

What `wrSensorReg16_8` does is pretty obvious: write the 8-bit 2nd argument into the register specified in the 16-bit 1st argument. `wrSensorRegs16_8` merely does the same thing for multiple register-value pairs passed into it. `OV5640YUV_Sensor_Dvp_Init`, `OV5640_JPEG_QSXGA` and `OV5640_QSXGA2QVGA` are all structs defined in the header I mentioned earlier; they contain the rest of the register-value pairs you need to know about. Ultimately, these settings should give you 320x240 JPEG, I think.

You can't use the `start_capture` method since you don't have the ArduCAM FIFO so you'll have to start grabbing frames yourself (and buffering them somewhere very quickly; transmitting the bytes as you read them is out of the question) by paying attention to VSYNC, HREF and PCLK. Look at the timing diagrams in the datasheet. I assume you'll only be taking frames occasionally since a Mega won't do for video. If you're very lucky, you'll get a nice image on your first try but on the whole, be ready to spend serious time studying the datasheet, ArduCAM code and other 0V5640-related code on the web or just go with the OV7670 which has more examples/tutorials.
> 0 votes

---
Tags: arduino-mega, i2c, c, eclipse
---


# Question
Title: Problem with using multi-node nRF24l01+ with Arduinos
I have 3 nodes in my system. One `centralNode` and two sensor nodes (`right` and `left`).
Sensor nodes transmit data to the `centralNode` and receive from it. `centralNode` may transmit to both nodes and receive from them.

I'm using an Arduino nano for central node and Uno and Mega for sensor nodes. I'm using nRF24's base module (with regulators and caps and all) but one node does not have base module (Although I've given it a descent 3.3 V and bypass caps).

**Here is my problem:**
**1-** It seems the centralNode can't detect which nodes data it is receiving. I can **sometimes** get it to work using different delays for sensorNodes but again, on reset it messes up the data. How can I detect which data's reading the centralNode is receiving?

**2-** How can I use radio.available(??) I've put 0, 1 , 2 and pipe addresses in ?? but it does not work (prints garbage data) radio.available's API

Here are the codes: `centralNode:`

```
/*
   Testing multi-node functionality of nRF24l01+
   This is centralNode code

   BOM
   1 Arduino Nano centralNode
   1 Ardiuno Uno rightSensorNode
   1 Arduino Mega leftSensorNode
   3 nRF24l01+
*/

#include <SPI.h>
#include "RF24.h"
#include <printf.h>

#define CEpin 6
#define CSpin 7

RF24 radio(CEpin, CSpin);
byte addresses [][6] = {"1Node", "2Node", "3Node"};

int rightNodeCount = 0;
int leftNodeCount = 0;
void setup() {
  Serial.begin(115200);
  Serial.println(F("This is the central node"));
  printf_begin();
  radio.begin();
  radio.setPALevel(RF24_PA_MAX);

  radio.openWritingPipe(addresses[0]);
  radio.openReadingPipe(1, addresses[1]);
  radio.openReadingPipe(2, addresses[2]);
  radio.startListening();
  radio.printDetails();
}

void loop() {
  if (radio.available()) {
    radio.read(&rightNodeCount, sizeof(rightNodeCount));
    radio.read(&leftNodeCount, sizeof(leftNodeCount));
  }
  //  if (radio.available(1)) {
  //    radio.read(&leftNodeCount, sizeof(leftNodeCount));
  //  }
  Serial.println("centralNode is reporting:");
  Serial.print("centralNode address : ");
  Serial.println((char *)addresses[0]);

  Serial.print("rightNode address : ");
  Serial.println((char *)addresses[1]);
  Serial.print("rightNodeCount = ");
  Serial.println(rightNodeCount);

  Serial.print("leftNode address : ");
  Serial.println((char *)addresses[2]);
  Serial.print("leftNodeCount = ");
  Serial.println(leftNodeCount);

  Serial.println("---END OF REPORT---\n\n\n\n");
  delay(500);
}

```

rightSensorNode:

```
/*
   Testing multi-node functionality of nRF24l01+
   This is rightSensorNode code

   BOM
   1 Arduino Nano centralNode
   1 Ardiuno Uno rightSensorNode
   1 Arduino Mega leftSensorNode
   3 nRF24l01+
*/

#include <SPI.h>
#include "RF24.h"
#include <printf.h>

#define CEpin 7
#define CSpin 8

RF24 radio(CEpin, CSpin);
byte addresses [][6] = {"1Node", "2Node", "3Node"};

int rightNodeCount = 0;
void setup() {
  Serial.begin(115200);
  Serial.println(F("This is the right node"));
  printf_begin();

  radio.begin();
  radio.setPALevel(RF24_PA_MAX);

  radio.openWritingPipe(addresses[1])

  radio.printDetails();

}

void loop() {
  rightNodeCount++;
  Serial.println("Sending data to centralNode");
  Serial.print("rightNode address : ");
  Serial.println((char *)addresses[1]);
  Serial.print("rightNodeCount = ");
  Serial.println(rightNodeCount);
  radio.write(&rightNodeCount, sizeof(rightNodeCount));

  Serial.println("---END OF REPORT---\n\n\n\n");
  delay(1000);
}

```

leftSensorNode:

```
/*
   Testing multi-node functionality of nRF24l01+
   This is leftSensorNode code

   BOM
   1 Arduino Nano centralNode
   1 Ardiuno Uno rightSensorNode
   1 Arduino Mega leftSensorNode
   3 nRF24l01+
*/

#include <SPI.h>
#include "RF24.h"
#include <printf.h>

#define CEpin 7
#define CSpin 8

RF24 radio(CEpin, CSpin);

byte addresses [][6] = {"1Node", "2Node", "3Node"};

int leftNodeCount = 0;
void setup() {
  Serial.begin(115200);
  Serial.println(F("This is the left node"));
  printf_begin();

  radio.begin();
  radio.setPALevel(RF24_PA_MAX);

  radio.openWritingPipe(addresses[2]);

  radio.printDetails();

}

void loop() {
  leftNodeCount++;
  Serial.println("Sending data to centralNode");
  Serial.print("leftNode address : ");
  Serial.println((char *)addresses[2]);
  Serial.print("leftNodeCount = ");
  Serial.println(leftNodeCount);
  radio.write(&leftNodeCount, sizeof(leftNodeCount));

  Serial.println("---END OF REPORT---\n\n\n\n");
  delay(1000);
}

```

# Answer
> 2 votes
Each sensor point should send its address to the central point and this is how the central point knows the source of the message. Then after the central point receives a message, after `if (radio.available())` command receive the data just once (not twice) and then use another if statement to determine which sensor has sent a message (by reading the sent address) and then print.

pseudo code:

```
if (radio.available())
{
    radio.read(&RXbuffer, sizeof(RXbuffer));
    if(RXbuffer.address == sensor1_address)
    {
        print "this is sensor 1"
        print RXbuffer.address;
        print RXbuffer.data;
    }
    else if(RXbuffer.address == sensor2_address)
    {
        print "this is sensor 2"
        print RXbuffer.address;
        print RXbuffer.data;
    }
}

```

In your code (inside `if (radio.available())`) you are trying to receive rightNodeCount and lefteNodeCount eventhough at that time just one of them was received.

**EDIT:**

It seems that RF24 uses dedicated pipes to know the source of the information. The following code should work:

pseudo code:

```
unsigned char pipe_num;

if (radio.available(&pipe_num))
{
    radio.read(&data, sizeof(data));

    if(pipe_num == 1)
    {
        print "this is sensor 1";
        print data;
    }
    else if (pipe_num == 2)
    {
        print "this is sensor 2";
        print data;
    }
}

```

---
Tags: network, nrf24l01+
---


# Question
Title: Unable to flash Arduino when TXD pin of HC-6 Bluetooth module is connected to Arduino RXD pin?
Unable to flash Arduino when TXD pin of HC-6 Bluetooth module is connected to Arduino RXD pin?

I get the following error:

> Flashing with command:C:/Users/home/.arduino-create/arduino/avrdude/6.3.0-arduino9/bin/avrdude.exe -CC:/Users/home/.arduino-create/arduino/avrdude/6.3.0-arduino9/etc/avrdude.conf -q -q -patmega328p -carduino -PCOM4 -b57600 -D -Uflash:w:C:/Users/home/AppData/Local/Temp/arduino-create-agent051272951/sketch\_jun10a.hex:i
>
> avrdude: stk500\_recv(): programmer is not responding
>
> avrdude: stk500\_getsync() attempt 1 of 10: not in sync: resp=0x48

# Answer
> 4 votes
Most\* Arduino devices are flashed through a bootloader which communicates over the serial pins. If you've connected another device to those pins, that communication may fail. You may need to disconnect the device while you flash the Arduino.

(\*: The exceptions are the 32u4-based devices, like the Leonardo and Micro. These communicate directly over USB.)

---
Tags: bluetooth
---


# Question
Title: Unable to load programs onto Arduino Pro Mini Using FTDI?
I'm pretty new to this, so forgive me if I get some things wrong. I am working with a piece of equipment that uses an Arduino Pro Mini. When I first got to it, I realized that some of the code was incorrect and wanted to fix it. Unfortunately, my Pro Mini is soldered into the board with the labels and pins down, so the only accessible pins are the top six, and even those aren't labeled. The reset button is also upside down. I tried using a FT232H FTDI hooked up (using a pinout because of the aforementioned no labels)

D0-\> TX

D1-\> RX

which I was told should work, but when I plug in the micro-usb into the FT232H and try to upload the sketch, it gives me the error

```
avrdude: stk500_getsync(): not in sync: resp=0x00

```

and also blinks green but has a constant red light (from what I can see from looking under the board). Because this Pro Mini controls my equipment, I'm wary of doing anything too intense. Any ideas of how to fix this without breaking my apparatus?

**Update!** I changed the pinning, and the IDE told me that it uploaded, but it still won't run the program! Help!

# Answer
Same problem faced. Try out many times with proper connection but no success. After that, I found one unique and simple solution. I use Arduino Uno instead of FTDI. Follow below step, your problem will definitely solve.

1. First, remove Arduino Uno's IC means ATMEGA 328P-PU.
2. Now, do connection as shown in below figure.

Connections are like:

```
Arduino Uno(Without Chip)     Arduino Mini Pro

          RX                         RX
          TX                         TX
          +5V                        Vcc
          GND                        GND
         RESET                  RST(RESET PIN)

```
3. Now, plug your Arduino Uno to your computer and open your Arduino IDE.
4. Now, an open sketch which one you want to upload. Now, go to `Tools` and select board in which you want to upload code. Below, show in the figure.

5. Now, upload your program. It will definitely work.

I hope it will help you.
> 2 votes

---
Tags: arduino-pro-mini, ftdi
---


# Question
Title: Optimizing ext. SPI ADC for speed and verify the speed
So I have a project where I will be using an Arduino Leonardo and an external ADC (AD7980) to run a 16-bit (18bit) conversion and transmit it to the Arduino and then out on USB as fast as possible.

The AD7980 can run up to 1 MSPS, and I know I cannot reach that with the ATmega32U4 - but I want to know how to optimize my code for running it as fast as possible and how to measure it.

Right now my code is:

```
#include <SPI.h>

int CNV= 11; //Convert on pin 11
int Slaveselect=8;
int adcValue;
byte highByte;
byte lowByte;

void setup() {
  Serial.begin(115200);
  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV2 ); // 8 MHz rate
  SPI.setBitOrder(MSBFIRST);
  pinMode(Slaveselect, OUTPUT);
  pinMode(CNV, OUTPUT);
}

void loop() {
  digitalWrite(Slaveselect,HIGH);
  // SS always high to use 3 Wire mode without busy indicator
  digitalWrite(CNV,LOW);
  digitalWrite(13,LOW);
  digitalWrite(CNV,HIGH);//starts conversion
  digitalWrite(13, HIGH);
  digitalWrite(CNV,LOW); //starts to transmit MSB on data line
  digitalWrite(13,LOW);
  highByte = SPI.transfer(0x00);
  lowByte = SPI.transfer(0x00);
  adcValue = highByte << 8;
  adcValue = adcValue | lowByte;
  Serial.print("analog value =");
  Serial.println(adcValue);
  Serial.print('\n');
}

```

The datasheet for the ADC can be found here: Datasheet

# Answer
1. Don't use `digitalWrite()`.
2. Don't use `delay()`.
3. Don't flood your Serial connection with useless junk ("analog value =")

You may also consider using lower level SPI operations instead of the SPI library, which is completely blocking and slows you down. At least consider the use of `SPI.transfer16(...)` which is more efficient than two `SPI.transfer(...)` calls.
> 1 votes

# Answer
For fast possible speed, use spi transmission buffer and spi interrupt. The concept is that once there is at least free space in the buffer, it interrupts and you load the next byte into the buffer.

That's assuming that dma isn't available.

Short of that, don't use arduino GPIO functions - they are like 100x slower than that's possible. And use a usartt isr to manage transmission.
> 0 votes

---
Tags: spi, adc, atmega32u4, analog-sampling
---


title: No ports available

text:
# Question
Title: No ports available
Heyy everyone!!! I have just started working on arduino uno board and for the first week it was working fine but yesterday when I plugged in the usb cable the port option in IDE turned gray(showing no ports). I tried to update drivers by following commands as given on forum but arduino.inf file was not there under the drivers folder. Also mega 16u2 ic on my board gets hot as soon as I connect it with usb . Tx and Rx LEDs are constantly glowing and 13 pin led glows just for a short time then goes off. It would be of great help if someone can solve my problem:)

# Answer
> Also mega 16u2 ic on my board gets hot as soon as I connect it with usb .

Your board is electrically damaged and must either be replaced or be repaired by someone able to change out one or more failed surface mount components.

The time of those able to do so is commercially priced above the value of this board, so generally it would only be repaired by someone able to do so themselves, where time spent on a hobby project doesn't necessarily have the same economic value as time spent on paying work.
> 3 votes

---
Tags: arduino-uno
---


# Question
Title: Can't open "COM1" on Linux with Trinket Pro
At work, on a Ubuntu 14.04 system, I can access my Trinket Pro without any difficulty whatsoever.

At home, using either Linux Mint or Ubuntu across two laptops, I can not communicate with the device no matter what I try.

I have the correct board selected, the correct processor, and trying to use USBTiny ISP.

Currently, I'm getting:

```
avrdude: ser_open(): can't open device "COM1": No such file or directory
An error occurred while uploading the sketch

```

It's really getting frustrating having to take my devices to work just to upload a sketch, and I've been banging my head for over a week and a half. My UNO R3 boards work without issue on the same laptops.

Here's what `dmesg` says:

```
[  863.471315] usb 1-1.1: Product: USBtiny
[  863.471316] usb 1-1.1: Manufacturer: Adafruit
[  876.438778] usb 1-1.1: USB disconnect, device number 12
[  880.921492] usb 2-1: new low-speed USB device number 5 using xhci_hcd
[  881.092152] usb 2-1: New USB device found, idVendor=1781, idProduct=0c9f
[  881.092157] usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[  881.092161] usb 2-1: Product: USBtiny
[  881.092163] usb 2-1: Manufacturer: Adafruit
[ 1004.305143] usb 2-1: USB disconnect, device number 5
[ 1019.935505] usb 2-1: new low-speed USB device number 6 using xhci_hcd
[ 1020.106524] usb 2-1: New USB device found, idVendor=1781, idProduct=0c9f
[ 1020.106530] usb 2-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[ 1020.106533] usb 2-1: Product: USBtiny
[ 1020.106536] usb 2-1: Manufacturer: Adafruit

```

I am running IDE version 1.8.3, with `sudo`, the exact same way I'm doing at the office.

Can someone please advise on what I'm missing here? Windows is not an option; I haven't used it in many years. I'd just like to figure out what's wrong.

I do have an FTDI connector, but didn't have much luck with it either, and to be honest, don't want to use it as I just want to plug the Trinket in, and upload.

Update: I've tried both USB2 and USB3 ports repeatedly with the same results.

# Answer
> 3 votes
```
[  881.092161] usb 2-1: Product: USBtiny
[  881.092163] usb 2-1: Manufacturer: Adafruit
[ 1004.305143] usb 2-1: USB disconnect, device number 5
[ 1019.935505] usb 2-1: new low-speed USB device number 6 using xhci_hcd
[ 1020.106524] usb 2-1: New USB device found, idVendor=1781, idProduct=0c9f

```

The **USB Tiny ISP** device which this logs shows being connected to your system **is not a USB serial device**. Therefore, it will not have any `/dev/ttyXXX` device associated with it. Instead it should be used with the `-c usbtiny` argument to `avrdude`.

Adafruit documents their products fairly well, and this is no exception. The Linux section of the user guide is at https://learn.adafruit.com/usbtinyisp/avrdude#for-linux

That guide goes on to explain that you will typically need to create a **udev rule** to allow an ordinary user account to access the device. Depending on Linux installation, typical contents might be

```
SUBSYSTEM=="usb", SYSFS{idVendor}=="1781", SYSFS{idProduct}=="0c9f", GROUP="users", MODE="0666"

```

or

```
SUBSYSTEM=="usb", SYSFS{idVendor}=="1781", SYSFS{idProduct}=="0c9f", GROUP="adm", MODE="0666"

```

The above linked guide will more comprehensively explain how all of this works.

Note that the above pertains to the **USB Tiny ISP** *programmer* shown in your dmesg output. According to the Adafruit page on the Trinket Pro, the **Trinket Pro** "bootloader looks just like a USBtinyISP" therefore, you would talk to it in the same way as the USB Tiny ISP that your system reports finding, ie, *without* using a `/dev/ttyXXX` device, but rather by specifying `-c usbtiny` in the avrdude command line, or using an Arduino IDE board configuration which does so.

Your error message suggests that `avrdude` is *not* being run with the correct command line options. You may want to turn on verbose mode to see what is being run - it would especially helpful if you did that on both the working and the non-working Linux systems.

# Answer
> 1 votes
So, in the end, although Chris' answer didn't directly lead me to the solution, by delving through his links, I eventually ended up at a page that suggested using the `Sketch->Upload Using Programmer` feature.

That corrected the issue both as `root` and my normal Linux user account, without any other changes necessary. I find it odd that it isn't required on my work PC, but I digress. It works on both, so I'm pleased.

---
Tags: arduino-ide, uploading, avrdude
---


title: Arduino as a real device to computer

text:
# Question
Title: Arduino as a real device to computer
Suppose we have a computer mouse , now when we connect it to a computer then computer understands it is a mouse which is been connected to it. Same thing happens for keyboard and many other devices. As per my understanding, the mouse has a microcontroller and a TTL serial converter which is programmed a certain way that enable computer's default mouse driver to understand the instructions coming from the connected device.

Let me to talk about one of my projects where I build a device driver for my own device. Like arduino send serial instructions to a port say COM3 and the driver which is a java program reads those instructions and performs accordingly.

As we all know that the arduino library provides support for Mouse and keyboard which works fine. Mouse operations are performed without a custom driver.

Now what I want is when arduino connects to a computer it gets detected as a Joystick or as a pendrive or something like that.

I go through different header files of mouse and keyboard which are present in arduino library but those are very complex and without proper documentation hard to understand.

Can you tell me where I could find study materiel regarding the existing library? Arduino website provides documentations only on different methods not on how it works.

Or if I think of building my own library then how I should start?

One more thing where I can find the information regarding the protocols that a conventional device like mouse, keyboard, pendrive, CD-ROM follows during communication (like the code or the algorithm that is burn into the microcontroller of the device) ?

I know it is a out of the box question but still if you help me, I will be grateful to you.

# Answer
> 2 votes
> As per my understanding, the mouse has a microcontroller and a TTL serial converter which is programmed a certain way that enable computer's default mouse driver to understand the instructions coming from the connected device.

No, the mouse's microcontroller *is* a USB device.

> Like arduino send serial instructions to a port say COM3 and the driver which is a java program reads those instructions and performs accordingly.

No, that is the *application* you are talking about. The driver is what you install in Windows to make COM3 appear (that is, in any version of Windows *before* windows 10. Every other operating system, and Windows 10, has the driver built in already).

> Now what I want is when arduino connects to a computer it gets detected as a Joystick or as a pendrive or something like that.

There is no support for that in the Arduino API.

> I go through different header files of mouse and keyboard which are present in arduino library but those are very complex and without proper documentation hard to understand.

Even with proper documentation and understanding of how USB works it's hard to understand.

> Can you tell me where I could find study materiel regarding the existing library? Arduino website provides documentations only on different methods not on how it works.
>
> Or if I think of building my own library then how I should start?

Don't. Trying to do what you want without an in-depth understanding of how USB works is nigh on impossible. I understand how USB works and struggle with writing USB driver code for microcontrollers.

Instead invest in a device that already does what you want (such as a Teensy 3.x), or move away from Arduino and use a professional environment with professional tools and examples to work with.

> One more thing where I can find the information regarding the protocols that a conventional device like mouse, keyboard, pendrive, CD-ROM follows during communication (like the code or the algorithm that is burn into the microcontroller of the device) ?

From the USB Implementer's Forum Inc.

> Mouse or pendrive have a special type of microcontroller which are capable of direct communication to pc ? if so then is their any programmable microcontroller in market?

Yes, and there are plenty. Any of the Arduino boards based around the ATMega32U4 (such as the Leonardo) are that kind of microcontroller. The "serial" interface chip on the Uno is that kind of microcontroller (it is capable of being reprogrammed so it looks like a completely different device, and if you google around you will find people that have done it).

> What is the difference between actual driver and my java program which reads COM port?

The driver is what *makes* the COM port. Your program is what *uses* the COM port.

```
[USB device]---->[USB)- Driver -(COM3]<-----[Your program]

```

---
Tags: arduino-uno, usb, keyboard, mouse
---


# Question
Title: How do I pull up D1-D6 using 10k ohm resistors?
I'm using push buttons to control CR servos (button1=turn CW; button2=turn CCW). How do I pull up D1-D6 and what does that do exactly? I can't find a tutorial that explains it well enough how to use the resistors.

# Answer
> 2 votes
Typical Atmel AVR inputs can “float” when left open, that is, may drift high or low. The idea of a pullup or pulldown resistor is to give an otherwise-open input a definite value – high if pulled up, low if pulled down.

The values of pullup and pulldown resistor values are a tradeoff: You can use high values to minimize the current that a sensor device must overcome when it switches values, and to minimize power loss in a battery-powered device. Or you can use low values to get faster switching when you release the input.

There are built-in pullup resistors on most AVR inputs. (But A6 and A7 on some models of ATmega328's don't have pullups.) To use a built-in pullup, initialize the input pin with (for example) `pinMode(mypin, INPUT_PULLUP)` instead of `pinMode(mypin, INPUT)`.

To sense the state of a simple normally-open switch, you would connect one side of the switch to an input, and the other side to ground. Initialize the pin to be a pulled-up input: eg, `pinMode(mypin, INPUT_PULLUP)`. Regard the switch as not-pushed when `digitalRead()` shows `HIGH`, and pushed when it shows `LOW`.

If you really want to use external pullup resistors, connect the switch as above – one side to ground, one side to a pin – and connect a resistor between +5 V and the pin. That is, one end of a resistor and one side of a switch will connect to the input pin. In this case, use either `INPUT` or `INPUT_PULLUP` as the `pinMode` setting; it makes no big difference because the internal pullup resistor has a fairly high value, eg 40 KΩ.

---
Tags: arduino-uno, servo, button, resistor, pull-up
---


# Question
Title: Shift Register 74HC595 circuit working weirdly
I built the circuit from the arduino ShiftOut tutorial, but it is not working as expected. I made a simulation model and that one isn't working either.

The code I used is from the tutorial:

```
// SH_CP; 11
const int clockPin = 9;
// DS; 15
const int dataPin = 8;
// ST_CP; 12
const int latchPin = 10;

void setup() {
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(latchPin, OUTPUT);

  Serial.begin(9600);
  Serial.println("reset");
}

void loop() {
  for (int number = 0; number < 256; number++) {
    Serial.println(number);
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, number);
    digitalWrite(latchPin, HIGH);
    delay(500);
  }
}

```

Any idea as to what's wrong?

# Answer
> 1 votes
I presume that you are referring to this tutorial, and this code.

The `clockPin` of Arduino should be connected to pin 11(SH\_CP) of 595, `dataPin` to pin 14(DS), and `latchPin` to pin 12(ST\_CP).

Swap the values of `clockPin` and `latchPin` in your code, and you should be good to go.

```
// SH_CP; 11
const int clockPin = 10;
// DS; 14 (not 15)
const int dataPin = 8;
// ST_CP; 12
const int latchPin = 9;

```

---
Tags: shift-register
---


title: Power supply to L293D motor driver

text:
# Question
Title: Power supply to L293D motor driver
I am new to Arduino. I'm making a line-following bot. I need to power my L293D module. I know that I can supply 9/12V directly with a battery but I am not sure whether I can supply 5V directly from the 5V pin of the Arduino or I have to use something like an IC 7805.

I am confused because I read that the L293D can cause currents up to 600 mA but the max current for an Arduino Uno pin is only 50mA. This question might seem too novice but it would be of great help if someone could explain me about this or the concept in general.

Thanks in advance.

# Answer
> 1 votes
Check the L293x datasheet.

The L293D IC has two power supply pins. Pin 16, VCC1, is to power the IC itself, ei., its internal logic. Pin 8, VCC2, is to power the motors.

The maximum logic current (ICC1 MAX) drawn by the driver IC at pin 16 is 60mA. Thus, provided you do not have other things connected to the Arduino that can take the current draw above the limit, it is safe to connect VCC1 of the driver IC directly to the Arduino's 5V pin.

The maximum current you can draw from the 5V pin is around 400 mA, or 900 mA, when the Arduino is powered by an external power adapter.

The maximum current sourced or sinked by each driver input pin (xA) is 100 μA, and by enable pins (EN), it is 10μA, which is well within the limit of the Arduino digital pins, 40mA (**not** 50 mA!). So you can also safely connect Ax and EN directly to the Arduino.

Coming to the last point, the maximum power current supply by driver outputs (xY) is 600 mA. You cannot source or sink more than 600 mA from the 1Y, 2Y, 3Y and 4Y pins. All of this current will be drawn from pin 8 (VCC2), which is connected to the power supply for the motors, which can be a 9V battery. Note that ICC2 MAX is 1.2 mA. Thus, if the supply voltage of the motors is 5V, you must use another voltage source, like 7805 and not the 5V pin of the Arduino to provide VCC2.

To summarize,

* You can connect pin 16 of L293D to Arduino's 5V pin.
* You can connect pins 1, 2, 7, 9, 10, 15 of L293D to Arduino's digital pins.
* You **cannot** connect pin 8 of L293D to Arduino's 5V pin.

---
Tags: arduino-uno
---


title: Output of Hex of ino

text:
# Question
Title: Output of Hex of ino
I have a hex file of a sketch i.e. `sketchname.ino.hex`. Can I find out anything from that hex file ? Can I see the output or anything ? Can I upload it on arduino ?

# Answer
> 0 votes
> I have a hex file of a sketch i.e. sketchname.ino.hex. Can I find out anything from that hex file ?

That is a binary image of the compiled sketch in a hexadecimal notation. You *could* spend hours disassembling it if you understood the right tools to use.

> Can I see the output or anything ?

You can convert it back to a crude form of assembly language maybe, but that is all. Understanding what that means takes skill and knowledge.

> Can I upload it on arduino ?

Sure. It's a compiled program ready to be uploaded to an Arduino.

```
avrdude -D -patmega328p -PCOM3 -b115200 -C/path/to/avrdude.conf -c arduino -Uflash:w:sketchname.ino.hex:i

```

---
Tags: arduino-ide
---