message:
Help with Stair Lighting using HC-SR04 sensor and WS2812 LED Strip

Excuse my naivete in this as I am very new to Arduino and the programming of. I am trying to put together a project for stair lighting triggered by a ultrasonic sensor at the bottom of the stairs and turned off by an ultrasonic sensor at the top of the stairs and vise versa. I am using an WS2812 LED strip and have the lights travel up the stairs when going up and down when going down. I'm sure this is a project many of you have seen. I have searched the net and youtube and have found many examples of this project, none that I can find using the HC-SR04 sensor. I have managed to cobble together a code which works fine in both direction but it is intermittent in working. I'm sure it is something to do with timings as sometimes it will work fine first time but then others the sensor needs to be blocked for a couple of seconds.
I would also like to add an LDR to the project so it is only active at night. If any of you can point me in the right direction I would be really grateful. I have attached the code so you can see where I am at.
This is just a test code and the final project will have around 200 LEDS.
Thanks

~~~~~~~~

#include <FastLED.h>
#define trigPin_up 2
#define echoPin_up 3
#define trigPin_down 4
#define echoPin_down 5
#define LED_PIN     7
#define NUM_LEDS    13
CRGB leds[NUM_LEDS];

void setup() {

    //Set Serial
  Serial.begin(9600);

  FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);

  pinMode(trigPin_up, OUTPUT);
  pinMode(echoPin_up, INPUT);
  pinMode(trigPin_down, OUTPUT);
  pinMode(echoPin_down, INPUT);

}
 void loop(){
 if (trigPin_up, HIGH && trigPin_down, LOW);
 {
   short duration, distance;
  digitalWrite(trigPin_up, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin_up, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin_up, LOW);
  duration = pulseIn(echoPin_up, HIGH);
  distance = (duration/2) / 29.1;

  if (distance <= 50) {
  leds[0] = CRGB(255, 225, 255);
  FastLED.show();
  delay(100);
  leds[1] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[2] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[3] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[4] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[5] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[6] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[7] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[8] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[9] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[10] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[11] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[12] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[13] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  }

{    short duration, distance;
  digitalWrite(trigPin_down, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin_down, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin_down, LOW);
  duration = pulseIn(echoPin_down, HIGH);
  distance = (duration/2) / 29.1;

  if (distance <= 50) {
  leds[0] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[1] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[2] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[3] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[4] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[5] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[6] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[7] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[8] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[9] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[10] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[11] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[12] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[13] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  }

else
if (trigPin_up, LOW && trigPin_down, HIGH);
  {

     short duration, distance;
  digitalWrite(trigPin_down, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin_down, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin_down, LOW);
  duration = pulseIn(echoPin_down, HIGH);
  distance = (duration/2) / 29.1;

  if (distance <= 50) {
  leds[13] = CRGB(255, 225, 255);
  FastLED.show();
  delay(100);
  leds[12] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[11] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[10] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[9] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[8] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  leds[7] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[6] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[5] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[4] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[3] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[2] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[1] = CRGB(255, 255, 255);
  FastLED.show();
   delay(100);
   leds[0] = CRGB(255, 255, 255);
  FastLED.show();
  delay(100);
  }
{
  short duration, distance;
  digitalWrite(trigPin_up, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin_up, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin_up, LOW);
  duration = pulseIn(echoPin_up, HIGH);
  distance = (duration/2) / 29.1;

    if (distance <= 50) {
  leds[13] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[12] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[11] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[10] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[9] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[8] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  leds[7] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[6] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[5] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[4] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[3] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[2] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[1] = CRGB(0, 0, 0);
  FastLED.show();
   delay(100);
   leds[0] = CRGB(0, 0, 0);
  FastLED.show();
  delay(100);
  }
}

  }
}
 }
 }
~~~~~~~~~

body:
There are a couple things with your code which you might need to look into.
Note: I'm doing this ontop of my head, so please correct me if I say something incorrect. ]

**First**, to check if values are equal, with an if-statement you'd have to use:

<!-- language-all: lang-cpp -->

    //if (trigPin_up, HIGH && trigPin_down, LOW); not like this.
    if (trigPin_up== HIGH && trigPin_down== LOW) {.....} //But like this

Do not use the ';' because that would be then end of the statement.

**Second**, there seems to be a random '{' without any statement beforehand, at line 88.

**Extra tip**
[You can use for loops!][1]
So:

    leds[0] = CRGB(255, 225, 255);
      FastLED.show();
      delay(100);
      ....
      leds[13] = CRGB(255, 255, 255);
      FastLED.show();
      delay(100);
becomes:

    for (int i = 0; i <14; i++){
        leds[i] = CRGB(255, 225, 255);
      FastLED.show();
      delay(100);
      }

As a good exercise, could you try to clean up your code, edit it in the OP, and try if it works then?

  [1]: https://www.arduino.cc/reference/en/language/structure/control-structure/for/


sender: user

sender: assistant

body:
Calvin Bootsman is right with the errors, that he described, but there are more problems in your code.

1. Look at these two lines, that I got from your sketch. I already corrected, what Calvin had to say about the if statement.

        #define trigPin_up 2
        if (trigPin_up == HIGH && trigPin_down == LOW){

    You define `trigPin_up` as the number two. A define is read by the preprocessor. It will replace all occurances of `trigPin_up` with the number 2. `HIGH` and `LOW` are also defines (defined in the Arduino core) with the values 1 and 0. They also get replaced. After that the code goes to the actual compiler. So the compiler sees this if statement:

        if( 2 == 1 && 4 == 0)

    2 isn't equal 1 and 4 isn't equal 0, so the result is always false. That corrupts your complete logic. I'm sure you want to read the state of the pin. `trigPin_up` and siblings are only the pin numbers. For getting the real electrical state of the pin you need to actually read it via `digitalRead()`:

        if(digitalRead(trigPin_up) == HIGH && digitalRead(trigPin_down) == LOW){

    You can simplify this even more, when you know, that zero is treated as `false` and every other value as `true`:

        if(digitalRead(trigPin_up) && !digitalRead(trigPin_down)){

    The `!` before the second `digitalRead()` does a negation, so that the part after the `&&` will become true, if `digitalRead(trigPin_down)` evaluates to false.

2. Now look at these lines:

        #define NUM_LEDS    13
        CRGB leds[NUM_LEDS];
        leds[13] = CRGB(0, 0, 0);

    You create an array named `leds` with `NUM_LEDS` (13) elements. The first index is 0 (as we start to count from zero in most programming languages). But that means, that the last index in the array is 12, not 13. When doing `leds[13]=...` you actually write to a memory address outside of your array. It could be everything, what is saved there. And you overwrite it. This often is a hard to diagnose problem, since it can have very weird consequences. Calvin Bootsman also did this wrong in his answer. For the for loop you only should count to 12, meaning using `i < 13` or `i < NUM_LEDS` in the for loop.

3. Then I guess you don't really understand how the logic of interfacing the HC-SR04 works. The trigger pins, that you define, are outputs. Their state will only change, if you yourself change it via `digitalWrite()`. But that cannot happen, as you enclosed the statements doing it into the if statement. It does not make sense to read these pins either. Instead you should write if statements with the calculated distance. You could go with the following flow in you `loop()` function: Trigger first HC-SR04, read the echo back, trigger second HC-SR04, read the echo back, if statement to compare the calculated distances to a trigger value, in there if statements to decide, which one was triggered, execute the corresponding code in it.

---

Honestly I'm suprised, that your code even compiled. You should look into some basic C/C++ tutorials, so that you get the programming syntax right. Also you should carefully think about the logic of your program. Often it is better to first write down short notes, what the logic of the program should be, without really writing the code. That helps with focussing on the logic instead of the syntax. That can be done afterwards.


message:
I can't receive string that I have sent through nrf correctly

I'm using arduino uno and nrf24l01. to monitor sensor data.
But this is the message that master receives:

> ⸮

this is my slave code.

    void monitoring() {
        delay(10);
        radio.stopListening();
        int soilMoisture = analogRead(A5);
        int light = analogRead(A4);
        float temp = analogRead(A3);
        temp = temp * 0.48828125;
        int ltemp = int(temp);
        String message = String(soilMoisture) + "," + String(light) + "," +    String(ltemp);
        Serial.println(message);
        delay(200);
        radio.write(&message, sizeof(message));
        delay(50);
        radio.startListening();
        delay(10);
    }
and here is my master code.

    while (1) {
        if (radio.available()) {
          char message[32] = "";
          radio.read(&message, sizeof(message));
          delay(500);
          Serial.println(message);
    }

body:
Remove the & in the master code line, change

     radio.read(message, sizeof(message));

to

    radio.read(message, sizeof(message));

`message` is an array, so either you should pass the address of the first character (`&message[0]`), or simply pass `message`.

Another problem is sending a String in the slave code (using type `String `). It's better not to use this type anyway, but you probably have to convert it to a character array of the same type as in the master code.

You can use the function `StringToCharArray` for that, see [StringToCharArray][1].

  [1]: https://www.arduino.cc/en/Reference.StringToCharArray


message:
cant figure out how to fix this compile error

evrything worked for a bit and changed to much to get it working again. dont really understand the error.

[![C:\Users\bavob\AppData\Local\Temp\ccyfrkaL.ltrans0.ltrans.o: In function `loop':

C:\Users\bavob\Documents\Arduino\counte_up/counte_up.ino:96: undefined reference to `num_Write(int)'

collect2.exe: error: ld returned 1 exit status

exit status 1
Fout bij het compileren voor board Arduino/Genuino Uno][1]][1]

  [1]: https://i.stack.imgur.com/M8QsC.png

```int num_array[10][7] = {
  { 1, 1, 1, 1, 1, 0, 1 }, // 0
  { 0, 1, 1, 0, 0, 0, 0 }, // 1
  { 1, 1, 0, 1, 1, 1, 0 }, // 2
  { 1, 1, 1, 1, 0, 1, 0 }, // 3
  { 0, 1, 1, 0, 0, 1, 1 }, // 4
  { 1, 0, 1, 1, 0, 1, 1 }, // 5
  { 1, 0, 1, 1, 1, 1, 1 }, // 6
  { 1, 1, 1, 0, 0, 0, 0 }, // 7
  { 1, 1, 1, 1, 1, 1, 1 }, // 8
  { 1, 1, 1, 0, 0, 1, 1 }  // 9
};

int pin = 2;
int buttonState = 0;
const int button = 12;
int led = 13;
int randVal;
bool pressVal;
void num_Write(int);
void setup() {
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(led, OUTPUT);
  Serial.begin(9600);
  pinMode(button, INPUT);
}

void loop() {
  buttonState = digitalRead(button);
  if (buttonState == LOW) {
    turnOff();
    pressVal = false;
  }
  else
  {
    if (pressVal == false)
    {
      randVal = rand() % 10;
      pressVal = true;
    }
    Serial.println(randVal);
    if (randVal == 0)
    {
      void zero(int number);
      num_Write(0);
    }
    else if (randVal == 1)
    {
      void one(int number);
      num_Write(1);
    }
    else if (randVal == 2)
    {
      void two(int number);
      num_Write(2);
    }
    else if (randVal == 3)
    {
      void three(int number);
      num_Write(3);
    }
    else if (randVal == 4)
    {
      void four(int number);
      num_Write(4);
    }
    else if (randVal == 5)
    {
      void five(int number);
      num_Write(5);
    }
    else if (randVal == 6)
    {
      void six(int number);
      num_Write(6);
    }
    else if (randVal == 7)
    {
      void seven(int number);
      num_Write(7);
    }
    else if (randVal == 8)
    {
      void eight(int number);
      num_Write(8);
    }
    else
    {
      void nine(int number);
      num_Write(9);
    }
  }
}

void zero(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}

void one(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}

void two(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}
void three(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}
void four(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}
void five(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}
void six(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}
void seven(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}
void eight(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}
void nine(int number)
{
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[number][j]);
    pin++;
  }
}
void turnOff()
{

}
```

body:
You call function `num_Write` a lot, you create a forward declaration:

   void num_Write(int);

But you forgot to create the implementation.

If you would have forgot the forward declaration the function would not be known at all (and you would get a compiler error). But with the forward declaration you let the compiler know the signature of `num_write` (so the return value and argument types).

When the linker wants to link all object (.o) files together it cannot find an implementation of the function `num_write` and you get this error. Hence `ld` is the linker.


message:
It gives some glitching on 7 segment display

It gives the right value on the monitor but it doesnt display the value on my display.
```
int pinNumb[7] = {2, 3, 4, 5, 6, 7, 8};
int num_array[11][7] = {
  { 1, 1, 1, 1, 1, 0, 1 }, // 0
  { 0, 1, 1, 0, 0, 0, 0 }, // 1
  { 1, 1, 0, 1, 1, 1, 0 }, // 2
  { 1, 1, 1, 1, 0, 1, 0 }, // 3
  { 0, 1, 1, 0, 0, 1, 1 }, // 4
  { 1, 0, 1, 1, 0, 1, 1 }, // 5
  { 1, 0, 1, 1, 1, 1, 1 }, // 6
  { 1, 1, 1, 0, 0, 0, 0 }, // 7
  { 1, 1, 1, 1, 1, 1, 1 }, // 8
  { 1, 1, 1, 0, 0, 1, 1 }, // 9
  { 0, 0, 0, 0, 0, 0, 0 }  //nothing
};

int pin = 2;
int button = 12;
int buttonVal;
int randVal;
bool pressVal;
void setup() {
  Serial.begin(9600);

  for (int i = 0; i < 7 ; i++)
  {
    pinMode(pinNumb[i], OUTPUT);
  }
  pressVal = false;
  pinMode(button, INPUT);
}

void loop() {
  buttonVal = digitalRead(button);
  if (buttonVal == 0)
  {
    //zero();
    turnOff();
    pressVal = false;
  }
  else
  {
    //zero();
    if (pressVal == false)
    {
      randVal = rand() % 10;
      pressVal = true;
      delay(100);
    }
    Serial.println(randVal);
    if (randVal == 0)
    {
      zero();

    }
    else if (randVal == 1)
    {
      one();

    }
    else if (randVal == 2)
    {
      two();

    }
    else if (randVal == 3)
    {
      three();

    }
    else if (randVal == 4)
    {
      four();

    }
    else if (randVal == 5)
    {
      five();

    }
    else if (randVal == 6)
    {
      six();

    }
    else if (randVal == 7)
    {
      seven();

    }
    else if (randVal == 8)
    {
      eight();

    }
    else
    {
      nine();

    }
  }
}

void zero()
{
  for(int i = 0; i < 7 ; i++)
  {
    digitalWrite(pinNumb[i],LOW);
  }
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[0][j]);
    pin++;
  }
}

void one()
{
  for(int i = 0; i < 7 ; i++)
  {
    digitalWrite(pinNumb[i],LOW);
  }
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[1][j]);
    pin++;
  }
}

void two()
{
  for(int i = 0; i < 7 ; i++)
  {
    digitalWrite(pinNumb[i],LOW);
  }
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[2][j]);
    pin++;
  }
}
void three()
{
  for(int i = 0; i < 7 ; i++)
  {
    digitalWrite(pinNumb[i],LOW);
  }
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[3][j]);
    pin++;
  }
}
void four()
{
  for(int i = 0; i < 7 ; i++)
  {
    digitalWrite(pinNumb[i],LOW);
  }
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[4][j]);
    pin++;
  }
}
void five()
{
  for(int i = 0; i < 7 ; i++)
  {
    digitalWrite(pinNumb[i],LOW);
  }
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[5][j]);
    pin++;
  }
}
void six()
{
  for(int i = 0; i < 7 ; i++)
  {
    digitalWrite(pinNumb[i],LOW);
  }
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[6][j]);
    pin++;
  }
}
void seven()
{
  for(int i = 0; i < 7 ; i++)
  {
    digitalWrite(pinNumb[i],LOW);
  }
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[7][j]);
    pin++;
  }
}
void eight()
{
  for(int i = 0; i < 7 ; i++)
  {
    digitalWrite(pinNumb[i],LOW);
  }
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[8][j]);
    pin++;
  }
}
void nine()
{
  for(int i = 0; i < 7 ; i++)
  {
    digitalWrite(pinNumb[i],LOW);
  }
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin, num_array[9][j]);
    pin++;
  }
}
void turnOff()
{
  for(int i = 0; i < 7 ; i++)
  {
    digitalWrite(pinNumb[i],LOW);
  }

}
````

body:
These can all be byte instead of int to save on memory:

    int pinNumb[7] = {2, 3, 4, 5, 6, 7, 8};
    int num_array[11][7] = {
      { 1, 1, 1, 1, 1, 0, 1 }, // 0
      { 0, 1, 1, 0, 0, 0, 0 }, // 1
      { 1, 1, 0, 1, 1, 1, 0 }, // 2
      { 1, 1, 1, 1, 0, 1, 0 }, // 3
      { 0, 1, 1, 0, 0, 1, 1 }, // 4
      { 1, 0, 1, 1, 0, 1, 1 }, // 5
      { 1, 0, 1, 1, 1, 1, 1 }, // 6
      { 1, 1, 1, 0, 0, 0, 0 }, // 7
      { 1, 1, 1, 1, 1, 1, 1 }, // 8
      { 1, 1, 1, 0, 0, 1, 1 }, // 9
      { 0, 0, 0, 0, 0, 0, 0 }  //nothing
    };

    int pin = 2;
    int button = 12;
    int buttonVal;
    int randVal;

In addition, the array can be reduced to 11 bytes:

    0bFD, // 0
    0bC0, // 1
    0bDE, // 2
    etc.

Then your functions can do direct port manipulation to send bits 0-5 to the Port for D2 to D7, and bit to D8.

As written, these functions probably need some hold time so they don't just flash the LED and disappear:

    void one()
    {
      for(int i = 0; i < 7 ; i++)
      {
        digitalWrite(pinNumb[i],LOW);
      }
      for (int j = 0; j < 7; j++) {
        digitalWrite(pin, num_array[1][j]);
        pin++;
      }
    }


body:
You are continually incrementing the pin variable via pin++, but you are never resetting it to the start (2?) when a new number is to be written.  So it might work the first time but never after that.

Also, you clear the display with digitalWrite(pinNumb[i],LOW);
But you turn segments on with digitalWRite(pin,....); pin++.
Shouldn't you turn the segments on with digitalWrite(pinNumb[i] . . ?


message:
Time counting using millis

I am trying to write a code where photoresistors (a or b) sense blinking of the light, and lights LED (k and d) simultaneosly with that blinking. And I want that when both photoresistors sense dark for more than 3 secs, the LEDs would light up and stay until one of them again gets lighting. But I cannot understand in which part should I put millis time count?
<!-- language-all: lang-cpp -->

    int k = 2;
    int d = 3;
    int fk = A0;
    int fd = A1;
    int a = 0;
    int b = 0;

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

    void loop()
    {
      a = analogRead (fk);
      b = analogRead (fd);
      while (a < 1000 && b < 1000)
      {
        digitalWrite(2, HIGH);
        digitalWrite(3, HIGH);
        a = analogRead (fk);
        b = analogRead (fd);
      }
      if (a > 1000)
        digitalWrite(2, HIGH);
      else
        digitalWrite(2, LOW);
      if (b > 1000)
        digitalWrite(3, HIGH);
      else
        digitalWrite(3, LOW);
    }

body:
Millis gives you a measure of time.  You can store that measure and compare to it later.  I don't know what in your code represents a sense of dark/light in your code (resistors can be used to raise or lower the measured input depending on your circuit) so you will have to work the following in by replacing stuff in <>

    unsigned long lastlight;
    void loop()
    {
        if (<isLitSensorA>) lastlight = millis();
        if (<isLitSensorB>) lastlight = millis();
        if(millis() - lastlight > 3000){ //3 sec since lastlight
            <LightsAlwaysOn>
        }
        else{
            <BlinkWithLights>
        }
    }


body:
This is one of those cases where the solution is simply to implement a
[finite state machine][FSM]. Consider a state machine with these three
states:

* `LIGH`: light has been detected by at least one of the sensors, the
  LEDs follow the light sensors
* `SHORT_DARK`: neither sensor sees light, both LEDs are off
* `LONG_DARK`: it has been at least three seconds since neither sensor
  saw light, both LEDs are on.

The transitions between those states can be depicted by the following
state diagram:

[![state transitions][1]][1]

where “darkness detected” means that no sensor sees light, and “light
detected” means that at least one sensor sees light.

As a general rule, it is a good practice to always draw a state diagram
before you start writing code. Once you are sure your diagram describes
the desired behavior, it is almost trivial to translate it into code.
Here is how I would code it:

```c++
void loop()
{
    bool light_k = analogRead(IN_K) >= 1000;
    bool light_d = analogRead(IN_D) >= 1000;

    static enum { LIGHT, SHORT_DARK, LONG_DARK } state;
    static uint32_t darkness_start;
    switch (state) {
    case LIGHT:
        digitalWrite(OUT_K, light_k ? HIGH : LOW);
        digitalWrite(OUT_D, light_d ? HIGH : LOW);
        if (!light_k && !light_d) {
            darkness_start = millis();
            state = SHORT_DARK;
        }
        break;
    case SHORT_DARK:
        if (light_k || light_d) {
            state = LIGHT;
        } else if (millis() - darkness_start >= 3000) {
            digitalWrite(OUT_K, HIGH);
            digitalWrite(OUT_D, HIGH);
            state = LONG_DARK;
        }
        break;
    case LONG_DARK:
        if (light_k || light_d) {
            state = LIGHT;
        }
        break;
    }
}
```

[FSM]: https://majenko.co.uk/blog/finite-state-machine
[1]: https://i.stack.imgur.com/HMnez.png


body:
Here is a more elegant way to do this. This program doesn't require you to actually count it has been dark, instead it just remembers the time it has last seen the light (how poetic ;). I also added some commentary alongside the code.
```c++
// All the variables
int k = 2;        // LED 1
int d = 3;        // LED 2
int fk = A0;      // photoresistor 1
int fd = A1;      // photoresistor 2
int lastLight = 0;

// Set up the LEDs
void setup() {
  pinMode(k, OUTPUT);
  pinMode(d, OUTPUT);
}

void loop()
{
  // Check the photoresitors
  int a = analogRead (fk);
  int b = analogRead (fd);
  if (a > 1000 || b > 1000)
  {
    // Turn LEDs on if one photoresitor senses light
    digitalWrite(k, HIGH);
    digitalWrite(d, HIGH);
    // Also set the last time it was bright to the current time
    lastLight = millis();
  }
  else if (abs(millis() - lastLight) > 3000)
  {
    // Turn LEDs on if it has been dark for more than 3 seconds (that is 3000 milliseconds)
    digitalWrite(k, HIGH);
    digitalWrite(d, HIGH);
  }
  else
  {
    // Turn LEDs off
    digitalWrite(k, LOW);
    digitalWrite(d, LOW);
  }
}
```


message:
ATmega328P - Problem using timer 2 for tone generation

I'm simply trying to use timer 2 for tone generation and what I get is a very faint and strange tone (almost like its modulated somehow as there is a "pulsing" to it). Here's my simple code:

    #include <Arduino.h>

    #define SPEAKER_PORT PORTC
    #define SPEAKER_BIT 2

    void setup()
    {
      pinMode(A2, OUTPUT);

      TCCR2A = _BV(WGM21);  // CTC mode
      TCCR2B = _BV(CS20);   // clk/1

      OCR2A = 200;  // 8-bit timer, so keep less than 256
      bitSet(TIMSK2, OCIE2A);  // enable OCR2A interrupt
    }

    void loop()
    {
      // NOP
    }

    ISR(TIMER2_COMPA_vect)
    {
      SPEAKER_PORT ^= _BV(SPEAKER_BIT);
    }

Any obvious mistakes? Thanks for your help!

body:
I tried the code on an Uno and as you say, it does sound odd.

By my calculations, the frequency is 40kHz (16MHz/(200 x 2)), which is above the threshold of hearing. The sound we are actually hearing is probably the 3rd or 5th harmonic, at a reduced intensity and perhaps subject to jitter.

I tried changing

`TCCR2B = _BV(CS20);   // clk/1`

to

`TCCR2B = _BV(CS21);   // clk/8`

which should mean that the frequency is now 5kHz (16MHz/8/(200 x 2)).

It sounds cleaner.


body:
Looks like my tone frequency was possibly just too high for the buzzer I was using, causing strange output.

Adjusting the clock divider fixed the issue. That is, I changed the following:

    TCCR2B = _BV(CS20);   // clk/1

to

    TCCR2B = _BV(CS22) | _BV(CS20);  // clk/128

and now I get reasonable-sounding tones.

Note that the clock divider you choose is ultimately driven by what frequency range you want to support, and the bit width of the timer. The formula is something like:

    freq = 16000000 / d / n / 2

where `d` is the clock divider value (like 128), and `n` is the counter value at which to interrupt (what goes in `OCR2A` for instance). `n` must fit into the bit width of the specific timer (on ATmega328P timer 1 is 16-bits wide, and timer 2 is 8-bits wide).

Hope this is helpful for anyone else running into these issues. Thanks so much to [Kartman over at AVRFreaks.net for pointing me in the right direction](https://www.avrfreaks.net/comment/2795731#comment-2795731).


body:
If you drive the speaker pin from an interrupt, you will inevitably have
some jitter, as the interrupt request will sometimes fire while the CPU
is processing another ISR. This can lead to one of the levels being held
for longer than expected, which in turn leads to spurious frequencies in
the output. Note that these are not really _harmonics_ (harmonics always
have frequencies higher than the fundamental), but rather _beating_
between different interrupt sources. That's why you are able to hear
something even though the fundamental is well above the hearing range.

If you want to have a clean PWM signal, you should instead generate it
in hardware. Timer 2 for example can drive pins 11 (OC2A) and 3 (OC2B).
See the bits COM2{A1,A0,B1,B0} in TCCR2A.


message:
Can I use laptop USB port to power Nodemcu if every port used

I wonder if a laptop USB port is enough or I have to use an external power supply if the NodeMCU under heavy load. Here is my list of sensors and port used.

````
3.3V
3.3V
D1 to D7
A0
GND

````

Sensors: Turbidity sensor, Flow sensor, Temperature sensor, 4 led

body: Sensors don't usually require that much current and a usb port should be able to handle 4 leds and the MCU without a problem.  If you are using an Apple laptop it will disable the usb port temporarily if you draw too much current from it.  Some PC laptops probably do the same.


body:
standard current you can draw from a usb port is 500 mili ampere with 5 volt(you may get even more but it is not recommended) . so if you want to calculate

sensors are very low current about 1~2 mA(but you must check out datasheet)

[turbidity][1] for example draws 30 mA

temperature ds1820 is 1 mA

flow is up 2 mA

the LEDs based on resistors series with them you normally up to 3 mA for
each(1k series to 3.3 volt)

if you sum up all of them

30+1+2+4*3=45mA

but you should consider other consumers for example if you need 3.3 V you need a regulator such as ams1117 and it may waste some mili Ampere (not too much) and you certainly have a microprocessor and you should check data sheet but consider 100mA for that in worst case.

to count all of them the answer is YES

  [1]: http://www.farnell.com/datasheets/1770074.pdf


message:
number generator show wrong segments on 7 segment display

I created a program to show a random number on a 7 segment display. It shows a random number in the serial monitor but always shows the same segments 'a c d and g'. anyone know hopw to fix this without changing the base of the coding its for and exercise so i need to have most of the code like I wrote it.

```
int num_array[11][7] = {
  { 1, 1, 1, 1, 1, 0, 1 }, // 0
  { 0, 1, 1, 0, 0, 0, 0 }, // 1
  { 1, 1, 0, 1, 1, 1, 0 }, // 2
  { 1, 1, 1, 1, 0, 1, 0 }, // 3
  { 0, 1, 1, 0, 0, 1, 1 }, // 4
  { 1, 0, 1, 1, 0, 1, 1 }, // 5
  { 1, 0, 1, 1, 1, 1, 1 }, // 6
  { 1, 1, 1, 0, 0, 0, 0 }, // 7
  { 1, 1, 1, 1, 1, 1, 1 }, // 8
  { 1, 1, 1, 0, 0, 1, 1 }, // 9
  { 0, 0, 0, 0, 0, 0, 0 }
};  //OFF

int buttonState = 0;
const int button = 12;
int randVal;
bool pressVal;
void num_Write(int);
void setup() {
  Serial.begin(9600);
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(button, INPUT);
}

void loop() {
  buttonState = digitalRead(button);
  if (buttonState == LOW) {
    turnOff();
    pressVal = false;

  }
  else
  {
    if (pressVal == false)
    {
      int pin = 2;
      for (int i = 0; i < 7 ; i++)
      {
        digitalWrite(pin++, num_array[11][i]);
      }
      randVal = rand() % 10;
      pressVal = true;
    }
    Serial.println(randVal);
    if (randVal == 0)
    {
      void zero();

    }
    else if (randVal == 1)
    {
      void one();

    }
    else if (randVal == 2)
    {
      void two();

    }
    else if (randVal == 3)
    {
      void three();

    }
    else if (randVal == 4)
    {
      void four();

    }
    else if (randVal == 5)
    {
      void five();

    }
    else if (randVal == 6)
    {
      void six();

    }
    else if (randVal == 7)
    {
      void seven();

    }
    else if (randVal == 8)
    {
      void eight();

    }
    else
    {
      void nine();

    }
  }
}

void zero()
{
  int pin = 2;
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin++, num_array[0][j]);

  }
  delay(250);
}

void one()
{
  int pin = 2;
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin++, num_array[1][j]);

  }
  delay(250);
}

void two()
{
  int pin = 2;
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin++, num_array[2][j]);

  }
  delay(250);
}
void three()
{
  int pin = 2;
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin++, num_array[3][j]);
  }
  delay(250);
}
void four()
{
  int pin = 2;
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin++, num_array[4][j]);

  }
  delay(250);
}
void five()
{
  int pin = 2;
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin++, num_array[5][j]);

  }
  delay(250);
}
void six()
{
  int pin = 2;
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin++, num_array[6][j]);

  }
  delay(250);
}
void seven()
{
  int pin = 2;
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin++, num_array[7][j]);

  }
  delay(250);
}
void eight()
{
  int pin = 2;
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin++, num_array[8][j]);

  }
  delay(250);
}
void nine()
{
  int pin = 2;
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin++, num_array[9][j]);

  }
  delay(250);
}
void turnOff()
{
  int pin = 2;
  for (int j = 0; j < 7; j++) {
    digitalWrite(pin++, num_array[10][j]);
  }
  delay(250);
}
```

body:
Note, this is not an answer to your question, but I like to show some programming improvements, making your sketch  much shorter and easier to maintain.

Instead of having all functions `one`, `two`, etcetera, use a parameter to pass the number. So you get this: (I couldn't test it as I don't have an Arduino IDE at hand). Also you can use a `for` loop in the `loop` function to set the output pins.

    int num_array[11][7] = {
      { 1, 1, 1, 1, 1, 0, 1 }, // 0
      { 0, 1, 1, 0, 0, 0, 0 }, // 1
      { 1, 1, 0, 1, 1, 1, 0 }, // 2
      { 1, 1, 1, 1, 0, 1, 0 }, // 3
      { 0, 1, 1, 0, 0, 1, 1 }, // 4
      { 1, 0, 1, 1, 0, 1, 1 }, // 5
      { 1, 0, 1, 1, 1, 1, 1 }, // 6
      { 1, 1, 1, 0, 0, 0, 0 }, // 7
      { 1, 1, 1, 1, 1, 1, 1 }, // 8
      { 1, 1, 1, 0, 0, 1, 1 }, // 9
      { 0, 0, 0, 0, 0, 0, 0 }
    };  //OFF

    int buttonState = 0;
    const int button = 12;
    int randVal;
    bool pressVal;

    void num_Write(int);
    void digit(int value);

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

      for (int pin = 2; pin <= 8; pin++)
      {
        pinMode(pin, OUTPUT);
      }

      pinMode(button, INPUT);
    }

    void loop() {
      buttonState = digitalRead(button);
      if (buttonState == LOW) {
        turnOff();
        pressVal = false;

      }
      else
      {
        if (pressVal == false)
        {
          int pin = 2;
          for (int i = 0; i < 7 ; i++)
          {
            digitalWrite(pin++, num_array[11][i]);
          }
          randVal = rand() % 10;
          pressVal = true;
        }
        Serial.println(randVal);
        if ((randVal >= 0) && (randVal <= 9))
        {
          digit(randVal);
        }
      }
    }

    void digit(int value)
    {
      int pin = 2;
      for (int j = 0; j < 7; j++) {
        digitalWrite(pin++, num_array[value][j]);
      }
      delay(250);
    }

    void turnOff()
    {
      int pin = 2;
      for (int j = 0; j < 7; j++) {
        digitalWrite(pin++, num_array[10][j]);
      }
      delay(250);
    }

You can also remove `turnOff` if you treat it like digit 10 but that is not so clear (or put the implementation of `digit` to another function and call it from `digit` and `turnoff`.

To solve your problem, print the values of each pin to the serial monitor. If they are correct, there is a problem in your circuit. If they are incorrect, there is a problem in your sketch. In the latter case, add more print statements until you found the exact problem.

**Update**

- Fixed void forward declaration to function call (see comment of chrisl)

If the `digit` function is never called, it means:

1. `((randVal >= 0) && (randVal <= 9))` is false, however, that is not possible since it is initialized to 0 and with the rand function it gets always values between 0 to 9.
2. pressVal is always TRUE.

So check the value of pressVal, also add (lots of) `print` statements, especiallya after each `if` and `else` so you know exactly the flow of your sketch. You will see it's very easy to find the error. If you pinpoint the problem to a `digitalRead` that is not the expected value, THAN there is high likely a problem with your circuit (a button that is never going to be LOW or HIGH). In that case, you probably forgot a pullup/pulldown resistor.


message:
Extract binary numbers from infrared sensor that uses I2C bus

I have an infrared sensor(OTI 301) which in order to display the desired temperature I need to apply a formula that depends on 3 binary numbers extracted from the sensor itself. I have tried different approaches but no success yet to extract these binary numbers. Please see link for the data sheet of the sensor where you can see useful information regarding the formula and the binary numbers. https://drive.google.com/file/d/1XMRDCNzY3fn0q6lkGejs5D-pqksfRuZ8/view also here is the code I have tried in the Arduino IDE. Also, attached picture are the needed commands to extract the data from the second data sheet, https://drive.google.com/file/d/1mmdkHkNbwC5VgQxGMrq07XolajNvgBkN/view. [![enter image description here][1]][1]

    #include <Wire.h>
    byte val[2] = {0x20,0x80};
    void setup() {
    Wire.begin(0x20);        // join i2c bus (address optional for master)
    Serial.begin(9600);  // start serial for output
    }

    void loop() {

      //master writter
      Wire.beginTransmission(0x20); // transmit to device
      Wire.write(val,2);
      //Wire.write(x);              // sends one byte
      Wire.endTransmission();    // stop transmitting

      //master reader
      Wire.requestFrom(0x20, 6);    // request 6 bytes from slave device

      while (Wire.available()) { // slave may send less than requested
      Serial.println("H");
      char c = Wire.read(); // receive a byte as character
    }

    delay(500);
    }

  [1]: https://i.stack.imgur.com/q1FqL.png

body:
There are likley two problems:

 - An invalid device address is used. The device address is 0x10 and the Arduino Wire library expects it that way (and not in the shifted version with read/write bit).
 - Your code uses two separate transactions, however the datasheet specifies a single transaction with a repeated START condition for separating the write and read part.

So an improved version looks like so:

    #define DEVICE_ADDRESS 0x10

    void loop() {
        Wire.beginTransmission(DEVICE_ADDRESS);
        Wire.write(0x80);  // readout command
        Wire.endTransmission(false); // stop sending without ending transaction (repeated START)
        Wire.requestFrom(DEVICE_ADDRESS, 6); // request 6 bytes
        uint8_t data[6];
        for (int i = 0; i < 6; i++) {
            data[i] = Wire.read();
        }
    }


message:
How to use ATtiny pins that are usually 'reserved' for chip programming?

How to program an ATtiny45 to use the pins 1, 5, 6, 7 (i.e. PB5, PB0, PB1, PB2) as input or output?

    pinMode(5, OUTPUT);
    pinMode(0, OUTPUT);
    pinMode(1, INPUT);
    pinMode(2, INPUT);
    digitalWrite(5, HIGH);
    ...

These pins are usually used **to program the ATtiny itself**, so how to avoid a conflict?

Of course, I could just avoid these 4 pins, but then as there are also pins for VCC and GND, **there would be only 2 pins left: PB3, PB4!**

Question: how to use the pins as input/output that are usually used for ATtiny programming?

![](https://i.stack.imgur.com/rlxlW.png)

Linked question:

* Should I connect pins 1, 5, 6, 7 of the ATtiny to the programmer

* Or should I connect pins 1, 5, 6, 7, **as well as 8 and 4 (VCC and GND)** of the ATtiny to the programmer?

If the second bullet is correct, when connecting VCC and GND, won't it make the ATtiny run the previously uploaded code?

body:
You can just normally use all pins except for the reset pin (pin 0). When you want to program the Attiny, you just connect the programmer. It will reset the Attiny through the reset pin and put it into ISP programming mode. At that point your code hasn't run.

Note: If you want to program the Attiny while it still sits in its circuit, you have to be careful, that the connected circuit does not disturb the ISP communication. The safest way is to disconnect the Attiny from its circuit and then program it.


body:
The ATTiny chips commonly used in Arduino-like boards, such as the Adafruit Trinket or the Digispark USB will usually have a bootloader which runs before your own code. The bootloader checks for a certain state on the USB port of the board, to see if something is waiting to write a new program to the chip.

The bootloader accepts new code from the host computer, if present, and writes it to a certain location in flash memory. If the bootloader does not find anything connected to the USB connector trying to load a new program, then it (the bootloader) starts executing from flash at the location where your program has been stored.

But, what if you want to write a new bootloader, or not have a bootloader? In that case, you can write new software using the MOSI, MISO, and SCK (clock) pins if the RESET pin is pulled to ground.

See:
http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf#page=151

In order to make use of all 6 non-power pins as I/O for the Trinket or Digispark, a "fuse" is set in the ATTiny chip which disables the RESET pin's normal purpose of holding the chip in reset. This means you cannot pull RESET to ground and load a program the normal way.

If the RESET pin is disabled, and the bootloader is not present, then there is another method for loading software, called "High Voltage Serial Programming". Not to worry, the "high" voltage is is about 12V.

See:
http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf#page=155

You can find schematics, or purchase kits/products that allow you to program an ATTiny chip in HV mode online. Many use the small 12V "A23" or "A27" batteries commonly found in RF remote control transmitters to get the 12V signal to put the chip in high-voltage programming mode.


message:
ADC register always returning high

Regardless of whatever voltage at A0, the software is always returning high (1023)

    volatile unsigned char* ADmux = (unsigned char*) 0x7C;
    volatile unsigned char* ADCSRa = (unsigned char*) 0x7A;
    volatile unsigned char* ADCSRb = (unsigned char*) 0x7B;
    volatile unsigned char* ADCh = (unsigned char*) 0x79;
    volatile unsigned char* ADCl = (unsigned char*) 0x78;
    int Voltage;

    void adc_init()
    {
      *ADmux = 0x00; // setting entire register to 0's notably setting Refs1 and refs0 to 0's meaning reference voltage is AREF
      *ADCSRa = 0b10000111; //Sets most significant bit to 1, which is the ADC enable bit, and the 3 least signifcant bits are the prescalar, which is 128

    }

    unsigned int adc_read( unsigned char adc_channel)
    {
      *ADmux = *ADmux | 0b00000000;// set mux bits to 0 to test A0 regardless of whatever adc_channel is
      *ADCSRa = *ADCSRa | 0b01000000; // set ADSC bit high to start conversion

      while(*ADCSRa & 0b01000000);//wait until ADSC goes low, indicated conversion is complete

      return ADC; //return bits in the adc registers
    }

    void setup() {
       // put your setup code here, to run once:
       Serial.begin(9600);
       adc_init(); // initializes the adc
    }

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

      Voltage = adc_read(0b00000); // calls on adc_read

      Serial.print(Voltage); // prints voltage reading
      Serial.write("\n");

    }

And here is a schematic of the circuit:

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/9CsiQ.png)

<!-- End schematic -->

I have combed over chapter 26 of the atmega2560 document and the descriptions of each register, but I am at a loss. Why is the contents of the adc registers always filled with 1's regardless of the voltage at a0?

body:
First, let me give a couple of suggestions on the programming style.
There is no point in defining your own variables for accessing the
hardware registers: the avr-libc does that for you, you just have to
`#include <avr/io.h>`. Actually, you don't have to \#include anything:
the Arduino IDE automatically \#includes Arduino.h, which in turn
\#includes avr/io.h.

Next, the same avr-libc also defines macros for the bit names, so you
don't have to explicitly write binary numbers in your own code (which is
error-prone). And a couple of utility macros that you can use to make
the code a little bit more readable. For example:

```c++
void adc_init()
{
    ADMUX  = _BV(REFS0);  // ADC reference = AVCC
    ADCSRA = _BV(ADEN)    // enable the ADC
           | _BV(ADPS2)   // set prescaler to 128
           | _BV(ADPS1)   // ditto
           | _BV(ADPS0);  // ditto
}

unsigned int adc_read(unsigned char adc_channel)
{
    ADMUX   = _BV(REFS0) | (adc_channel & 7);  // select channel
    ADCSRA |= _BV(ADSC);  // start conversion

    // Conversion is complete when ADSC goes low.
    loop_until_bit_is_clear(ADCSRA, ADSC);

    return ADC;  // return the adc data register
}
```

Now, let's answer your actual question. When you set both `REFS0` and
`REFS1` to 0, the voltage reference is stated to be “AREF, internal V
REF turned off”. The implication is that you are supposed to bring your
own voltage reference and connect it to the AREF pin. Otherwise AREF is
left as a floating input. This is illustrated in the schematic of the
ADC. Here is the relevant part:

[![AREF input MOSFET][1]][1]

As you see here, `REFS0` is used to connect AREF to one of the other
possible references: either AVCC or the internal bandgap. If `REFS0` is
zero, the transistor depicted above is off, and AREF is left floating.

[1]: https://i.stack.imgur.com/Quxog.png


body:
What are the resistance values for R1 and LDR1? Their ratio will determine the voltage at A0. If the ratio of their resistances is too high (for example, 100:1) then any light measured by LDR1 would only result in a small change in the voltage being measured. If the difference is extreme enough, the voltage could also appear to be constantly low or high. If you have a multimeter available, checking the voltage of that divider circuit could help determine what's going on.

https://learn.sparkfun.com/tutorials/voltage-dividers/all


message:
Publish chipid to mqtt using ESP32-CAM

I have been trying to push the data of temp, humidity, and pressure from a sensor to MQTT using ESP 32Cam, and was able to do using the following code:

    pressure = bme.readPressure();

    //Convert the value to a char array
    char preString[16];
    dtostrf(pressure, 1, 2, preString);
    Serial.print("Pressure: ");
    Serial.println(preString);
    client.publish("esp32/pressure", preString);

When I started off with the following code for getting the mac address:

    chipid=ESP.getEfuseMac();//The chip ID is essentially its MAC address(length: 6 bytes).
    Serial.printf("ESP32 Chip ID = X",(uint16_t)(chipid>>32));//print High 2 bytes
    Serial.printf("X\n",(uint32_t)chipid);//print Low 4bytes.

But when I tried to publish the Chip id, that I was getting on the serial monitor, to the MQTT, an error came up with this:

`call of overloaded 'String(uint64_t)' is ambiguous`

Here's my code that I tried:

    char macValue[16];
    String(ESP.getEfuseMac()).toCharArray(macValue,16);
    client.publish("esp32/ChipID", macValue);

body:
You would be better off formatting it nicely instead of relying on String...

    char macValue[17]; // Don't forget one byte for the terminating NULL...
    uint64_t mac = ESP.getEFuseMac();
    sprintf(macValue, "6x", mac);
    client.publish("esp32/ChipID", macValue);

However, I'm not certain that sprintf can cope with a 64 bit value like that directly. If not, you can split it:

    char macValue[17]; // Don't forget one byte for the terminating NULL...
    uint64_t mac = ESP.getEFuseMac();
    uint32_t hi = mac >> 32;
    uint32_t lo = mac;
    sprintf(macValue, "xx", hi, lo);
    client.publish("esp32/ChipID", macValue);


message:
Switch Case Return , Return not printing

I am trying to get the value of a key pressed and set it to return a value to use in a loop.  In the code below the Print(t) does not show anything

    #include <Keypad.h>

    const byte ROWS = 4; //four rows
    const byte COLS = 4; //four columns
    char hexaKeys[ROWS][COLS] = {
        {'1', '2', '3', 'A'},
        {'4', '5', '6', 'B'},
        {'7', '8', '9', 'C'},
        {'*', '0', '#', 'D'}
    };
    byte rowPins[ROWS] = {9, 8, 7, 6};
    byte colPins[ROWS] = {5, 4, 3, 2};
    Keypad customKeypad = Keypad(makeKeymap(hexaKeys),rowPins,colPins,ROWS,COLS;

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

    void loop()
    {
        int t;
        switch (customKeypad.getKey())
        {
        case 'A':
            t = 8;
            break;
        case '2':
            t = 9;
            break;
        }
        return t;
        Serial.print(t);
    }

body:
You misunderstand the use of return.  The loop function is declared void.  That means it doesn't return anything.  If you simply remove that return statement completely then your code will do what you want.

The return stops the loop.  It throws away the value since the loop is defined as returning void, and code execution never reaches the print statement.  Writing anything in a function after a return statement is useless.


message:
Converting each digit in an integer to its respective ASCII characters

For example what would be the process of converting the integer 1023 into ascii characters of

0x31 (1)
0x30 (0)
0x32 (2)
0x33 (3)

Not looking for any library functions (I know of Serial.print() and what not). I am trying to serially communicate an integer to the serial monitor, and I'd like to know what the process would be for an algorithm to take an integer and make each digit its corresponding ascii character

body:
To convert a whole number to a char array in one go use the itoa function. That sounds like what you actually need.

To convert one digit from decimal to ascii just add '0', the ascii value for a 0. If you just want to try to understand what's going on, it's something like this.

    char result[4] = {0};
    int num = 345;

    int digit = num % 10;  // get the 5 off the end
    result[2] = digit + '0';  // convert to ascii and store
    num /= 10;   // get rid of the 5
    digit = num % 10;   // get the 4 off the end
    result[1] = digit + '0';  // convert to ascii and store
    num /= 10;   // get rid of the 4
    digit = num % 10;   // get the 3 off the end
    result[0] = digit + '0';  // convert to ascii and store

    Serial.print(result);  // prints "345"


message:
How do I download a sketch to an Arduino semi-permanently?

I will be working with Arduino(s), and I would like to find a way to download the sketches to the board semi permanently, in a way that I can remove the USB from the board, apply power, and still have the Arduino execute the code

I am planning to use Mega2960, Uno, and Nano. If there are any differences between the uploading process,
please let me know.

P.S., I am using boards produced by Elegoo, not by Arduino, if that makes a difference.

body:
1. Download the Arduino software (IDE, or Integrated Development Environment).

In our case, we only need to download and run Windows Installer and follow the pop up instructions.  When asked if you want to install the Arduino driver, just press Yes.

2. Connect your Arduino Nano board to your computer.

In this step, Windows should automatically find the proper Arduino driver and install it, and your Nano board should be ready to use.  If not, please refer to the above mentioned instruction for details on installing the drivers.  Some compatible Nano boards such as DCCduino manufactured by a Chinese company use different USB-to-Serial chips so they require to install different drivers, but the installation should be quite straight forward once you have downloaded the proper drivers from internet.

3. Launch the Arduino application.

4. Open the blink example.

Open the LED blink example sketch: File > Examples > 01.Basics > Blink.

For those who are not familiar with Arduino sketch, a sketch is simply a program with various instructions telling Arduino board what to do.

5. Select your board.

You’ll need to select what type of Arduino board you are using.  In our case, simply select Tools > Board > Arduino Nano w/Atmega328.

6. Select your serial port

You also need to select the serial device of the Arduino board: Tools > Serial Port.  Usually the port number will be COM3 or higher (COM1 and COM2 are usually reserved for hardware serial ports). To find out, you can disconnect your Arduino board and re-open the menu; the entry that disappears should be the Arduino board. Reconnect the board and select that serial port.

7. Upload the program to Nano board

Now, simply click the “Upload” button in the environment. Wait a few seconds – you should see the RX and TX leds on the board flashing. If the upload is successful, the message “Done uploading.” will appear in the status bar.

A few seconds after the upload finishes, you should see the pin 13 (L) LED on the board start to blink (in orange). If it does, congratulations! You’ve gotten Arduino up-and-running.

Disconnect from your computer and connect to a power supply to see the blinking light.


message:
Arduino IDE with ATtiny85 error "multiple definition of `__vector_5"

I am having a problem compiling the code for my ATtiny85 circuit.

I am using the timer/counter0 in normal mode so that when it overflows it triggers the TIMER0_OVF_vect ISR. When I have that ISR in my code, it wont compile and gives this error:

    wiring.c.o (symbol from plugin): In function `__vector_5':
    (.text+0x0): multiple definition of `__vector_5'
    sketch\Glove_heater_v1.ino.cpp.o (symbol from plugin):(.text+0x0): first defined here
    collect2.exe: error: ld returned 1 exit status
    exit status 1
    Error compiling for board ATtiny25/45/85.

Maybe I just need to use a different name for the ISR?
---------------------------------------------------------

    My Code:

    //Red LED on PB0
    //Blue LED on PB1
    //Pushbutton PB2
    //Battery voltage divider PB3
    //Mosfet control PB4

    #include <avr/io.h>
    #include <stdint.h>
    #include <avr/interrupt.h>

    volatile uint8_t checkVoltage = 0;

    void setup() {

       DDRB = 0b0010011; //set PB0,PB1,PB4 as output, PB2,PB3 as input
       PORTB = 0b00000011; //set PB0,PB1 HIGH so LEDs are off, other pins LOW

       //Setup TC0 for overflow interrupt trigger
       TCCR0B |= 0b00000101; //clk/1024 prescaler
       TIMSK |= 0b00000010;  //set TOIE0 enable overflow interrupt
       sei();
    }

    void loop() { //do nothing in this test code

    }

    ISR(TIMER0_OVF_vect){ //Timer/counter0 interrupt check voltage
       checkVoltage = 1;
    }

Any ideas are appreciated!

body:
The error message was:

> wiring.c.o [...]: multiple definition of \`\_\_vector\_5'
> Glove\_heater\_v1.ino.cpp.o [...]: first defined here

`__vector_5` is `TIMER0_OVF_vect`. So you have one definition of this
ISR in your sketch, and another one in wiring.c. This wiring.c is part
of the Arduino core. As KIIV puts it in a comment, it uses
`TIMER0_OVF_vect` for timekeeping (`millis()`, `micros()` and
`delay()`).

You have two options for solving this:

* you can use the other timer (Timer 1) in your sketch, and leave Timer
  0 for the Arduino core
* since you are not using the Arduino core anyway, you can get rid of it
  by simply defining `main()` in your sketch instead of `setup()` and
  `loop()`.


message:
millis() function works with inline code and gives output but when creating own library it doesn't works

I am creating library for GPS to use in my project. I am using Adafruit GPS and its library to create my own library in which I am using `millis()` function to display the GPS Location after 1 minute (60s). So when I created my inline code the function works very well and also displays location after 60s. But I created `header` and `cpp` file for my own library, in which it doesn't gives any error but the results(location) is not displayed. Doesn't shows any output. So I printed the time which is 0 (attached the output screenshot)[![enter image description here][1]][1]

My code updates the GPS every 30s and prints the location every 1 minute.It also checks the if old location is equal to new location in every 1minute.

I think there is problem with my libaray or with the millis() function. I am new to Arduino programming , please help me with this.

My inline code is:

    #include <Adafruit_GPS.h>
    #include <SoftwareSerial.h>

    SoftwareSerial mySerial(11, 10);
    Adafruit_GPS GPS(&mySerial);

    #define GPSECHO  true
    uint32_t timer = millis();
    float old_lat,old_lon,new_lat,new_lon;

    void setup()
    {

      Serial.begin(9600);
      delay(1000);
      Serial.println("Adafruit GPS library basic test!");
      GPS.begin(9600);
      GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
      GPS.sendCommand("$PMTK220,30000*1F");
      mySerial.println(PMTK_Q_RELEASE);
    }

    void loop()                     // run over and over again
    {
      char c = GPS.read();
      if (GPS.newNMEAreceived()) {
        //Serial.println(GPS.lastNMEA());   // this also sets the newNMEAreceived() flag to false
        if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
          return;  // we can fail to parse a sentence in which case we should just wait for another
      }

    if (GPS.fix) {

          old_lat = GPS.latitudeDegrees;
          old_lon = GPS.longitudeDegrees;
          if (timer > millis())  timer = millis();
          if (millis() - timer > 60000) {
            timer = millis();
              Serial.println("Location 1 minute:");
              displaytime();
              new_lat = GPS.latitudeDegrees;
              new_lon = GPS.longitudeDegrees;

              if (new_lat == old_lat){
                new_lat = old_lat;
              }
              else{
                new_lat = GPS.latitudeDegrees;
              }
              Serial.print("Final Latitude: ");
              Serial.println(new_lat,6);

              if (new_lon == old_lon){
                new_lon = old_lon;
              }
              else{
                new_lon = GPS.longitudeDegrees;
              }
              Serial.print("Final Longitude: ");
              Serial.println(new_lon,6);

    }
    }
    }

    void displaytime(){
        Serial.print("\nTime: ");
        if (GPS.hour < 10) { Serial.print('0'); }
        Serial.print(GPS.hour, DEC); Serial.print(':');
        if (GPS.minute < 10) { Serial.print('0'); }
        Serial.print(GPS.minute, DEC); Serial.print(':');
        if (GPS.seconds < 10) { Serial.print('0'); }
        Serial.print(GPS.seconds, DEC); Serial.print('.');
        if (GPS.milliseconds < 10) {
          Serial.print("00");
        } else if (GPS.milliseconds > 9 && GPS.milliseconds < 100) {
          Serial.print("0");
        }
        Serial.println(GPS.milliseconds);
    }

My header file is :

    /*
     * GPS.h - library used to show Latitude and Longitude
     */

     #ifndef GPS_Loc_h
     #define GPS_Loc_h

     #include "Arduino.h"

    class SoftwareSerial;
    class Adafruit_GPS;

     class GPS_Loc
     {
      public:
        GPS_Loc();
        void displaytime();
        void displayloc();
        uint32_t timer;
        float old_lat,old_lon,new_lat,new_lon;
     };

     #endif

My cpp file is:

    /*
     * GPS_Loc.cpp - library used to show Latitude and Longitude
     */

     #include "Arduino.h"
     #include "GPS_Loc.h"

     #include "Adafruit_GPS.h"
     #include "SoftwareSerial.h"

     #define GPSECHO  true

    SoftwareSerial mySerial(11,10);
    Adafruit_GPS GPS(&mySerial);

    GPS_Loc::GPS_Loc()
    {
      timer = millis();
      old_lat = old_lat;
      old_lon = old_lon;
      new_lat = new_lat;
      new_lon = new_lon;
    }

    void GPS_Loc::displayloc(){
      //Serial.println("Adafruit GPS library basic test!");
      GPS.begin(9600);
      GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
      GPS.sendCommand("$PMTK220,30000*1F");
      mySerial.println(PMTK_Q_RELEASE);
      char c = GPS.read();
      if (GPS.newNMEAreceived()) {
        //Serial.println(GPS.lastNMEA());   // this also sets the newNMEAreceived() flag to false
        if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
          return;  // we can fail to parse a sentence in which case we should just wait for another
       }

    if (GPS.fix) {

          old_lat = GPS.latitudeDegrees;
          old_lon = GPS.longitudeDegrees;
          if (timer > millis())  timer = millis();
          if (millis() - timer > 60000) {
            timer = millis();
              Serial.println("Location 1 minute:");
              displaytime();
              new_lat = GPS.latitudeDegrees;
              new_lon = GPS.longitudeDegrees;

              if (new_lat == old_lat){
                new_lat = old_lat;
              }
              else{
                new_lat = GPS.latitudeDegrees;
              }
       Serial.print("Location lat: ");
              Serial.println(new_lat,6);

              if (new_lon == old_lon){
                new_lon = old_lon;
              }
              else{
                new_lon = GPS.longitudeDegrees;
              }

              Serial.print("Location long: ");
              Serial.println(new_lon,6);

    }
    }
    }

    void GPS_Loc::displaytime(){
        Serial.print("\nTime: ");
        if (GPS.hour < 10) { Serial.print('0'); }
        Serial.print(GPS.hour, DEC); Serial.print(':');
        if (GPS.minute < 10) { Serial.print('0'); }
        Serial.print(GPS.minute, DEC); Serial.print(':');
        if (GPS.seconds < 10) { Serial.print('0'); }
        Serial.print(GPS.seconds, DEC); Serial.print('.');
        if (GPS.milliseconds < 10) {
          Serial.print("00");
        } else if (GPS.milliseconds > 9 && GPS.milliseconds < 100) {
          Serial.print("0");
        }
        Serial.println(GPS.milliseconds);
    }

My demo code using my own library is:

    #include <GPS_Loc.h>

    GPS_Loc bgps;

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

    }

    void loop() {
      // put your main code here, to run repeatedly:
      bgps.displaytime();
      bgps.displayloc();
    }

Output of inline code[![enter image description here][2]][2]

  [1]: https://i.stack.imgur.com/ykGiV.png
  [2]: https://i.stack.imgur.com/F49ov.png

body:
I think Gerben is on to something.  If you re-initialize the gps at every loop and then never give it time to acquire the gps signal then your if (GPS.fix) condition is never true and you never print out any other data.  All your timing code is inside the GPS.fix condition which doesn't happen until you have a fix.
Try putting the init code inside your contructor for your class. Somethink like :
```
GPS_Loc::GPS_Loc()
{
  timer = millis();
  old_lat = old_lat;
  old_lon = old_lon;
  new_lat = new_lat;
  new_lon = new_lon;

  //Serial.println("Adafruit GPS library basic test!");
  GPS.begin(9600);
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  GPS.sendCommand("$PMTK220,30000*1F");
  mySerial.println(PMTK_Q_RELEASE);
}

void GPS_Loc::displayloc(){
  delay(100); // short delay to stop a no-fix runaway
  char c = GPS.read();
  if (GPS.newNMEAreceived()) {
    //Serial.println(GPS.lastNMEA());   // this also sets the newNMEAreceived() flag to false
    if (!GPS.parse(GPS.lastNMEA()))   // this also sets the newNMEAreceived() flag to false
      return;  // we can fail to parse a sentence in which case we should just wait for another
    }

if (GPS.fix) {
````
It might also be useful to put a small delay somewhere in the code so that it won't loop like crazy before getting a fix.


message:
How to set current position for the DC motor to zero + store current positions in an array and run it?

I would like to know how to set the current position for the DC motors to zero and store the current position in an array. after that I would like it to loop in the array to run all steps that was stored in the array?

Am using Genuino UNO board, I have 4 DC motors and each 2 wheels are connected to an H-bridge.

I have an application that have a "save" button and a "Run" button.
For the save button, I would like it to set the current position for each wheel to zero first then store the positions of each wheel in an array.
For the run button, I would like it to loop in the array that was made by the save button and show the output on each wheels.

basically what am trying to achieve is to make the robotic car that can move any direction I tell it to move in the same time  I can control the wheel speed.
all that move are being sent via Bluetooth as numbers.

I hope it's clear now

here is my code

    #include <SoftwareSerial.h>

    SoftwareSerial Bluetooth(0, 1); // Arduino(RX, TX) - HC-05 Bluetooth (TX, RX)

    // Define the motors and the pins
    // Motor A1

    int enA1 = 2;
    int in11 = 3;
    int in21 = 4;

    // Motor B1

    int enB1 = 5;
    int in31 = 6;
    int in41 = 7;

    //other H-bridge

    // Motor A2

    int enA2 = 8;
    int in12 = 9;
    int in22 = 10;

    // Motor B2

    int enB2 = 11;
    int in32 = 12;
    int in42 = 13;

    int wheelSpeed = 125;
    int dataIn, m;
    //lbw left back wheel / lfw left fron wheel / rbw right back wheel / rfw right front wheel
    int lbw[50], lfw[50], rbw[50], rfw[50]; // for storing positions/steps
    int index = 0;

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

      Bluetooth.begin(9600); // Default baud rate of the Bluetooth module
      Bluetooth.setTimeout(1);
      Serial.print("connected");
      Serial.print("-------------------");
      delay(20);

      pinMode(enA1, OUTPUT);
      pinMode(enB1, OUTPUT);
      pinMode(in11, OUTPUT);
      pinMode(in21, OUTPUT);
      pinMode(in31, OUTPUT);
      pinMode(in41, OUTPUT);
      pinMode(enA2, OUTPUT);
      pinMode(enB2, OUTPUT);
      pinMode(in12, OUTPUT);
      pinMode(in22, OUTPUT);
      pinMode(in32, OUTPUT);
      pinMode(in42, OUTPUT);
    }

    void loop() {
      // Check for incoming data

     if (Bluetooth.available() > 0) {
        dataIn = Bluetooth.read();  // Read the data

        if (dataIn == 0) {
          m = 0;
        }
        if (dataIn == 1) {
          m = 1;
        }
        if (dataIn == 2) {
          m = 2;
        }
        if (dataIn == 3) {
          m = 3;
        }
        if (dataIn == 4) {
          m = 4;
        }
        if (dataIn == 5) {
          m = 5;
        }
        if (dataIn == 6) {
          m = 6;
        }
        if (dataIn == 7) {
          m = 7;
        }
        if (dataIn == 8) {
          m = 8;

        }
        if (dataIn == 9) {
          m = 9;
        }
        if (dataIn == 10) {
          m = 10;
        }
        if (dataIn == 11) {
          m = 11;
        }

        if (dataIn == 12) {
          m = 12;
        }
        if (dataIn == 14) {
          m = 14;
        }
        // Set speed
        if (dataIn >= 16) {
          wheelSpeed = dataIn * 10;
          Serial.println(wheelSpeed);
        }
      }
      if (m == 4) {
        moveSidewaysLeft();
      }
      if (m == 5) {
        moveSidewaysRight();
      }
      if (m == 2) {
        moveForward();
      }
      if (m == 7) {
        moveBackward();
      }
      if (m == 3) {
        moveRightForward();
      }
      if (m == 1) {
        moveLeftForward();
      }
      if (m == 8) {
        moveRightBackward();
      }
      if (m == 6) {
        moveLeftBackward();
      }
      if (m == 9) {
        rotateLeft();
      }
      if (m == 10) {
        rotateRight();
      }

      if (m == 0) {
        stopMoving();
      }
      //Serial.println(dataIn);
      // If button "SAVE" is pressed
      if (m == 12) {
        if (index == 0) {
            digitalWrite(in11, LOW);
            digitalWrite(in21, LOW);
            digitalWrite(in31, LOW);
            digitalWrite(in41, LOW);
            digitalWrite(in12, LOW);
            digitalWrite(in22, LOW);
            digitalWrite(in32, LOW);
            digitalWrite(in42, LOW);

        }

        // save position into the array
      }
      //if (m == 14) {
       // runSteps();
        //if (dataIn != 14) {
          //stopMoving();
          // Clear the array data to 0
       // }
      //}

    }

    //method to read the array from what was saved by the save button and run it step by step
    //void runSteps() {}

    void moveForward() {
            digitalWrite(in11, HIGH);
            digitalWrite(in21, LOW);
            digitalWrite(in31, HIGH);
            digitalWrite(in41, LOW);
            digitalWrite(in12, HIGH);
            digitalWrite(in22, LOW);
            digitalWrite(in32, HIGH);
            digitalWrite(in42, LOW);
            Serial.println("Motor: move Forward");
    }

    void moveBackward() {
            digitalWrite(in11, LOW);
            digitalWrite(in21, HIGH);
            digitalWrite(in31, LOW);
            digitalWrite(in41, HIGH);
            digitalWrite(in12, LOW);
            digitalWrite(in22, HIGH);
            digitalWrite(in32, LOW);
            digitalWrite(in42, HIGH);
            Serial.println("Motor: move Backward");
    }

    void moveSidewaysLeft() {
            digitalWrite(in11, HIGH);
            digitalWrite(in21, LOW);
            digitalWrite(in31, LOW);
            digitalWrite(in41, HIGH);
            digitalWrite(in12, LOW);
            digitalWrite(in22, HIGH);
            digitalWrite(in32, HIGH);
            digitalWrite(in42, LOW);
            Serial.println("Motor: move Sideways Left");
    }
    void moveSidewaysRight() {
            digitalWrite(in11, LOW);
            digitalWrite(in21, HIGH);
            digitalWrite(in31, HIGH);
            digitalWrite(in41, LOW);
            digitalWrite(in12, HIGH);
            digitalWrite(in22, LOW);
            digitalWrite(in32, LOW);
            digitalWrite(in42, HIGH);
            Serial.println("Motor: move Sideways right");
    }

    void moveRightForward() {
            digitalWrite(in11, LOW);
            digitalWrite(in21, LOW);
            digitalWrite(in31, HIGH);
            digitalWrite(in41, LOW);
            digitalWrite(in12, HIGH);
            digitalWrite(in22, LOW);
            digitalWrite(in32, LOW);
            digitalWrite(in42, LOW);
            Serial.println("Motor: move Right Forward");
    }

    void moveLeftBackward() {
            digitalWrite(in11, LOW);
            digitalWrite(in21, LOW);
            digitalWrite(in31, LOW);
            digitalWrite(in41, HIGH);
            digitalWrite(in12, LOW);
            digitalWrite(in22, HIGH);
            digitalWrite(in32, LOW);
            digitalWrite(in42, LOW);
            Serial.println("Motor: move left Back ward");
    }

    void moveLeftForward() {
            digitalWrite(in11, LOW);
            digitalWrite(in21, LOW);
            digitalWrite(in31, LOW);
            digitalWrite(in41, HIGH);
            digitalWrite(in12, LOW);
            digitalWrite(in22, HIGH);
            digitalWrite(in32, LOW);
            digitalWrite(in42, LOW);
            Serial.println("Motor: move Left Forward");
    }

    void moveRightBackward() {
            digitalWrite(in11, LOW);
            digitalWrite(in21, HIGH);
            digitalWrite(in31, LOW);
            digitalWrite(in41, LOW);
            digitalWrite(in12, LOW);
            digitalWrite(in22, LOW);
            digitalWrite(in32, LOW);
            digitalWrite(in42, HIGH);
            Serial.println("Motor: move Right Backward");
    }

    void rotateLeft() {
            digitalWrite(in11, HIGH);
            digitalWrite(in21, LOW);
            digitalWrite(in31, LOW);
            digitalWrite(in41, HIGH);
            digitalWrite(in12, HIGH);
            digitalWrite(in22, LOW);
            digitalWrite(in32, LOW);
            digitalWrite(in42, HIGH);
            Serial.println("Motor: rotate Left");
      }

    void rotateRight() {
            digitalWrite(in11, LOW);
            digitalWrite(in21, HIGH);
            digitalWrite(in31, HIGH);
            digitalWrite(in41, LOW);
            digitalWrite(in12, LOW);
            digitalWrite(in22, HIGH);
            digitalWrite(in32, HIGH);
            digitalWrite(in42, LOW);
            Serial.println("Motor: rotate Right");
      }

    void stopMoving() {
            digitalWrite(in11, LOW);
            digitalWrite(in21, LOW);
            digitalWrite(in31, LOW);
            digitalWrite(in41, LOW);
            digitalWrite(in12, LOW);
            digitalWrite(in22, LOW);
            digitalWrite(in32, LOW);
            digitalWrite(in42, LOW);
            Serial.println("Motor: off");
      }

body:
As I understood it from your comments, your aim is not really to store the actual positions of the wheels or your robot, but to save and repeat the actions, that the robot did. (Meaning you don't have a "position" here, but only a measurement of wheel speed)

If that is true, then you can save this in a 2-dimensional array with the element form `{speed_wheel_1, speed_wheel2, duration}`. So each action is defined by the speeds of both wheels and the duration of the action, for example:

    Driving forward at full speed for 3s, turn on the spot to the left with half speed for 1.5s, drive a curve with motor left full speed and motor right half speed for 5s

This would translate to the following elements:

    {100, 100, 3000}
    {-50, 50, 1500}
    {100, 50, 5000}

The speeds have to be read in percent here and the durations in milliseconds.

----

Obviously you are controlling the robot over serial. I don't completely understand your code (also as you didn't show us the full code), so I will give some hints, how you can go on from here:

You are obtaining the speeds from serial into the variable `wheelSpeed`. We cannot see, how you are using this variable later, but you can use it in some way to set the speed fields of a new array element.

Then you need the duration. The Arduino framework has a function for that: `millis()`. It will return the number of milliseconds since the startup, much like a clock. When an action starts (when the corresponding serial command is received), you have to set a timestamp:

    unsigned long timestamp;
    ...
    timestamp = millis();

When the action ends (either because it actually only had a limited duration, or because another command is received), you calculate the difference between the current millis value and the timestamp. This is the duration.

So the corresponding code parts will look like this:

    unsigned long timestamp = 0; // Define timestamp at global scope
    unsigned int current_element = 0; // A variable to keep track of the current array element
    int actions[10][3]; // Array to hold up to 10 actions

    void start_action(byte speed_left, byte speed_right){
        actions[current_element][0] = speed_left;
        actions[current_element][1] = speed_right;
        timestamp = millis();
        // Start the action with the provided speeds here
    }

    void end_action(unsigned int element_index){
        actions[current_element][2] = millis() - timestamp;
        current_element++;
        if(current_element >= 10){
            // Do something to prevent more actions. Maybe just disable recording.
    }

For repeating the actions, you just have to cycle over the array and set the corresponding speeds for the corresponding time.

If you want to go fancy, you can ditch the 2-dimensional array and instead define a struct for an action:

    struct Action{
        int speed_left;
        int speed_right;
        unsigned long duration;
    };

Then you can create a simple array of the `Action` objects and reference the fields by name:

    Action actions[10];
    ...
    actions[1].duration = millis() - timestamp;


message:
Protect the Arduino make with Unique Id

I’d like to protect my arduino make with a unique serial number for every device I make.
What are the proper ways to do it? Probably there are kind of best practices…
Keep it in EEPROM is obviously a bad idea.

I believe that there is some chip that can be added to the circuitry.

The general idea is the following.
Circuitry has a hardware which gives a unique id (serial number). Distributor/seller generates the signature using unique id and put it to the eeprom. Arduino program verifies this signature using hardware serial number. Arduino program is distributed in binary or within the device.

body:
I found a way! I can use DS2401 or DS2411.

These devices are 64-bit read only memory (ROM) "silicon serial number" devices which are programmed by the manufacturer with a unique 48 bit serial number, an 8 bit product family code, and an 8 bit CRC.


body:
I still suggest using the eeprom.
It is the firmware's job to handle whether or not data in eeprom can be written.
You could implement wrapper functions for the arduino which can only read/write after a defined offset. You can set this read-only data with the .eep-file when you upload your sketch. The eeprom file then may be generated programmatically.

Once you have to flash several individual devices with a final firmware version, there are no benefits in using the arduino ide. You can upload the firmware and the eeprom file using avrdude:

    avrdude -P YOUR_PORT -b 115200 -p ATmega328P -e -U flash:w:YOUR_FIRMWARE.hex -U eeprom:w:YOUR_EEPROM.eep

It's up to you how to generate the eeprom file (bash/batch, make, pyhton,...).


message:
Can i combine an ultrasonic sensor and gps together?

I need to operate 2 different sensors by Arduino UNO: GPS module and Ultrasonic sensor. I have managed to run each one of them separately and I don't know how to manipulate the code;

## GPS MODULE ##

    #include <TinyGPS++.h>
    #include <SoftwareSerial.h>

    static const int RXPin = 4, TXPin = 3;
    static const uint32_t GPSBaud = 9600;

    // The TinyGPS++ object
    TinyGPSPlus gps;

    // The serial connection to the GPS device
    SoftwareSerial ss(RXPin, TXPin);

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

    void loop()
    {
      // This sketch displays information
      // every time a new sentence is correctly encoded.
      while (ss.available() > 0)
      {
        gps.encode(ss.read());
        if (gps.location.isUpdated())
        {
          Serial.print("Latitude= ");
          Serial.print(gps.location.lat(), 6);
          Serial.print(" Longitude= ");
          Serial.println(gps.location.lng(), 6);
        }
      }
    }

###ULTRASONIC SENSOR###

    // defines pins numbers
    const int trigPin = 9;
    const int echoPin = 10;

    // defines variables
    long duration;
    int distance;
    void setup()
    {
      pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
      pinMode(echoPin, INPUT); // Sets the echoPin as an Input
      Serial.begin(9600); // Starts the serial communication
    }

    void loop()
    {
      // Clears the trigPin
      digitalWrite(trigPin, LOW);
      delayMicroseconds(2);

      // Sets the trigPin on HIGH state for 10 micro seconds
      digitalWrite(trigPin, HIGH);
      delayMicroseconds(10);
      digitalWrite(trigPin, LOW);

      // Reads the echoPin, returns the sound wave travel time in microseconds
      duration = pulseIn(echoPin, HIGH);

      // Calculating the distance
      distance= duration*0.034/2;

      // Prints the distance on the Serial Monitor
      Serial.print("Distance: ");
      Serial.println(distance);
    }

body:
That's easy. I have no possibility to try it. But if your code has been working, this will also. (Just copy/paste.) I had to change the while loop into a if block, because I was not sure, if the while blocks for a longer time. It could have been that the GPS sends and sends and sends ... That would block the ultrasonic sensor.

    #include <TinyGPS++.h>
    #include <SoftwareSerial.h>

    static const int RXPin = 4, TXPin = 3;
    static const uint32_t GPSBaud = 9600;

    // The TinyGPS++ object
    TinyGPSPlus gps;

    // The serial connection to the GPS device
    SoftwareSerial ss(RXPin, TXPin);

    const int trigPin = 9;
    const int echoPin = 10;

    long duration;
    int distance;

    void setup()
    {
      Serial.begin(9600);
      ss.begin(GPSBaud);

      pinMode(trigPin, OUTPUT);
      pinMode(echoPin, INPUT);
    }

    void loop()
    {
      // This sketch displays information
      // every time a new sentence is correctly encoded.
      if (ss.available() > 0)
      {
        gps.encode(ss.read());
        if (gps.location.isUpdated())
        {
          Serial.print("Latitude= ");
          Serial.print(gps.location.lat(), 6);
          Serial.print(" Longitude= ");
          Serial.println(gps.location.lng(), 6);
        }
      }

      // Clears the trigPin
      digitalWrite(trigPin, LOW);
      delayMicroseconds(2);

      // Sets the trigPin on HIGH state for 10 micro seconds
      digitalWrite(trigPin, HIGH);
      delayMicroseconds(10);
      digitalWrite(trigPin, LOW);

      // Reads the echoPin, returns the sound wave travel time in microseconds
      duration = pulseIn(echoPin, HIGH);

      // Calculating the distance
      distance= duration*0.034/2;

      // Prints the distance on the Serial Monitor
      Serial.print("Distance: ");
      Serial.println(distance);
    }


message:
arduino circuit review/ safety review

I have the following circuit

It has a simple dc motor that is OFF, and switches ON once a day for 2 seconds.

I use MOSFET IRF540N as a switch

I use L7805CV as a voltage regulator

I would like to have a review and to ask whether it is safe to connect this circuit to a 9v 1A (center+) DC wall plug.

I have measured the dc motor and it takes 60 mA when it is on with 5V.

[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/CTfKO.png

body:
In general your circuit is fine, but the parts are pretty overpowered.
If there is a reasonable voltage drop at the IRF540N you better choose a mosfet with a lower gate-source threshold voltage, if it works I'd say it's fine.


body:
The "Arduino" part of your schematic looks OK. 9 VDC to VIN on the Uno is OK. Connecting the MOSFET directly to the Arduino is OK.

Personally, I would connect a 1000 ohm resistor in series between the Arduino pin and the gate of the MOSFET. If you like to live dangerously like I do, and change wiring connections with power supplied to your Arduino, then a 1k resistor will limit the maximum current flow to around 5 mA. This is not going to "fry" anything if you inadvertently connect an output to power or ground.

The question about the L7805CV is off-topic, but a quick look at the datasheet suggests an input and output capacitor should be used.

I’m sorry to be the bearer of bad news, but the IRF540N is a poor choice as a MOSFET to use with a micro-controller. While it’s true that you are only drawing 60 mA, the VGS specified for this MOSFET is at 10 VDC, not the 5 VDC supplied by the Uno. A "logic level" MOSFET would be better suited for your application.

For more information regarding MOSFETs, please read: [How to control a 12V solenoid valve with a mosfet?][1]

  [1]: https://electronics.stackexchange.com/questions/29065/how-to-control-a-12v-solenoid-valve-with-a-mosfet


body:
You should not use a "naked" L7805CV. That voltage regulator requires a couple of capacitors in order to build a functioning voltage regulator out of it. You should be able to find instructions online for how to build one. Search on "L7805CV circuit" and you should find quite a few sample circuits.

That said, 9V is a good unregulated voltage to provide to the Vin line on the Arduino. Its built-in voltage regulator should be able to regulate that to 5V quite well, even with "bobble" caused by motor. (The built-in voltage regulator is able to handle input voltages from 7.5V to 12V, although if you feed it 12V and draw a lot of current out of the 5V line you may have overheating problems.)

You should also use a "logic level" MOSFET that can be driven with a 5V gate voltage.


message:
publish json data to mqtt

I am trying to publish `JSON` data to mqtt with following code snippet

    #include <Arduino_JSON.h>
    JSONVar data;
    data["temperature"] = temperature;
    data["humidity"] = humidity;
    data["pressure"] = pressure;
    data["chipId"] = chipId;

    String jsonString = JSON.stringify(data);
    client.publish("esp32/data", jsonString);

But getting following error

    /home/ubuntu/Arduino/libraries/PubSubClient/src/PubSubClient.h:144:12: note:   candidate expects 4 arguments, 2 provided
    Multiple libraries were found for "PubSubClient.h"
     Used: /home/ubuntu/Arduino/libraries/PubSubClient
    Multiple libraries were found for "Wire.h"
     Used: /home/ubuntu/.arduino15/packages/esp32/hardware/esp32/1.0.4/libraries/Wire
    Multiple libraries were found for "Adafruit_BME280.h"
     Used: /home/ubuntu/Arduino/libraries/Adafruit_BME280_Library
    Multiple libraries were found for "Adafruit_Sensor.h"
     Used: /home/ubuntu/Arduino/libraries/Adafruit_Unified_Sensor
    Multiple libraries were found for "SPI.h"
     Used: /home/ubuntu/.arduino15/packages/esp32/hardware/esp32/1.0.4/libraries/SPI
    Multiple libraries were found for "Arduino_JSON.h"
     Used: /home/ubuntu/Arduino/libraries/Arduino_JSON
    Multiple libraries were found for "WiFi.h"
     Used: /home/ubuntu/.arduino15/packages/esp32/hardware/esp32/1.0.4/libraries/WiFi
     Not used: /opt/arduino-1.8.10/libraries/WiFi
    exit status 1
    no matching function for call to 'PubSubClient::publish(const char [11], String&)'

Whats is wrong here ?

body:
What's your last error message?
```
no matching function for call to 'PubSubClient::publish(const char [11], String&)'
```

[Read the documentation][1] for the `publish()` method in `PubSubClient`:

> int publish (topic, payload)
>
> Publishes a string message to the specified topic.
>
> Parameters
>
>   topic - the topic to publish to (const char[])
>
>   payload - the message to publish (const char[])

Look at the parameters you're using. You're passing a `String` as `payload`. `publish()` expects `payload` to be a `char[]` (essentially the same thing as a `char*`) - a C language string. This is the error you're seeing.

[Read the documentation][2] for `String`. How do you get a `char*` from a `String`? The `c_str()` method.

You need to change
```
client.publish("esp32/data", jsonString);
```

to
```
client.publish("esp32/data", jsonString.c_str());
```

As for your other warnings, it looks like your Arduino libraries are a mess with multiple conflicting libraries installed; if you want to get rid of the warnings, clean up your libraries.

  [1]: https://pubsubclient.knolleary.net/api.html#publish1
  [2]: https://www.arduino.cc/reference/en/language/variables/data-types/stringobject/


message:
Somewhat Obfuscated Serial With SIM800L and Uno R3

I am successfully communicating with my SIM800L from my UNOR3 aside form some errors. But the biggest problem is with the serial monitor.

Responses from the SIM800L are somewhat obfuscated in that some characters are randomly wrong. See a snippet below:
```
Initializing...

OK

+C⸮T'⸮⸮b⸮j

OK

88l4110068165694746f

O⸮

+CQEG:Y⸮⸮H⸮⸮*⸮⸮C⸮
ERROR
⸮> H⸮⸮*⸮⸮
F⸮ROR
H⸮⸮
ERRO
H⸮⸮*⸮⸮

```

My code is also below.
```
#include <SoftwareSerial.h>

//Create software serial object to communicate with SIM800L
SoftwareSerial mySerial(11,10); //SIM800L Tx & Rx is connected to Arduino #3 & #2

void setup()
{

  pinMode(2, INPUT);
  pinMode(3, OUTPUT);
  //Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
  Serial.begin(115200);

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

  Serial.println("Initializing...");
  delay(1000);

  mySerial.println("AT"); //Once the handshake test is successful, it will back to OK
  updateSerial();
  mySerial.println("AT+CSQ"); //Signal quality test, value range is 0-31 , 31 is the best
  updateSerial();
  mySerial.println("AT+CCID"); //Read SIM information to confirm whether the SIM is plugged
  updateSerial();
  mySerial.println("AT+CREG?"); //Check whether it has registered in the network
  updateSerial();
  mySerial.println("AT+CMGF=1"); // Configuring TEXT mode
  updateSerial();
  mySerial.println("AT+CNMI=1,2,0,0,0"); // Decides how newly arrived SMS messages should be handled
  updateSerial();
  mySerial.println("AT+CMGS=\"+447518103652\"");//change ZZ with country code and xxxxxxxxxxx with phone number to sms
  updateSerial();
  mySerial.print("System on!"); //text content
  updateSerial();
  mySerial.write(26);

  delay(1000);
}

int milli = millis();
void loop()
{
  if (digitalRead(2) == HIGH) {
    digitalWrite(3, HIGH);
  mySerial.println("AT+CMGS=\"+447518103652\"");//change ZZ with country code and xxxxxxxxxxx with phone number to sms
  updateSerial();
  mySerial.print("Button Pressed!"); //text content
  updateSerial();
  mySerial.write(26);
  } else {
    digitalWrite(3, LOW);
  }

  if (milli <= millis() - 500) {
    updateSerial();
    milli = millis();
  }
}

void updateSerial()
{
  //delay(300);
  while (Serial.available())
  {
    mySerial.write(Serial.read());//Forward what Serial received to Software Serial Port
  }
  while(mySerial.available())
  {
    Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
  }
}
```

The SIM800L runs off a separate power supply with a decoupling cap of 100n and the grounds are commoned.

body:
Here is a good documentation: https://lastminuteengineers.com/sim800l-gsm-module-arduino-tutorial/ --

Did you add a voltage divider to the RX pin?
If Arduino drive 5 Volt to the module's pin, the module might be destroyed.

The module has an automatic baud rate detection, so 115200 baud should be OK.
Do you configured your terminal with 115200 baud for the serial communication?

While sending, the Software Serial switches off all interrupts to make the micro clock more accurate. That might distort a timer interrupt for the hardware serial (but I don't really know, whether it needs one).

You changed the pins 2 and 3 for software serial (as from the example) to `SoftwareSerial mySerial(11,10);` Did you add the connections to the right pins. (RX?? <--> TX??)?

And last but not least. The axample uses 9600 baud for both serial interfaces. Perhaps your decision 115200 is too high.


message:
while(1) inside if conditional

if (!MDNS.begin("esp8266")) {
        Serial.println("Error setting up MDNS responder!");
        while (1) {
          delay(1000);
        }
      }

I know this will result in an infinite loop if the `if` conditional is never satisfied, however I was wondering if this code would still result in an infinite loop if say, after 3 iterations the `if` conditional is satisfied?

Or if something like:

    while(!MDNS.begin("esp8266")) {
       delay(1000);
    }

is different?

Code from: https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266mDNS/examples/mDNS_Web_Server/mDNS_Web_Server.ino (line 58)

body:
In the first case, the first time, that the outer if statement becomes true, the code will go into the `while(1)` loop and will be stuck there forever.

The second code is different, since the `while` loop will check at each start of it's iteration, if the condition is still met. If not, it will exit, so not necessarily an infinite loop.

---

Going into an infinite loop, if something fails to initialize is often done in the microcontroller world, especially when initializing external hardware. A reset loop (restarting until it works) is mostly not fitting there, because often it is not just waiting for a resource to become free. Often this is used for serious problems, for example external hardware not being there or functioning. Imagine trying to use an external GPS chip, but the chip is not there. It should be there, since the device is build this way. Why should a reset loop be better here? The problem won't get away with time. Or imagine, that the initialization fails, because the GPS chip is broken. Trying to interface such a broken chip repeatedly might break even more things. Either way, someone has to look at this, to fix the problem. It will not go away by itself.

I would say, that the failed initialization in the library above is such a situation.


body:
This is likely a case where the original code needs to be inspected to understand the purpose of the infinite loop.  In the original code we see this:

      if (!MDNS.begin("esp8266")) {
        Serial.println("Error setting up MDNS responder!");
        while (1) {
          delay(1000);
        }
      }
      Serial.println("mDNS responder started");

Here, it can be inferred the infinite loop is used to preserve the error message on the serial monitor.  By doing so prevents subsequent messages from announcing the Domain Name Server has started.  Which may confuse the user.

As mentioned in other answers, infinite loops are often used to purposely reset a processor.  However, this approach depend on an actively running [watch dog][1] feature.  A feature that is not normally active or even supported in the Arduino development environment.  Perhaps because the watch dog feature is considered an intermediate to advanced topic.

  [1]: https://en.wikipedia.org/wiki/Watchdog_timer


message:
8 digit 7 segment display issues

I've been trying to follow a few tutorials on how to get the 7 segment to display simple output but none seem to work 100%.

It starts out fine. It increments the number across the screen and then writes 8s to all of them and then reverses. After a few loops however it starts to act weird. Here's a video link where it acts a bit weird (a few digits don't write correctly and fix themselves) and then at the end, it only displays half of the 8 digit display before it goes to 8s and crashes. https://youtu.be/LD_C7I_bGyc

Here's the code:

    //We always have to include the library
    #include "LedControl.h"

    // pin 4 is connected to the DIN pin
    // pin 2 is connected to the CLK pin
    // pin 3 is connected to the CS pin
    // 1 as we are only using 1 MAX7219
    LedControl lc = LedControl(4, 2, 3, 1);

    void setup(){
        // the zero refers to the MAX7219 number, it is zero for 1 chip
        lc.shutdown(0, false);// turn off power saving, enables display
        lc.setIntensity(0, 0);// sets brightness (0~15 possible values)
        lc.clearDisplay(0);// clear screen
    }

    void loop(){
        // numbers 7 to 0
        for (int a = 0; a < 8; a++){
            lc.setDigit(0, a, a, false);
            delay(100);
        }
        delay(1000);
        // display number 8 on all segments
        for (int a = 0; a < 8; a++){
            lc.setDigit(0, a, 8, false);
            delay(100);
        }
        delay(1000);

        for (int a = 8; a >= 0; a--){
            lc.setDigit(0, a, a, false);
            delay(100);
        }
    }

Hardware:
   Arduino Uno: https://www.jaycar.com.au/duinotech-uno-r3-development-board/p/XC4410
   8 digit display: https://www.jaycar.com.au/8-digit-7-segment-display-module/p/XC3714

At this stage it's hard to tell if it's a hardware issue or if it's setup related. If someone could please give me some insight or maybe run it if they have the same hardware that would be fantastic.

Thanks!

body:
The last loop exceeds the limits of 8 Digits. You iterate 9 times (0-8).

       for (int a = 7; a >= 0; a--){
            lc.setDigit(0, a, a, false);
            delay(100);
        }


body:
This was an unexpected result. @Dougie was pretty on to it. I didn't know how to adjust the timings as I was pretty sure the library took care of it, so the only thing I could think of was to redo all the wiring again. That's when I noticed that the ground wire pin into the board was half sticking out.

In the video you can see the ground pin at the top right. So it was making a connection (otherwise the whole thing wouldn't work), but after replacing the wire it runs fine. So that would have messed up the timings if the connection was unstable.