# Question
Title: Arduino Serial Monitor displaying weird characters and changes spelling
I am recieving the following in my serial monitor. There is a mix of wierd characters then the spelling changes for words once it gets repeated. I don't know why its doing this. my esp01 chip uses 115200 baud rate and the program is 115200 baud rate as well. What is going on.

```
#include <SoftwareSerial.h>

#define TIMEOUT 5000 // mS
#define LED 5

SoftwareSerial mySerial(7, 6); // RX, TX

const int button = 11;
int button_state = 0;

void setup()
{
  pinMode(LED, OUTPUT);
  pinMode(button, INPUT);

  Serial.begin(115200);
  mySerial.begin(115200);

  SendCommand("AT+RST", "Ready");

  delay(5000);

  SendCommand("AT+CWMODE=3", "OK");
  SendCommand("AT+CIFSR", "OK");
  SendCommand("AT+CIPMUX=1", "OK");
  SendCommand("AT+CIPSERVER=1,80", "OK");
}

void loop() {
  button_state = digitalRead(button);
  mySerial.println(button_state);

  if (button_state == HIGH) {
    SendCommand("AT+CIPSEND=0,23", "OK");

    delay(250);

    mySerial.println("<h1>Button was pressed!</h1>");

    delay(250);

    SendCommand("AT+CIPCLOSE=0", "OK");
  }

  String IncomingString = "";
  boolean StringReady = false;

  while (mySerial.available()) {
    IncomingString = mySerial.readString();
    StringReady = true;
  }

  if (StringReady) {
    Serial.println("Received String: " + IncomingString);

    if (IncomingString.indexOf("LED=ON") != -1) {
      digitalWrite(LED, HIGH);
    }

    if (IncomingString.indexOf("LED=OFF") != -1) {
      digitalWrite(LED, LOW);
    }
  }
}

boolean SendCommand(String cmd, String ack) {
  mySerial.println(cmd); // Send "AT+" command to module

  if (!echoFind(ack)) // timed out waiting for ack string
    return true; // ack blank or ack found
}

boolean echoFind(String keyword) {
  byte current_char = 0;
  byte keyword_length = keyword.length();
  long deadline = millis() + TIMEOUT;

  while (millis() < deadline) {
    if (mySerial.available()) {
      char ch = mySerial.read();
      Serial.write(ch);

      if (ch == keyword[current_char])
        if (++current_char == keyword_length) {
          Serial.println();
          return true;
        }
    }
  }

  return false; // Timed out
}

```

# Answer
> 1 votes
Try adding:

```
void setup()
{
  pinMode(LED, OUTPUT);
  pinMode(button, INPUT);

  Serial.begin(115200);
  while(!Serial){}       // Loop until USB is ready

  mySerial.begin(115200);

```

It will unblock once the USB port is ready.

# Answer
> 0 votes
Your code for the most part looks ok. Your symptoms indicate a Baud mismatch or the receiver is not getting all of the bits. Try doing without the delay's, even reducing them may help. Note when in a delay the processor is committed and cannot do anything else. See if that helps. 115000 baud is quit hot for the Arduino and software serial. Maybe you can slow things down a little and see if that helps.

---
Tags: wifi
---


# Question
Title: How to use RTC memory in NodeMCU to count awakes from deep sleep?
Problem: I need to retry at least 3 times (before giving up) to reconnect my NodeMCU if it doesn't get connected to Wifi, through deep sleep cycles in order to save batteries. I thought to use RTC memory to save a counter, but it doesn't work because content of RTC RAM is unpredicatble at first power up.

Following is a NOT WORKING code, but it gives the idea of what I need to achieve. The problem is: the kounter variable is persistent through cycles, but its very first value is unpredicatble.

```
#define DONEPIN 5
uint32_t kounter;

void setup() {
    digitalWrite(DONEPIN, HIGH);
    //WiFi setup functions...
    // .....
    if (WiFi.status() != WL_CONNECTED) {
        ESP.rtcUserMemoryRead(0, &kounter, sizeof(kounter));
        kounter++
        if (kounter > 3) {
            digitalWrite(DONEPIN, LOW);
        }
        ESP.rtcUserMemoryWrite(0, &kounter, sizeof(kounter));
        ESP.deepSleep(60e6);
    }
}

```

# Answer
> 2 votes
The simplest trick is to use more than one memory location. Have one, as you have now, as a counter, and then have one or more as a "This has been configured" flag.

Ideally you want the flag to have a very low probability of occurring randomly, so using a combination of a number of memory locations would improve that.

For instance, if you read memory locations 1-4 and look for four specific bytes, that gives you about a 1 in 4 billion possibility of it happening randomly.

If you don't see those four bytes, you set the counter byte to 0 (or whatever you want your initial value to be) and set the other 4 memory locations to contain your 4 flag bytes.

Using 8 bytes for your flag would give you in the order of 1 in 1.8x1019 chance of it occuring randomly.

These "flag byte combination" are often called "magic numbers" and are used all over the place to identify either *what* something is, or if something is *valid*.

# Answer
> 2 votes
I realize this is *really* old, but it is still the top of the list when you search for RTCmem read/write. While it isn't maybe as "by the book" as the 'correct' answer above, there is a really simple way to deal with the "the rtcmem value is something ridiculous on first read" issue. When you first power on the esp8266 or after a button-based reset, the rtcmem value WILL be something insane. You can account for it in the code by ignoring anything that is outside the count you want. Since my application "sleeps" for 4 hours, which in esp8266 means 4, 1 hour loops, I simply say if the rtcMem value is outside that range, it is obviously bogus, set it to what I want, and go about your business:

```
void writeToRTCMemory() {
  if (rtcMem.count == MAXHOUR) {
    rtcMem.count = 1;
  } else {
    if (rtcMem.count < 1) {
      rtcMem.count = 1;
    }
    if (rtcMem.count > 4) {
      rtcMem.count = 1;
    }
    rtcMem.count++;
  }

```

As long as your device has not lost power, or you have not pushed the reset button, this will keep it looping the way you want for as long as it has enough juice to deep sleep. (My solar powered sensors with this loop last around 2/2.5 weeks in the mid winter and much longer in summer)

---
Tags: esp8266, nodemcu, rtc
---


# Question
Title: Why am I getting a "SendCommand was not declared" error?
```
#include <Adafruit_Fingerprint.h>
#include  <SoftwareSerial.h>
#include <LiquidCrystal.h>

uint8_t id;
int getFingerprintIDez();
//pin #16 is IN from sensor (GREEN wire)
//pin #15 is OUT from arduino (WHITE wire)
int Contrast = 100;
SoftwareSerial mySerial(52, 16);
LiquidCrystal lcd(13, 12, 11, 10, 9, 8); // initialize the library with the numbers of the interface pins
Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);
#define S1 22 //Button candidate A
#define S2 24 // Button candidate B
#define S3 26 // Button candidate c
#define S4 28 // Button candidate D
#define S5 30 // Button Result
#define S6 2 // Button submit
#define S7 32 // Button to cast vote
int can1 = 0;
int can2 = 0;
int can3 = 0;
int can4 = 0;
int total;
SoftwareSerial ESP8266(50, 18);// RX, TX

void setup() {
  Serial.begin(9600); // initialize the serial communications:
  lcd.begin(16, 2); lcd.clear();
  lcd.print("  Polling Day  ");
  lcd.setCursor(0, 1);
  lcd.print("      UPM      ");
  delay(2000);

  mainpage();

  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(A0, INPUT);

  finger.begin(57600); // set the data rate for the sensor serial port

  pinMode(S1, INPUT);
  pinMode(S2, INPUT);
  pinMode(S3, INPUT);
  pinMode(S4, INPUT);
  pinMode(S5, INPUT);
  pinMode(S6, INPUT);
  pinMode(S7, INPUT);

  ESP8266.begin(9600);

  digitalWrite(S1, HIGH);
  digitalWrite(S2, HIGH);
  digitalWrite(S3, HIGH);
  digitalWrite(S4, HIGH);
  digitalWrite(S5, HIGH);
  digitalWrite(S6, HIGH);
  digitalWrite(S7, HIGH);

  SendCommand("AT+RST", "Ready");
  delay(5000);
  SendCommand("AT+CWMODE=1", "OK");
  SendCommand("AT+CIFSR", "OK");
  SendCommand("AT+CIPMUX=1", "OK");
  SendCommand("AT+CIPSERVER=1,80", "OK");
}

void loop() { // run over and over again
  getFingerprintID();
  delay(100);
  digitalWrite (13, HIGH);
  if (digitalRead(S5) == 0) { // To view the result for admin only
    int total = can1 + can2 + can3 + can4;
    lcd.clear();
    lcd.setCursor(1, 0);
    lcd.print("1");
    lcd.setCursor(1, 1);
    lcd.print(can1);
    lcd.setCursor(5, 0);
    lcd.print("2");
    lcd.setCursor(5, 1);
    lcd.print(can2);
    lcd.setCursor(9, 0);
    lcd.print("3");
    lcd.setCursor(9, 1);
    lcd.print(can3);
    lcd.setCursor(13, 0);
    lcd.print("4");
    lcd.setCursor(13, 1);
    lcd.print(can4);
    delay(4000);
    if (total) {
      if ((can1 > can2 && can1 > can3 && can1 > can4)) {
        lcd.clear();
        lcd.print("Can A is Winner");
        delay(3000);
        lcd.clear();
      } else if ((can2 > can1 && can2 > can3 && can2 > can4)) {
        lcd.clear();
        lcd.print("Can B is Winner");
        delay(3000);
        lcd.clear();
      } else if ((can3 > can1 && can3 > can2 && can3 > can4)) {
        lcd.clear();
        lcd.print("Can C is Winner");
        delay(3000);
        lcd.clear();
      } else if (can4 > can1 && can4 > can2 && can4 > can3) {
        lcd.setCursor(0, 0);
        lcd.clear();
        lcd.print("Can D is Winner");
        delay(3000);
        lcd.clear();
      } else if (can4 > can1 && can4 > can2 && can4 > can3) {
        lcd.setCursor(0, 0);
        lcd.clear();
        lcd.print("Can D is Winner");
        delay(3000);
        lcd.clear();
      } else {
        lcd.clear();
        lcd.print(" Tie Up Or ");
        lcd.setCursor(0, 1);
        lcd.print(" No Result ");
        delay(3000);
        lcd.clear();
      }
    } else {
      lcd.clear();
      lcd.print("No Voting....");
      delay(3000);
      lcd.clear();
    }
    can1 = 0; can2 = 0; can3 = 0; can4 = 0, total = 0;
    lcd.clear();
    adminpage();
  }

  if (digitalRead(S7) == 0) { //To cast avote for user
    voterpage();
  }

  if (digitalRead(S1) == 0) {
    can1++;
    votereceived();
    mainpage();
  }

  while (digitalRead(S1) == 0);
  if (digitalRead(S2) == 0) {
    can2++;
    votereceived();
    mainpage();
  }
  while (digitalRead(S2) == 0);
  if (digitalRead(S3) == 0) {
    can3++;
    votereceived();
    mainpage();
  }
  while (digitalRead(S3) == 0);
  if (digitalRead(S4) == 0) {
    can4++;
    votereceived();
    mainpage();
  }
  while (digitalRead(S4) == 0);
  if (digitalRead(S6) == 0) {
    lcd.clear();
    lcd.print("Submitting...");
    delay(1000);
    ESP8266.println("AT+CIPSEND=0,23");
    delay(1000);
    SendCommand("AT+CIPCLOSE=0", "OK");
  }
  String IncomingString = "";
  boolean StringReady = false;

  while (ESP8266.available()) {
    IncomingString = ESP8266.readString();
    StringReady = true;
  }

  if (StringReady) {
    Serial.println("Received String: " + IncomingString);

    if (IncomingString.indexOf("LED=ON") != -1) {
      digitalWrite(LED, HIGH);
    }

    if (IncomingString.indexOf("LED=OFF") != -1) {
      digitalWrite(LED, LOW);
    }
  }

  boolean SendCommand(String cmd, String ack) {
    ESP8266.println(cmd); // Send "AT+" command to module
    if (!echoFind(ack)) // timed out waiting for ack string
      return true; // ack blank or ack found
  }

  boolean echoFind(String keyword) {
    byte current_char = 0;
    byte keyword_length = keyword.length();
    long deadline = millis() + TIMEOUT;
    while (millis() < deadline) {
      if (ESP8266.available()) {
        char ch = ESP8266.read();
        Serial.write(ch);
        if (ch == keyword[current_char])
          if (++current_char == keyword_length) {
            Serial.println();
            return true;
          }
      }
    }
    return false; // Timed out
  }
}

uint8_t getFingerprintID() {
  uint8_t p = finger.getImage();
  switch (p) {
    case FINGERPRINT_OK:
      lcd.clear();
      lcd.print(" Image taken... ");
      delay(1000);
      break;
    case FINGERPRINT_NOFINGER:
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      return p;
    case FINGERPRINT_IMAGEFAIL:
      return p;
    default:
      return p;
  }

  // OK success!
  p = finger.image2Tz();
  switch (p) {
    case FINGERPRINT_OK:
      break;
    case FINGERPRINT_IMAGEMESS:
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      return p;
    case FINGERPRINT_FEATUREFAIL:
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      return p;
    default:
      return p;
  }

  // OK converted!
  p = finger.fingerFastSearch();
  if (p == FINGERPRINT_OK) {
    if (finger.fingerID == 26) {
      lcd.clear();
      lcd.setCursor(1, 0);
      lcd.print("Redirecting to");
      lcd.setCursor(1, 1);
      lcd.print("Admin process");
    } else {
      lcd.clear();
      lcd.setCursor(2, 0);
      lcd.print("Valid Voter!");
      lcd.setCursor(2, 1);
      lcd.print("ID : ");
      lcd.print(finger.fingerID);
    }

    digitalWrite(11, HIGH);
    delay(1000);
    digitalWrite(11, LOW); // turn on green LED to indicate match
  } else if (p == FINGERPRINT_NOTFOUND) {
    lcd.clear();
    lcd.setCursor(1, 0);
    lcd.print("Unregistered");
    lcd.setCursor(3, 1);
    lcd.print("Voter!");
    delay(1000);
    lcd.clear();
    lcd.setCursor(2, 0);
    lcd.print("scan finger");
    lcd.setCursor(6, 1);
    lcd.print("again");
    return p;
  } else {
    return p;
  }

  // IF FOUND A MATCH............
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Found ID #");

  if (finger.fingerID == 26) {
    adminpage();
  } else {
    voterpage();
  }
}

// returns -1 if failed, otherwise returns ID #
int getFingerprintIDez() {
  uint8_t p = finger.getImage();
  if (p != FINGERPRINT_OK) return -1;
  p = finger.image2Tz();
  if (p != FINGERPRINT_OK) return -1;
  p = finger.fingerFastSearch();
  if (p != FINGERPRINT_OK) return -1;
  // found a match!
  digitalWrite(13, LOW);
  delay(10);
  digitalWrite(13, HIGH);
  delay(10);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Found ID # ");
  lcd.print(finger.fingerID);
  lcd.setCursor(0, 1);
  lcd.print("confidence ");
  lcd.print(finger.confidence);
  return finger.fingerID;
}

void voterpage() {
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("Candidate 1");
  lcd.setCursor(1, 1);
  lcd.print("Mohd Faiz");
  delay(3000);
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("Candidate 2");
  lcd.setCursor(1, 1);
  lcd.print("Siti Nur Ila");
  delay(3000);
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("Candidate 3");
  lcd.setCursor(1, 1);
  lcd.print("Muhammad Aus");
  delay(3000);
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("Candidate 4");
  lcd.setCursor(1, 1);
  lcd.print("Wan zakaria");
  delay(3000);
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("Choose 1 only");
  lcd.setCursor(1, 1);
  lcd.print("1");
  lcd.setCursor(5, 1);
  lcd.print("2");
  lcd.setCursor(9, 1);
  lcd.print("3");
  lcd.setCursor(13, 1);
  lcd.print("4");
}

void votereceived() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Vote Received");
  lcd.setCursor(2, 1);
  lcd.print("Thank You :)");
  delay(2000);
}

void adminpage() {
  lcd.clear();
  lcd.setCursor(3, 0);
  lcd.print("1");
  lcd.setCursor(1, 1);
  lcd.print("Result");
  lcd.setCursor(11, 0);
  lcd.print("2");
  lcd.setCursor(8, 1);
  lcd.print(" Submit");
  delay(2000);
}

void mainpage() {
  lcd.clear(); lcd.setCursor(0, 0); lcd.print("Scan your finger");
}

```

# Answer
> 2 votes
Both `boolean SendCommand()` and `boolean echoFind()` are defined inside `loop()`, and they shouldn't be; it is not allowed to define functions inside functions.

Take them out of `loop()` and define them at (move them to) the same level as `uint8_t getFingerprintID()`, etc.

---
Tags: esp8266, arduino-mega, adafruit, compilation-errors, command-line
---


title: Error while burning bootloader

text:
# Question
Title: Error while burning bootloader
I am trying to burn bootloader on Arduino UNO using MEGA2560 as the programmer, I followed the steps stated here but still get the error below:

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

         System wide configuration file is "/home/arduino/arduino-nightly/hardware/tools/avr/etc/avrdude.conf"
         User configuration file is "/home/webdev/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

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

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

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

avrdude: AVR device initialized and ready to accept instructions

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

avrdude: Device signature = 0x000000 (retrying)

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

avrdude: Device signature = 0x000000 (retrying)

Error while burning bootloader.
Reading | ################################################## | 100% 0.02s

avrdude: Device signature = 0x000000
avrdude: Yikes!  Invalid device signature.
         Double check connections and try again, or use -F to override
         this check.

avrdude done.  Thank you.

```

**Note:** The Arduino UNO stopped responding when I mistakenly short-circuited a connection, I mistakenly passed 12v to one of the header pins of sensor shield mounted on the board.

**How it was connected**

# Answer
Based on this:

> Note: The Arduino UNO stopped responding when I mistakenly short-circuited a connection, I mistakenly passed 12v to one of the header pins of sensor shield mounted on the board.

There are no I/O pins on the Arduino that are 12V tolerant. You have almost certainly "fried" your Uno board. It's possible the only casualty is the ATMega chip itself and replacements are available from a number of sources or you can purchase a "raw" one from an electronics reseller and use your programmer setup above to burn your own boot loader.

It's also quite likely that your sensor board is damaged as well.

From the Microchip datasheet:

You want something like this:

Adafruit Pre-programmed ATMega168p

Buy several, accidents happen!
> 2 votes

---
Tags: arduino-uno, arduino-mega, bootloader, avrdude
---


# Question
Title: Stepper Motor is not working with A4988 board
So, I have been following this tutorial on how to run a stepper motor with Arduino using an A4988 Stepper Driver. This is the tutorial: How To Control a Stepper Motor with A4988 Driver and Arduino. I have connected the wires according to this schematic:

I have connected the wires exactly like this and triple-checked it! The problem is the stepper motor is not turning. This is the code(it's simple):

```
// defines pins numbers
const int stepPin = 3;
const int dirPin = 4;

void setup() {
  // Sets the two pins as Outputs
  pinMode(stepPin,OUTPUT);
  pinMode(dirPin,OUTPUT);
}

void loop() {
  digitalWrithe(dirPin,HIGH); // Enables the motor to move in a particular direction
  // Makes 200 pulses for making one full cycle rotation
  for(int x = 0; x < 200; x++) {
    digitalWrite(stepPin,HIGH);
    delayMicroseconds(500);
    digitalWrite(stepPin,LOW);
    delayMicroseconds(500);
  }
  delay(500); // One second delay
}

```

One weird thing:

> **When I connect the sleep and reset pin on the A4988 board the stepper motor starts turning. Like why?**

**NOTE:** I replaced the MEGA with a UNO because at the moment I'm just testing.

# Answer
> 4 votes
You have to connect the sleep and reset pin together. I assume that you took this schema on how to mechatronics. In his video you see that the sleep and reset pins are connected. I don't know why but it has to be like that.

Then, if the motor vibrates or click, it may be one of these problems:

* You didn't connect the motor properly
* The current is set too low on the board (screw on the motor driver)
* The battery (Vmot) isn't powerful enough

If it's not one of those problems, the A4988 chip might have an issue. I have a similar problem where it turn in one direction and only when the pwm signal goes throught the direction pin instead of the step pin.

---
Tags: arduino-uno, stepper, stepper-motor, a4988
---


# Question
Title: How do I convert Arduino to an ATmega328P-based project?
I have an Arduino board where I am using some of the peripherals like LCD with I2C.

Now I want to convert this Arduino-based circuit to an atmega328p based circuit, i.e. atmega328p with LCD and I2C.

Here is my actual question: Can I use the same sketch (binary) that I have compiled and uploaded for the Arduino board for the atmega328p and does it work? Or do I need to write atmega328p based C++ code?

# Answer
A compiled sketch will run just fine on a bare ATmega328p, if all the necessary surrounding components are there, and if you have a way to program it.

This could be as simple as putting the chip on the Uno and programming it there. Don't do that too often; the socket isn't intended for that. You could get a 28-pin ZIF socket, though.

There are a few things to consider:

* The bare chip needs external components like a crystal, etc. to function; you can check the Uno's schematic to see what you want to copy to your PCB/breadboard;
* You may want to include a way to program the ATmega328p in-circuit using an ISP or a USB-to-serial chip;
* The pin numbers will be different, a minor annoyance;
* Possibly things I forgot.

There is a how-to on the Arduino site, and also a description of how to build a "whole" Arduino on a breadboard.
> 4 votes

# Answer
I've built PCBs with a standalone ATMega328p chip on them before for situations where I wanted all my electronics embedded onto a single board. It can be a great learning experience imo.

I would suggest first creating a schematic and implementing it on a breadboard with DIP packages as seen on the photo. You will need a crystal, loading caps (22 pF), as well as bypass caps (100nF) and pull-up resistors. Plus any other components your application requires.

After that typically you would burn a boot loader onto the chip so it can be programmed with the Arduino IDE.

Nick Gammon has provided an excellent tutorial on all of this. His article was my main resource when I made my PCBs: http://www.gammon.com.au/breadboard

Once you get everything working on a breadboard, you may want to look into laying out a PCB for a more permanent solution. Best of luck!
> 2 votes

# Answer
Unable to write in the comments. If you are looking at using just a raw atmega328p, you can use the Arduino as ISP sketch and then upload your existing sketch to the new chip. I use it for programming ATTiny 85 chips for small stand alone projects. Here is a Link to the Arduino site which explains this in detail.
> 1 votes

# Answer
Yes, you can use the same sketch and also the same HEX file. Though the uploading depends on your actual setup. If you include a UART USB bridge, like the Arduino has, then you can upload over USB (assuming you have burned the bootloader to the Atmega328p). Otherwise you can use your Arduino as an ISP programmer and burn your sketch onto the Atmega through it. Google for Arduino as ISP for more information
> 1 votes

# Answer
The Arduino has already a 328p chip on the board, but with a bootloader and a 16MHz crystal.

If you use only the chip, you need to create a board like the arduino. Or you can extend the IDE with this board library: https://github.com/MCUdude/MiniCore

So you can still use the same sketch but remove the crystal for example.
> 0 votes

---
Tags: arduino-uno, atmega328
---


title: PulseIn tachometer

text:
# Question
Title: PulseIn tachometer
I tried to create a tachometer for my motorcycle using an Arduino Uno.
I am trying to measure the voltage of the ignition coil (stepped down to not destroy the Arduino).

I am trying to determine the time between two explosions (one ignition coil high voltage).

I tried to use the `pulseIn` command in the following way:

```
unsigned pin=8;
float t;

unsigned long rpm;

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

void loop() {

    rpm=pulseIn(pin,LOW);

    Serial.println(rpm/60);
}

```

The problem with it is that it won't display stable values. It will go all crazy. With an open circuit it still displays random values.

# Answer
No one mentioned that there is back EMF from primary coil when switch (or points) becomes open. This means that there is 200-300V applied backwards to your voltage divider while you think there is only 0-12V.
> 2 votes

# Answer
I can't tell you why that isn't working, but I can give you a working alternative.

```
unsigned int pin=8;

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

void loop() {
    unsigned float rpm = 0;

    while (digitalRead(pin) == FALSE) {
        rpm++;
        delayMicroseconds(1);
    }

    Serial.println(rpm/60);
}

```

I might've forgotten something, but that should work.

Edit: the comments may be right, are you stepping down your input voltage?
> 0 votes

---
Tags: pulsein
---


# Question
Title: The PCM libary won't work on an Arduino Nano
I'm using the PCM(http://highlowtech.org/?p=1963) library on the Arduino nano, I'm plugging the speaker(https://www.amazon.com/gp/product/B07WZP4QFK/ref=ox\_sc\_act\_title\_3?smid=A2O4FZXIRZDLHA&psc=1) into pin 11 and ground, but the example file won't work.

# Answer
I guess the Nano had a sketch which was setting pin 11 HIGH (using SPI?) as you turned it on with a 4 Ohm speaker attached without any other resistance. It created a short circuit and damaged the pin's circuit.

Using tone() or the PCM library with a speaker connected without additional resistor doesn't damage the pin immediately because it is then HIGH only for very short moments, but it stresses the pin circuit too.

The linked page recommends to use direct speaker connection because it is much louder then with a resistor in series, but this is a wrong advice. It should recommend an amplifier module for example with LM386 IC.

A piezo speaker has higher resistance so it can be connected directly to Arduino pin, but a piezo sounds loud only in high frequencies so with the PCM library the sound is like whispering.
> 1 votes

---
Tags: arduino-nano, speaker
---


# Question
Title: SSD1306 shows static when I try to display an XBM image
This is my circuit.

This is the code.

```
    #include "U8glib.h" // include the universal graphcs library

    U8GLIB_SSD1306_128X64 u8g(12, 11, 10, 9, 8);  // initialise a u8g display object

    const uint8_t flux_xbm[] PROGMEM = {
       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x56, 0x6D, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xEF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0x69, 0x92,
  0x6E, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xC1, 0xFF, 0xFE, 0xFF, 0xFF,
  0xFF, 0x3F, 0x80, 0x01, 0xF5, 0x7E, 0xFF, 0xFF, 0xFF, 0xFB, 0x00, 0xC2,
  0x3F, 0x21, 0xF4, 0xFF, 0xFF, 0xFF, 0x36, 0x6C, 0xBE, 0x7F, 0xFC, 0xFF,
  0xFF, 0xFF, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x86, 0x61,
  0xDE, 0x4F, 0xFE, 0xFF, 0xFF, 0xFB, 0x64, 0xE4, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x3F, 0x20, 0x04, 0xFC, 0x63, 0xFA, 0xFF, 0xFF, 0xFD, 0x24, 0xCD,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x95, 0xA9, 0x7F, 0x08, 0xFC, 0xFF,
  0xFF, 0xF7, 0x27, 0xDA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0x00,
  0x04, 0x50, 0xFC, 0xFF, 0xFF, 0xFF, 0xD9, 0xC9, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x3F, 0x10, 0x01, 0x21, 0x90, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x02, 0x84, 0x08, 0x02, 0xFC, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x04, 0x00,
  0x00, 0x28, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00,
  0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00,
  0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x1F, 0x00, 0x00, 0x80, 0x07, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0xC0, 0x05, 0xF8, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00,
  0xB8, 0x0F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x3F, 0x00, 0xE0, 0xFB, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0xF0, 0xFF, 0x0F, 0xF8, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0xBC,
  0xFE, 0x1F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x3F, 0x00, 0xDF, 0x49, 0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x4B, 0xA8, 0x1F, 0xF8, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x40, 0x00,
  0x40, 0x7A, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x1F, 0x80, 0x00, 0xA0, 0xFD, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x40, 0x00, 0x00, 0x7A, 0xFC, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00,
  0xA2, 0xF5, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x1F, 0x70, 0x00, 0x00, 0xF9, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x30, 0x00, 0xA0, 0xFC, 0xFD, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00,
  0x00, 0xE2, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x3F, 0x10, 0x00, 0x00, 0xD8, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0xD2, 0xB7, 0xFB, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xD0, 0x02,
  0x60, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x1F, 0x08, 0x35, 0xF4, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x40, 0x08, 0xDC, 0xD4, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x20, 0x36,
  0x16, 0x9F, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x1F, 0x42, 0xEC, 0xB7, 0xAB, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xA0, 0x67, 0xAB, 0xBC, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x40, 0x66,
  0xB4, 0x6A, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x3F, 0x34, 0x49, 0x06, 0x95, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x0B, 0x20, 0x5C, 0x0A, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1D, 0x10,
  0x5C, 0xE4, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0x1E, 0x08, 0xB8, 0xD5, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4A, 0x15, 0x64, 0x29, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x0E, 0x10,
  0xAA, 0x91, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x7F, 0x9E, 0x00, 0xB4, 0x6C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x0F, 0x12, 0xED, 0x6A, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x1F, 0x80,
  0x7E, 0x99, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x9F, 0x5F, 0x14, 0xBA, 0xD4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x5F, 0x41, 0xE4, 0x69, 0xFE, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xBF, 0x05,
  0xAA, 0x7B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0x3F, 0x7F, 0xD8, 0xF9, 0xD5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0x2A, 0xFA, 0xA8, 0xFD, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x4D,
  0x6A, 0xB7, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0x27, 0x90, 0xDA, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xFF, 0xFE, 0xF8, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F,
  0x6A, 0x7F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xF7, 0x7F, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x43, 0xD8, 0x7D, 0xFF, 0xDF,
  0xBF, 0x9B, 0xEF, 0xFF, 0x5F, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xBF, 0x43,
  0x88, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFE, 0xFB, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xEF, 0x41, 0xA8, 0xFF, 0x5D, 0x77, 0x9F, 0xBF, 0xE6, 0x77,
  0xFF, 0xFB, 0xFB, 0xFB, 0xFB, 0xFB, 0xF7, 0xEF, 0xFE, 0xEF, 0xFF, 0xFF,
  0xFF, 0xDB, 0xBF, 0xF7
    };

    void setup(void) {
    }

    void loop(void) {
      u8g.drawXBMP( 0, 0, 128, 64, flux_xbm); // send the xbm image to the display, specifying position and size
      while (1==1) {} // set the loop to only run once
    }

```

The image that it holds in XBM is this.

The output is this.  What is it that I am doing wrong? Edit 1- As reported by user timemage. The xbm array was 64x128 instead of 128x64 I have changed the image added a more simpler one but that still does not solve the problem,

# Answer
NOTE: This refers to an problem in the initial posting. The question **has since been edited**. This may be deleted later.

---

One problem, perhaps *the* problem, is that your given image appears to be 64x128 rather than 128x64:

That said, I'm not sure exactly why the screen is showing precisely what it does.

When you do get this showing in the correct resolution, I expect you'll be a bit unimpressed with the result though.
> 1 votes

---
Tags: oled, u8glib, ssd1306
---


title: Arduino fade to color change

text:
# Question
Title: Arduino fade to color change
I am making a fun LED Christmas tree project using this code:

```
// Source location \\adam\U_DRIVE\_BACKED_UP\_Documents\Electronics\XmasTree
#include <FastLED.h>
#define NUM_LEDS 102
#define DATA_PIN 6
CRGB leds[NUM_LEDS];
void setup() {
  Serial.begin(9600);
  Serial.println("Boot");
  // put your setup code here, to run once:
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

  //  SetRandomLight;
  SetAllOff();
  delay(10); //Delay before getting going.
  BootUp();
  randomSeed(analogRead(0) + analogRead(1) + analogRead(2) + analogRead(3) + analogRead(4) + analogRead(5) + analogRead(6));
}

void loop() {
  // put your main code here, to run repeatedly:
  SingleDrift();
  FastLED.show();
  //delay(random(50));
}

void FadeAll(int x)
{
  for (int i = 0; i < NUM_LEDS; i++)
  {
    leds[i].subtractFromRGB(x);
  }
}

void SetRandomLight() {
  for (int i = 0; i < NUM_LEDS; i++)
  {
    leds[i].r = random(128);
    leds[i].g = random(128);
    leds[i].b = random(128);
    Serial.println(i);
  }
}

void SetAllOff()
{
  Serial.println("Blanking all.");
  for (int i = 0; i < NUM_LEDS; i++)
  {
    leds[i] = 0x000000;
    leds[i].r = 0;
    leds[i].g = 0;
    leds[i].b = 0;

    //Serial.println(i);
  }
  FastLED.show();
}

void SingleDrift() {
  int mini = 5;
  int maxi = 255;
  FastLED.setBrightness(maxi);
  for (int i = 0; i < NUM_LEDS; i++)
  {
    if (leds[i].r > 64) leds[i].r = leds[i].r - 8;
    if (leds[i].g > 64) leds[i].g = leds[i].g - 8;
    if (leds[i].b > 64) leds[i].b = leds[i].b - 8;

    int rnd = random(10);
    if (rnd == 1 && leds[i].r >= 2) leds[i].r = leds[i].r - 1;
    if (rnd == 2 && leds[i].g >= 2) leds[i].g = leds[i].g - 1;
    if (rnd == 3 && leds[i].b >= 2) leds[i].b = leds[i].b - 1;
    if (rnd == 4) leds[i].fadeToBlackBy(2);
    if (rnd == 5) leds[i].g++;
    //if (rnd == 6 && leds[i].g < 240) leds[i].g = leds[i].g + 1;
    //if (rnd == 7 && leds[i].b < 240) leds[i].b = leds[i].b + 1;
    if (leds[i].g < 2) leds[i].g = 2;
  }

  int i = random(NUM_LEDS);
  Serial.println(i);
  if (leds[i].r + leds[i].g + leds[i].b > 10) return; //If the LED is still bright, do not change it.
  if (random(100) > 80)
  {
    //Choose a colour
    int r = random(20);
    switch (r)
    {
      case 99:
        for (i = 0; i < NUM_LEDS; i++)
        {
          int x = leds[i].r;
          leds[i].r = leds[i].b;
          leds[i].b = x;
        }

      case 1:
      case 2:
      case 3:
        leds[i] = CRGB::Red;
        break;
      case 4:
      case 5:
      case 6:
        leds[i] = CRGB::Green;
        break;
      case 7:
        leds[i] = CRGB::Blue;
        break;
      case 8:
        leds[i].r = random(128, 255);
        leds[i].g = random(128, 255);
        leds[i].b = random(128, 255);
      case 9:
        leds[i] = CRGB::Yellow;
        break;
      case 10:
        leds[i] = CRGB::Crimson;
        break;
      case 12:
        leds[i] = CRGB::Aqua;
        break;
      case 13:
        leds[i] = CRGB::BlueViolet;
        break;
      case 14:
        leds[i] = CRGB::MidnightBlue;
        break;
      case 15:
        leds[i].setRGB( 255, 255, 255);
        break;
    }
  }
}

void BootUp()
{
  for (int i = 0; i < NUM_LEDS; i++)
  {
    leds[i].b = map(i, 0, NUM_LEDS, 0, 255);
    leds[i].r = map(i, NUM_LEDS, 0, 0, 255);
  }
  for (int pc = 0; pc < 100; pc++)
  {
    FastLED.setBrightness(pc);
    FastLED.show();
    delay(3);
  }
  for (int i = 0; i < NUM_LEDS; i++)
  {
    leds[i] = -leds[i];
    FastLED.show();
    delay(10);
  }

  for (int i = 0; i < NUM_LEDS; i++)
  {
    leds[i].setRGB( 0, 10, 0);

    FastLED.show();
    delay(10);
  }
}

```

The LED cycle currently fades to green every time, so I would like to add different color fades. However, I could not figure out how to change the color/timing after poking around. Could someone please point me in the right direction for what I changes to the code I need to make?

# Answer
I think line 84 that keeps the leds green instead of going black. I think line 81 is there to create some kind of shimmer effect on some of the green leds and to skew the color to a bit more green. So I removed those. To prevent the leds from going to black instead of green, I added an if statement that stops any further fading out, if the total "brightness" is `16` or lower. I have no idea how this will look. You might have to tweak this 16-value a bit.

That's the best I could do without a full rewrite of the code.

```
void SingleDrift() {
  int mini = 5;
  int maxi = 255;
  FastLED.setBrightness(maxi);
  for (int i = 0; i < NUM_LEDS; i++)
  {
    if (leds[i].r > 64) leds[i].r = leds[i].r - 8;
    if (leds[i].g > 64) leds[i].g = leds[i].g - 8;
    if (leds[i].b > 64) leds[i].b = leds[i].b - 8;

    if ( (leds[i].r + leds[i].g + leds[i].b) > 16) // prevent fading to black
    {
      int rnd = random(10);
      if (rnd == 1 && leds[i].r >= 2) leds[i].r = leds[i].r - 1;
      if (rnd == 2 && leds[i].g >= 2) leds[i].g = leds[i].g - 1;
      if (rnd == 3 && leds[i].b >= 2) leds[i].b = leds[i].b - 1;
      if (rnd == 4) leds[i].fadeToBlackBy(2);
      //if (rnd == 5) leds[i].g++;
      //if (rnd == 6 && leds[i].g < 240) leds[i].g = leds[i].g + 1;
      //if (rnd == 7 && leds[i].b < 240) leds[i].b = leds[i].b + 1;
      //if (leds[i].g < 2) leds[i].g = 2; // I think this line kept the leds green
    }
  }
  ...

```
> 0 votes

# Answer
That code is a bit of a mess. It has some code that will never execute, as well as very confusing structure.

If it were me I would throw away that code and start over with code that does some other animation. You won't break anything, so play.

As to the code you posted:

It looks to me like the first for loop that cycles through all the LEDs is set to first fade all the LEDs down towards 0 brightness by 8 while their value is \> 64.

After the global fade, it then uses a random number 0-9 to decide what to do next for each LED.

1. If the random value is 1, 2, or 3, it reduces the red, green, or blue channels by 1.
2. If the random value is 4, it drives the current LED to black.
3. If the random value is 5, it increases the green channel of the current LED by 1. finally, it sets the green channel of the current LED back to 2 if it drops below 2. **That means that every LED will end up with flicker with a dim green color unless the next section changes that LED's color to something different**.

I added "\**this" comments to the lines that drive the LEDs towards green.

```
  for (int i = 0; i < NUM_LEDS; i++)
  {
    if (leds[i].r > 64) leds[i].r = leds[i].r - 8;
    if (leds[i].g > 64) leds[i].g = leds[i].g - 8;
    if (leds[i].b > 64) leds[i].b = leds[i].b - 8;

    int rnd = random(10);
    if (rnd == 1 && leds[i].r >= 2) leds[i].r = leds[i].r - 1;
    if (rnd == 2 && leds[i].g >= 2) leds[i].g = leds[i].g - 1;
    if (rnd == 3 && leds[i].b >= 2) leds[i].b = leds[i].b - 1;
    if (rnd == 4) leds[i].fadeToBlackBy(2);
    if (rnd == 5) leds[i].g++;  //**This will tend to make this LED flicker green.
    //if (rnd == 6 && leds[i].g < 240) leds[i].g = leds[i].g + 1;
    //if (rnd == 7 && leds[i].b < 240) leds[i].b = leds[i].b + 1;
    if (leds[i].g < 2) leds[i].g = 2; //**This will make each LED stop at dim green.
  }

```

If you want the LEDs to end up at some color other than green, you might want to change those last lines of the first for loop You could change that first section to something like this:

```
  for (int i = 0; i < NUM_LEDS; i++)
  {
    if (leds[i].r > 64) leds[i].r = leds[i].r - 8;
    if (leds[i].g > 64) leds[i].g = leds[i].g - 8;
    if (leds[i].b > 64) leds[i].b = leds[i].b - 8;

    int rnd = random(11);
    if (rnd == 1 && leds[i].r >= 2) leds[i].r = leds[i].r - 1;
    if (rnd == 2 && leds[i].g >= 2) leds[i].g = leds[i].g - 1;
    if (rnd == 3 && leds[i].b >= 2) leds[i].b = leds[i].b - 1;
    if (rnd == 4) leds[i].fadeToBlackBy(2);

    if (rnd == 5) leds[i].g++;  //**This will tend to make this LED flicker green.
    if (rnd == 6) leds[i].r++;  //**This will tend to make this LED flicker red.
    if (rnd == 7) leds[i].b++;  //**This will tend to make this LED flicker blue.

    if (rnd == 8) && (leds[i].g < 2) leds[i].g = 2; //**This will make the LED go dim green
    if (rnd == 9) && (leds[i].r < 2) leds[i].r = 2; //**This will make the LED go dim red
    if (rnd == 10) && (leds[i].b < 2) leds[i].b = 2; //**This will make the LED go dim blue
  }

```

Then it picks one random LED, and 20% of the time, does more random stuff to the color of that LED if it is dim enough. It uses a random value from 0-19 to decide what to do in the next switch statement. The first case is `case 99:`, which can never execute because the random value will never be greater than 19. For other values, it forces that LED to be a bright primary color, or maybe white, or maybe a color with random RGB values ranging from 128 to 255.
> 0 votes

---
Tags: arduino-uno
---


# Question
Title: Why I can't exit this while loop by reading from the Serial?
I'm trying to work with the FastLed libraries and i'm controlling a Led Stip via a WEMOS D1 MINI based on the ESP8266, what I'm trying to achieve is to jump from fastled animation to another one..those animations are inside a While loop as shown in the code, so , i thought to just read again from the serial in order to change an integer to exit those while loop, but for some reason is not working as expected. Anyone can help me to uderstand?

```
CRGB leds[NUM_LEDS];
int incomingByte = 0;
int exit = 0;
void setup() {
    Serial.begin(115200);
    delay( 1000 );
    FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
    FastLED.setBrightness(  BRIGHTNESS );
}

void loop()
{
    while (Serial.available()>0)
    {
      Serial.write("Serial.available");
       incomingByte = Serial.read();

       switch (incomingByte)
        {
          case '1':
            GreenYellow();
            break;

          case '2':
            Sparkle();
            break;
        }
    }
}

void Sparkle() {
    while(exit = 0){
        int Pixel = random(NUM_LEDS);
        setPixel(Pixel,random(255),random(255),random(255));
        FastLED.show();
        delay(50);
        setPixel(Pixel,0,0,0);
        if(Serial.available()>0){
            incomingByte = Serial.read();
            if(incomingByte != '2'){
                exit = 1;
            }
        }
    }
  }
}
void GreenYellow()
{
  for(int x =0; x< NUM_LEDS/2; x++){
    leds[x]= CRGB::Green;
  }

  for(int x =NUM_LEDS/2; x< NUM_LEDS; x++){
    leds[x]= CRGB::Yellow;
  }
  FastLED.show();
}

void setPixel(int Pixel, byte red, byte green, byte blue)
{
   leds[Pixel].r = red;
   leds[Pixel].g = green;
   leds[Pixel].b = blue;
   FastLED.show();
}
void setAll(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  FastLED.show();
}

```

**Bonus question:** I read that there is no thread programming on the ESP2866 via the Arduino IDE, am I right?

# Answer
The problem is that you check inside the two functions `Sparkle` and `GreenYellow` for another serial byte. Then when it's unequal, you move back to the `while` loop where you wait for the next serial byte, but I think you need to use the same one to decide to go to the correct function instead of waiting for a next serial byte.

Probably the easiest is to not read serial in the `while` loop but check the `incomingByte` global variable (containing the last read byte, and e.g. 1 initially), and ONLY in the two functions set that global variable. Then, when returning to the `while` loop, you check that global variable to jump to the correct function.

So you make a `setup` function that sets the global variable to 1 (or you do it in the initialization itself):

```
int incomingByte = 1; // Start with GreenYellow

```

Then, in the `loop` function, you use:

```
void loop()
{
       switch (incomingByte)
        {
          case '1':
            GreenYellow();
            break;

          case '2':
            Sparkle();
            break;
        }
}

```

If you don't want to start in either one, then use 3 values (0, 1, 2), and ONLY in the `loop` function read the Serial byte, but don't read it in the functions. This way it's a bit more cleaner as it separates the LED functionality with the Serial functionality.

The result (using the last method), results in the following code (compiles, not checked).

Comments:

* Used an enumeration for the mode
* Split functionality of serial data, processing the mode and RGB routines
* I added some initialization lines (i.e. constants) to make it compile.

```
#include <FastLED.h>

#define NUM_LEDS 60 // number of led present in your strip
#define LED_PIN 6
#define BRIGHTNESS 100

enum EMode
{
  ModeNone,
  ModeSparkle,
  ModeGreenYellow
};

CRGB leds[NUM_LEDS];
EMode mode;

void ParseSerialData();
void ProcessMode();
void GreenYellow();
void Sparkle();
void setPixel(int Pixel, byte red, byte green, byte blue);

void setup()
{
    Serial.begin(115200);
    delay( 1000 );
    FastLED.addLeds<WS2811, LED_PIN, EOrder::RGB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
    FastLED.setBrightness(  BRIGHTNESS );
    mode = EMode::ModeNone;
}

void loop()
{
  ParseSerialData();
  ProcessMode();
}

void ParseSerialData()
{
  while (Serial.available() > 0)
  {
    Serial.write("Serial.available");
    char incomingByte = Serial.read();

    switch (incomingByte)
    {
    case '1':
      mode = EMode::ModeGreenYellow;
      break;

    case '2':
      mode = EMode::ModeSparkle;
      break;

    default:
      // Ignore
      break;
    }
  }
}

void ProcessMode()
{
  switch (mode)
  {
  case EMode::ModeNone:
    // Do nothing
    break;

  case EMode::ModeGreenYellow:
    GreenYellow();
    break;

  case EMode::ModeSparkle:
    Sparkle();
    break;

  default:
    // Ignore
    break;
  }
}

void Sparkle()
{
    int Pixel = random(NUM_LEDS);
    setPixel(Pixel,random(255),random(255),random(255));
    FastLED.show();
    delay(50);
    setPixel(Pixel,0,0,0);
}

void GreenYellow()
{
  for(int x =0; x< NUM_LEDS/2; x++)
  {
    leds[x]= CRGB::Green;
  }

  for(int x =NUM_LEDS/2; x< NUM_LEDS; x++)
  {
    leds[x]= CRGB::Yellow;
  }
  FastLED.show();
}

void setPixel(int Pixel, byte red, byte green, byte blue)
{
   leds[Pixel].r = red;
   leds[Pixel].g = green;
   leds[Pixel].b = blue;
   FastLED.show();
}

void setAll(byte red, byte green, byte blue)
{
  for(int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  FastLED.show();
}

```
> 1 votes

---
Tags: esp8266, threads
---


# Question
Title: Speed data logging using arduino and GPS module
I am using a Quectel L80-R GPS Module coupled with an Arduino UNO to read and log my car's coordinates and speed. I am currently using TinyGPS++ library which works okay. It does spell out coordinates and speed but with some inaccuracies and delays. After some literature review I realized that NeoGPS library might be a better option. I found a thread over stackexchange where a code block is provided written by slash-dev who most possibly is the writer of NeoGPS library. However, when I am trying to compile the code, I get the following error `'class gps_fix' has no member named 'lat'` .I can not get rid of the issue even tough I've tried a whole bunch of workarounds.

# Answer
According to the NeoGPS documentation for the gps\_fix class, it looks like `.lat` and `.lon` are no longer part of the `gps_fix` class.

It looks like instead you will have to use `.latitudeL` and `.longitudeL` for high precision (Long Integer scaled by 10,000,000) GPS coordinates.

The solution would be to replace `fix.lat` in your code with `fix.latitudeL` and `fix.lon` with `fix.longitudeL`.
> 1 votes

---
Tags: arduino-uno, gps, speed
---


# Question
Title: Why is it I need transistors and resistors to turn a DC motor with an Arduino but I can connect it directly to a battery?
As the question says: I'm building a circuit to run a DC motor whenever motion is detected by a motion sensor. Now as this image suggests:

I need a diode + resistor + transistor to get this thing to turn with an Arduino, but I can do the same with a battery and connecting each of the terminals to the + and - of the battery. I understand this might be for speed control? Or turning the motor different ways?

But if I just need it to spin at 100%, would all this be needed?

I tried hooking up the motor directly with a resistor to the 5 V + GND of the board while it was on, but no joy. I am (obviously) doing something wrong but I want to use this problem as a way to learn circuits better.

# Answer
> 4 votes
If you want the motor to rotate continuously, without using PWM, and without switching the motor on and off from the Arduino, you can connect the motor straight to 5 V and ground. If you then add a large resistor like you tried, not enough current will pass through the motor to rotate it; in the image the resistor is there to limit the current into the transistor, not to limit the current into the motor.

You can't connect a motor directly to an IO pin because an IO pin can only deliver about 20 mA, which isn't enough for a motor. So, if you want to control a motor from an IO pin, you need a transistor as a switch and you operate that transistor from the IO pin. The transistor does the heavy lifting and switches the larger current the motor needs. The resistor is there to limit the current into the transistor.

Note that it is generally better to wire a motor directly to a 5 V power source and not to the 5 V pin on the Arduino, as the current you can get from that pin is limited; it will do for small motors, though, if they don't pull more than, let's be safe, about 300 mA. In other words, it is preferred not to use the Arduino 5 V pin as a power source, but to use a 5 V power source directly.

Also note that you always need the diode across the motor, however you wire it. It keeps inductive spikes away from the rest of your circuit.

---
Tags: arduino-uno, motor, transistor, resistor
---


# Question
Title: Search for a certain combination of strings in serial and read the following characters until another set character stops the search
I have the following serial message that I'm receiving from an ESP32 running GRBL:

```
<Idle|MPos:158.500,0.000,0.000|FS:0,0|Pn:H|Ov:100,100,100|SD:0.21,/instruction.nc>

```

I want to check the value after `SD:` which in this case would be `0.21`. It is a value that represents the percentage of a file being read, so values between 100.00 and 0.00 are being sent.

My guess is to look for the `SD:` in the string and then read all characters until the `,` but I can't really find a way to realize that.

I found the `startsWith()` and the `substring()`function that are able to look for a set of characters in a string, but it seems like they can only check a set amount of characters which in this case doesn't work as `0.00` is 4 characters and `100.00` is 6 characters.

Any help is much appreciated!!

# Answer
> 1 votes
Firstly you should really be working with a C string (`char *`) instead of a `String` object, otherwise you will be massively fragmenting your heap with the string manipulations to come.

Once you have your data in a C string (char array) you can use `strtok_r` to split the string on the `|` character, then for each substring further split it on the `:`. You need the `_r` variant of `strtok` to make it "re-entrant" so you can have two tokenizations at once nested.

For example (untested):

```
char *data = "<Idle|MPos:158.500,0.000,0.000|FS:0,0|Pn:H|Ov:100,100,100|SD:0.21,/instruction.nc>";
char *pair; // Pointer to a K/V pair
char *pairptr = data; // Pointer for outer strtok

// Split the string on the first |
pair = strtok_r(data, "|", &pairptr);

// While we have a K/V pair
while (pair) {
    char *kvptr = pair;
    // Split the substring into two parts on the colon
    char *key = strtok_r(pair, ":", &kvptr);
    char *val = strtok_r(NULL, ":", &kvptr);
    if (val) { // If we split the data correctly:
        if (strcmp(key, "SD") == 0) { // If the key is "SD" then
            Serial.print("SD data: ");
            Serial.println(val);
        }
    }
    // Get the next string portion
    pair = strtok_r(NULL, "|", &pairptr);
}

```

Once you have your `val` you can further split that down on commas in the same way as it's been split on the colon.

---
Tags: serial
---


# Question
Title: Are these GND connected resistors on the Arduino Due redundant?
Does anyone know why these 4 resistors are there (attachment)? It seems like they are useless since connected in a loop to GND. Full schematics here: https://store.arduino.cc/arduino-due

# Answer
> 3 votes
Yes, they are redundant. They are elements of resistor arrays (multiple resistors in one package) that aren't used. They have just connected all unused pins of those packages to ground.

If you want to know why they would have unused elements, it's all to do with optimizing the manufacturing process. If you have, say some 100k arrays elsewhere in your design and you want to have maybe one or two other 100k resistors elsewhere, rather than adding another component of a discrete 100k resistor it's cheaper to use a 100k array and not use some of the elements. One of the factors in the cost of pick-and-place operations is the number of different components. By keeping the number of component types to a minimum they keep the manufacture costs to a minimum.

---
Tags: arduino-due, resistor, pcb-design
---


# Question
Title: Sending variable length sequence via serial from PC to Mega
I am trying to send a sequence of commands from a PC to a Mega. The Mega in turn controls 2 signal generators (AD9833's).

The sequences can vary in length but always have the same format:

1. A start byte of 255
2. The length of the sequence
3. Elements of the sequence: Channel 0: MSB, LSB & waveform, Channel 1: MSB, LSB & waveform

The PC side code:

```
import serial
import struct

usbport    = 'COM3'
ser        = serial.Serial(usbport, 9600, timeout=1)

def sendSequence(seq):

    ''' Send a sequence of frequencies along with waveform '''

    # Start byte & sequence length
    ser.write(struct.pack('>B', 255))
    ser.write(struct.pack('>B', len(seq)))

    for s in seq:

        print(s)
        MSB, LSB = (s[0] & 0xFFFF).to_bytes(2, 'big')     # Split frequency to send
        ser.write(struct.pack('>B', MSB))
        ser.write(struct.pack('>B', LSB))
        ser.write(struct.pack('>B', s[1]))                # Waveform

        combined = ((MSB & 0xFF) << 8) | (LSB & 0xFF)
        print(combined)

sendSequence([[1000, 0], [1000, 0], [2000, 0], [1000, 0], [2000, 0], [2000, 0]])
ser.close()

```

On the Arduino side:

```
#include <SPI.h>

// Set up Serial data variables
byte freq_MSB;
byte freq_LSB;
int startbyte;
unsigned long freq_seq_ch_0[16];
int wave_seq_ch_0[16];
unsigned long freq_seq_ch_1[16];
int wave_seq_ch_1[16];
int wave_select = 0;
int seq_length;
long f_2;
long f_1;

const int SINE     = 0x2000;                // Define AD9833's waveform register value.
const int SQUARE   = 0x2028;                // When we update the frequency, we need to
const int TRIANGLE = 0x2002;                // define the waveform when we end writing.
int wave           = SINE;

const float refFreq = 25000000.0;           // On-board crystal reference frequency

const int FSYNCA = 53;                       // Standard SPI pins for the AD9833 waveform generator.
const int FSYNCB = 49;
const int CLK    = 52;

unsigned long pause     = 5000;
unsigned long freq      = 1000;              // Set initial frequency.
int i;

void setup() {

  // Set slave ocntrol pins
  pinMode(FSYNCA, OUTPUT);
  pinMode(FSYNCB, OUTPUT);
  digitalWrite(FSYNCA, HIGH);
  digitalWrite(FSYNCB, HIGH);

  // Set up SPI
  SPI.begin();
  SPI.setDataMode(SPI_MODE2);
  delay(50);

  // Set up AD9833s
  AD9833reset();                                   // Reset AD9833 module after power-up.
  delay(50);
  AD9833setFrequency(freq, SINE, FSYNCA);          // Set the frequency and Sine Wave output
  AD9833setFrequency(freq, SINE, FSYNCB);

  // Open the serial connection, 9600 baud
  Serial.begin(9600);
}

void loop() {

   // Wait for serial input
  if (Serial.available()) {

    startbyte = Serial.read();              // Read the first byte
    if (startbyte == 255) {
      seq_length = Serial.read();

      for (i = 0; i < seq_length; i++) {

        // Channel 0
        freq_MSB = Serial.read();
        freq_LSB = Serial.read();
        f_2 = (long)freq_MSB << 8;
        f_1 = (long)freq_LSB;
        freq_seq_ch_0[i] = f_2 | f_1;
        wave_select = Serial.read();
        switch (wave_select) {
          case 0:
            wave_seq_ch_0[i] = SINE;
            break;
          case 1:
            wave_seq_ch_0[i] = TRIANGLE;
            break;
          case 2:
            wave_seq_ch_0[i] = SQUARE;
            break;
          }

        // Channel 1
        freq_MSB = Serial.read();
        freq_LSB = Serial.read();
        f_2 = (long)freq_MSB << 8;
        f_1 = (long)freq_LSB;
        freq_seq_ch_1[i] = f_2 | f_1;
        wave_select = Serial.read();
        switch (wave_select) {
          case 0:
            wave_seq_ch_1[i] = SINE;
            break;
          case 1:
            wave_seq_ch_1[i] = TRIANGLE;
            break;
          case 2:
            wave_seq_ch_1[i] = SQUARE;
            break;
          }
      }

      // Send sequence to signal generators
      for (i = 0; i < seq_length; i++) {
        AD9833setFrequency(freq_seq_ch_0[i], wave_seq_ch_0[i], FSYNCA);
        AD9833setFrequency(freq_seq_ch_1[i], wave_seq_ch_1[i], FSYNCB);
        delay(3000);
      }

    }

  }
}

// AD9833 documentation advises a 'Reset' on first applying power.
void AD9833reset() {
  WriteRegister(0x100, FSYNCA);   // Write '1' to AD9833 Control register bit D8.
  delay(10);
  WriteRegister(0x100, FSYNCB);
  delay(10);
}

// Set the frequency and waveform registers in the AD9833.
void AD9833setFrequency(long frequency, int Waveform, int channel) {

  long FreqWord = (frequency * pow(2, 28)) / refFreq;

  int MSB = (int)((FreqWord & 0xFFFC000) >> 14);    //Only lower 14 bits are used for data
  int LSB = (int)(FreqWord & 0x3FFF);

  //Set control bits 15 ande 14 to 0 and 1, respectively, for frequency register 0
  LSB |= 0x4000;
  MSB |= 0x4000;

  WriteRegister(0x2100, channel);
  WriteRegister(LSB, channel);                  // Write lower 16 bits to AD9833 registers
  WriteRegister(MSB, channel);                  // Write upper 16 bits to AD9833 registers.
  WriteRegister(0xC000, channel);               // Phase register
  WriteRegister(Waveform, channel);             // Exit & Reset to SINE, SQUARE or TRIANGLE

}

void WriteRegister(int dat, int channel) {

  // Display and AD9833 use different SPI MODES so it has to be set for the AD9833 here.
  //SPI.setDataMode(SPI_MODE2);

  digitalWrite(channel, LOW);           // Set FSYNC low before writing to AD9833 registers
  delayMicroseconds(10);              // Give AD9833 time to get ready to receive data.

  SPI.transfer(highByte(dat));        // Each AD9833 register is 32 bits wide and each 16
  SPI.transfer(lowByte(dat));         // bits has to be transferred as 2 x 8-bit bytes.

  digitalWrite(channel, HIGH);          //Write done. Set FSYNC high
}

```

My problem is that this does NOTHING. No matter what sequence I send the output of the signal generators never deviates from the set up defaults.

The generators do work & I have managed to control them via serial before but in that case I knew exactly how much information would be in the serial buffer before I read it in but in this case the sequence length isn't known a priori.

Is this a serial issue?

# Answer
The main issue here is, that you are reading data, that might not be received yet. This:

```
if (Serial.available()) {

```

will check if there is **any** data in the Serial buffer. As the code runs rather fast and communication over Serial at 9600 baud is relatively slow, this very well might be true, when not your complete message was received. So you might have received the start byte, but the rest of the data is still being transmitted. In that case `Serial.read()` will return `-1`.

With Serial (UART) the transmission happens with individual bytes, not in big chucks. You need to only read data, that is really received.

As you don't know the sequence length beforehand I would suggest 2 different ways:

1. You can wait for 2 bytes being in the Serial buffer (start byte and length) and then again wait, until enough further bytes are in the Serial buffer (as you now have the length of the sequence).
2. You can rebuild your code, so that it just places the data in an extra buffer, until you have received enough data (which you need to check via the received length byte). Then, when you have received the full message, you process it and then clear the buffer, waiting for a new message.
> 0 votes

---
Tags: serial, arduino-mega
---


# Question
Title: How to get arduino to always be connected as /dev/ttyUSB0 and with chmod 0777?
I've got Debian 10 as OS and for a Project, I need my arduino to always be connected as /dev/ttyUSB0, not any other ttyUSB-number, and I need it to be connected with the 0777 rights for a script to work.

I've read some things about udev, but nothing I tried yet worked.

I tried creating

/etc/udev/rules.d/51-my\_usb\_device

with the content

SUBSYSTEM=="tty", MODE="0777", KERNELS=="ttyUSB0"

but it does not work, even after reboot (like nothing changed). I must admit though that I do not really understand udev.

How to do this?

# Answer
Have you considered not trying to force ttyUSB0 but instead creating a symlink to whatever tty is assigned? Your software then just uses the symlink.

A problem with forcing a particular tty is what if you boot without the Arduino but another device is attached? You then need to convince the other device to skip ttyUSB0.

If you would consider a symlink then something like:

```
ACTION=="add", KERNEL=="ttyUSB*", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="arduino"

```

might get you started. Check the VID and PID using `lsusb` or similar. To set permissions as well you can use e.g. `MODE="0777"` as you already have.

There is an example at https://wiki.debian.org/udev that might give more background.
> 3 votes

---
Tags: usb, linux
---


# Question
Title: detecting signal coming from another motion sensor that triggers camera's shutter
I have a motion sensor (used for camera trapping) that sends a signal to the camera to trigger the shutter. I am trying to use Arduino to turn on lights for 10 seconds by getting the signal from the motion sensor. I know there are ways to use motion sensor that can be used with Arduino. However, I need to know how I can detect a signal coming from the sensor to feed it to Arduino. I have tried connecting the cable from the sensor to A0, wrote a simple code to print the value of A0 but the serial monitor of Arduino shows nothing.

# Answer
> 0 votes
Almost all camera shutter cables are simple switches. They are an open circuit until you want to press the shutter, and then the switch closes. There is no voltage out of the shutter release, and so nothing for an analog pin to detect.

Many cameras have a shutter half-press switch that activates the light meter/auto-focus, and then a second switch that closes the shutter.

For a simple RCA plug shutter release or mono 3.5 mm plug shutter release, it's probably just a simple single pole switch. Wire one wire from the shutter release to a digital pin, and the other wire to ground. Set the pin to INPUT\_PULLUP, and wait for it to go LOW. When it goes LOW the shutter is being pressed.

Be aware that a modulated IR shutter trap will be a little slow. It probably won't catch subjects like birds flying at high speed until the bird has moved past the point where the trap is pointed. For that you would want a laser beam and a fast phototransistor. Those can be fast enough and accurate enough to measure the speed of a bullet. (Although you need to read port registers directly in order to get fast enough response for that. `DigitalRead()` is too slow.)

# Answer
> 1 votes
Sorry I am typing this here coz I don't have enough rep to comment. Anywho, most of the motion sensors involve PIR tech, so the best way is to connect your PIR Signal pin from your sensor to any analog pin of your arduino and test the kind of signal you're getting when the environment is idle and when movement is detected, Keep in mind of the region that the sensor covers too (ROI). That will tell you some things,

* If the sensor works or not.
* If the sensor value is analog or digital
* If the sensor is active high or low
* Trial and error on the actual ROI

After all that you can write your code around it.

---
Tags: arduino-uno
---


title: 'scale' was not declared in this scope

text:
# Question
Title: 'scale' was not declared in this scope
I am currently doing a robotic arm project. I used load cell with HX711 amplifier to detect and monitor of the objects. If the objects is less than 3kg, then the servomotor in gripper can rotate and the gripper can hold the objects. But there is an error in my coding.

# Answer
You forgot 'at least' to declare the global variable:

```
HX711 scale;

```

See documentation: https://github.com/bogde/HX711/blob/master/src/HX711.h

See GitHub example: https://github.com/bogde/HX711/blob/master/examples/HX711\_basic\_example/HX711\_basic\_example.ino
> 4 votes

---
Tags: servo
---


# Question
Title: Nextion Display not getting updated data
I am using an Arduino Mega to display the readings of 4 pots on a Nextion Display as well as store them on an SD Card with a time stamp. I keep getting:

`recvRetCommandFinished err`

on the serial monitor and the display does not update with time.

I have attached my code below:

```
#include "Nextion.h"
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"

RTC_DS1307 rtc;
char daysOfTheWeek[7][12] = {"Sunday","Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

// Declare your Nextion objects - Example (page id = 0, component id = 1, component name = "b0")
NexText tDate = NexText(0, 1, "tDate");
NexText tPot1 = NexText(0, 6, "tPot1");
NexText tPot2 = NexText(0,7, "tPot2");
NexText tPot3 = NexText(0, 8, "tPot3");
NexText tPot4 = NexText(0, 9, "tPot4");

File myFile;

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

  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    //rtc.adjust(DateTime(2016, 11, 19, 19, 45, 0));   // <----------------------SET TIME AND DATE: YYYY,MM,DD,HH,MM,SS
  }

  delay(100);

  // You might need to change NexConfig.h file in your ITEADLIB_Arduino_Nextion folder
  // Set the baudrate which is for debug and communicate with Nextion screen
  nexInit();

  SPI.begin();

  int pot1 = 0;
  int pot2 = 0;
  int pot3 = 0;
  int pot4 = 0;

  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  Serial.print("Initializing SD card...");
  if (!SD.begin(53)) {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
}

void loop(void) {
  myFile = SD.open("testpot1.csv", FILE_WRITE);
  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to testpot1.txt...");

    while(1) {
      DateTime now = rtc.now();
      myFile = SD.open("testpot1.csv ", FILE_WRITE);
      int pot1 = analogRead(A0);
      int pot2 = analogRead(A1);
      int pot3 = analogRead(A2);
      int pot4 = analogRead(A3);
      myFile.print(now.hour());
      myFile.print(":");
      myFile.print(now.minute());
      myFile.print(",");

      myFile.println(pot1);
      myFile.println(",");
      tPot1.setText(pot1);

      myFile.println(pot2);
      myFile.println(",");
      tPot2.setText(pot2);

      myFile.println(pot3);
      myFile.println(",");
      tPot3.setText(pot3);

      myFile.println(pot4);
      myFile.println(",");
      tPot4.setText(pot4);

      Serial.print(pot1);
      Serial.print(",");
      Serial.print(pot2);
      Serial.print(",");
      Serial.print(pot3);
      Serial.print(",");
      Serial.print(pot4);
      Serial.print(",");

      delay(2000);
      myFile.close();
    }
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
}

```

How do I get the pot values on my display? Any help or tips would be helpful!

# Answer
I changed the text components to number components on the Nextion GUI Editor. That worked as I primarily wanted to show numerical readings from the pot.
> 0 votes

# Answer
`recvRetCommandFinished err` means something is wrong with the serial communication between the Arduino and the Nextion display; it is what `recvRetCommandFinished()` prints when there is an error.

Check if you are using the right pins (TX1 and RX1 for Serial1) for the serial connection to the display, the actual connections you made (RX1 to TX, TX1 to RX), the baud rate, and the cable.
> 2 votes

---
Tags: arduino-mega, sd-card, display, rtc
---


# Question
Title: Problem understanding how to program DS3231 RTC
I need to send a pulse to an Arduino at **every one hour**. I don't need day, month, year etc. I just want a pulse from DS3231 at every 1 hour **through the square wave pin**.

https://github.com/NorthernWidget/DS3231
**I have included this library** but I can't anyhow understand how to generate an pulse at each hour using this library. Is it possible?

My requirement is simple. I need a pulse at my Arduino interrupt pin at each hour.

```
#include <DS3231.h>
#include <Wire.h>

void setup()
{
  Wire.begin();
  EICRA |= 0b00000011;
  EIMSK |= 0b00000001;
  sei();
 // No clue on how to setup DS3231 for getting a pulse at each hour
}
ISR(INT0_vect)
{
  // This function will be executed in each hour
}
void loop(){}

```

# Answer
> 2 votes
DS3231 address is 104. Instead of using that large complicated header, send simple frame.

For 1 sec pulse the frame will be : S 208 A 14 A 0 P

N.B. Here address is 7 bit value 104. And a extra bit for R/W operation.

In the Arduino wire library, you don’t need to include the R/W bit. So,just write 104. For hourly Alam set the INT bit of control register and send simple frame like this. Don't make things complicated using the header.

# Answer
> 0 votes
See the documentation at:

DTC3231 Library Documentation

Where there is the section on alarm bits and setting alarms:

```
        // Alarm functions

        void getA1Time(byte& A1Day, byte& A1Hour, byte& A1Minute, byte& A1Second, byte& AlarmBits, bool& A1Dy, bool& A1h12, bool& A1PM);
/* Retrieves everything you could want to know about alarm
 * one.
 * A1Dy true makes the alarm go on A1Day = Day of Week,
 * A1Dy false makes the alarm go on A1Day = Date of month.
 *
 * byte AlarmBits sets the behavior of the alarms:
 *  Dy  A1M4    A1M3    A1M2    A1M1    Rate
 *  X   1       1       1       1       Once per second
 *  X   1       1       1       0       Alarm when seconds match
 *  X   1       1       0       0       Alarm when min, sec match
 *  X   1       0       0       0       Alarm when hour, min, sec match
 *  0   0       0       0       0       Alarm when date, h, m, s match
 *  1   0       0       0       0       Alarm when DoW, h, m, s match
 *
 *  Dy  A2M4    A2M3    A2M2    Rate
 *  X   1       1       1       Once per minute (at seconds = 00)
 *  X   1       1       0       Alarm when minutes match
 *  X   1       0       0       Alarm when hours and minutes match
 *  0   0       0       0       Alarm when date, hour, min match
 *  1   0       0       0       Alarm when DoW, hour, min match
 */
        void getA2Time(byte& A2Day, byte& A2Hour, byte& A2Minute, byte& AlarmBits, bool& A2Dy, bool& A2h12, bool& A2PM);
            // Same as getA1Time();, but A2 only goes on seconds == 00.
        void setA1Time(byte A1Day, byte A1Hour, byte A1Minute, byte A1Second, byte AlarmBits, bool A1Dy, bool A1h12, bool A1PM);
            // Set the details for Alarm 1
        void setA2Time(byte A2Day, byte A2Hour, byte A2Minute, byte AlarmBits, bool A2Dy, bool A2h12, bool A2PM);
            // Set the details for Alarm 2
        void turnOnAlarm(byte Alarm);
            // Enables alarm 1 or 2 and the external interrupt pin.
            // If Alarm != 1, it assumes Alarm == 2.
        void turnOffAlarm(byte Alarm);
            // Disables alarm 1 or 2 (default is 2 if Alarm != 1);
            // and leaves the interrupt pin alone.
        bool checkAlarmEnabled(byte Alarm);
            // Returns T/F to indicate whether the requested alarm is
            // enabled. Defaults to 2 if Alarm != 1.
        bool checkIfAlarm(byte Alarm);
            // Checks whether the indicated alarm (1 or 2, 2 default);
            // has been activated.

```

**UPDATE:**

Based on your comment:

> I checked that too. The example was too complicated.

You need to spend some time gaining a familiarity with some of the basic Arduino and AVR functions. To make this work you're going to not only need to understand how to talk to the RTC via I2C but also how to enable and respond to a pin interrupt in the AVR. You have the ISR function there but you have not done anything to enable any interrupt source.

---
Tags: arduino-nano, rtc, ds3231-alarms
---


title: Arduino stuck in PT_WAIT_UNTIL

text:
# Question
Title: Arduino stuck in PT_WAIT_UNTIL
I am using the Protothread Library from Adam Dunkels. It is supposed to wait 1 second and then continue. But instead it gets stuck there and everything after that line is not executed.

```
lastTimeBlink = millis();
PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > 1000);

```

Why does it get stuck there? The entire code is uploaded here: https://pastebin.com/jRsuvn54

(The comments are on german)

# Answer
By best attempt to provide something of an answer.

You have said:

> PT\_WAIT\_UNTIL(pt, millis() - lastTimeBlink \> 1000);

That is not literally represented in your code, so I take your question to refer to:

```
int dist2 = dist1.toInt();
...
PT_WAIT_UNTIL(pt, millis() - lastTimeBlink > (dist2 * 1710));

```

or a similar section.

When you execute this `PT_WAIT_UNTIL`, `dist2` contains whatever value you initialized it with in `int dist2 = dist1.toInt();` Assuming the condition isn't met, you are exiting `runCommand()` by way of `PT_WAIT_UNTIL`'s `return PT_WAITING;`

```
#define PT_WAIT_UNTIL(pt, condition) \
  do {                               \
    LC_SET((pt)->lc);                \
    if(!(condition)) {               \
      return PT_WAITING;             \
    }                                \
  } while(0)

```

The `LC_SET` here in `PT_WAIT_UNTIL` is being used to generate a label that can be jumped-to later:

```
#define LC_SET(s)                                \
   do {                                          \
     LC_CONCAT(LC_LABEL, __LINE__):              \
     (s) = &&LC_CONCAT(LC_LABEL, __LINE__);      \
   } while(0)

```

Later when you later call runCommand to resume the thread, you execute `LC_RESUME` by way of `PT_BEGIN(pt);`

```
#define PT_BEGIN(pt) { char PT_YIELD_FLAG = 1; LC_RESUME((pt)->lc)
...
#define LC_RESUME(s)        \
  do {                      \
    if(s != NULL) {         \
      goto *s;              \
    }                       \
  } while(0)

```

`goto *s` here is ultimately jumping to the label created by your use of `PT_WAIT_UNTIL`.

You are now back in `PT_WAIT_UNTIL` checking the condition with the line `if(!(condition))`. That is, you are checking `millis() - lastTimeBlink > (dist2 * 1710)` However, what you are *probably* (more on that below) doing here is reading junk off the stack. `dist2` **was** initialized on a *previous* execution of `runCommand` and its effective lifetime ended when you returned in `PT_WAIT_UNTIL` on that prior execution. On this new execution `dist2` is **un**initialized because you have jumped over its initialization. If you turn the warning level up in File/Preferences you should see something for this.

A number of things can happen at this point, most of them not good. I can't say what the compiler's optimizer will do to this code for certain, but not much would surprised me. It seems likely, just on familiarity with optimizing compilers and what your code looks like, that it is generating code to read `dist2`. That may sound like a given, but it isn't when you're doing something undefined. It's possible `dist2` has the value from a previous run where you're executing this function in a loop. But it could also have value that makes `dist2 * 1710` evaluate to a duration of up to nearly 50 days, causes `PT_WAIT_UNTIL` to return from runCommand for so long as you're testing.

Generally, if you're going to use these proto-threads you're going to have to be very careful in thinking about what's actually initialized and what just *looks* like it is. If you have a `PT_whatever` between a non-static local variable initialization or assignment and code where it's used, that's something to examine.
> 1 votes

---
Tags: arduino-uno, library, millis, threads
---


# Question
Title: How to stop the relay after it is getting on and let the sensor get the result
I want to provide a delay in the following iteration reading so that the sensor can read the condition after the pump starts.

```
void loop() {
  //-------------Fungsi Read sensor-----------
  // sensorAll();

  hasilec = (ppmcensor - inputec);
  ph = (phcensor - inputph);

  //  hasilec = random(-200, 0) / 100.0;
  //  ph = random(-200, 200) / 100.0;

  //  ph = -180/100.0;
  //  hasilec = -1.2;

  unsigned long now = millis();

  Serial.print("pH    ");
  Serial.print(ph);
  Serial.print("  ");
  Serial.print("EC ");
  Serial.print(hasilec);
  Serial.println("");
  Serial.print(ph); Serial.print(" ");
  Serial.print(hasilec); Serial.print(" ");
  Serial.println(" ");

  //  delay (500000);

  fuzzy->setInput(2, hasilec);
  fuzzy->setInput(1, ph);
  fuzzy->fuzzify();

  float pompa01 = fuzzy->defuzzify(1);//pHDOWN
  float pompa02 = fuzzy->defuzzify(2);//pHUP
  float pompa03 = fuzzy->defuzzify(3);//ABMIX

  Serial.println("Result= ");
  Serial.println("");
  Serial.print(" Pompa1 pHDOWN: ");
  Serial.println(pompa01);
  Serial.print(" pompa2 phUP  : ");
  Serial.println(pompa02);
  Serial.print(" pompa3 ABMIX : ");
  Serial.println(pompa03);
  Serial.println("");
  Serial.println("");
  Serial.println("");

  delay (2000);

  long int pompa1 = pompa01 * 1000;
  long int pompa2 = pompa02 * 1000;
  long int pompa3 = pompa03 * 1000;

  pump_periods[0] = pompa1; //PHdown
  pump_periods[1] = pompa2; //PHup
  pump_periods[2] = pompa3; //ABMIX

  for (int i = 0; i < jml_pump; i++) {
    if (now - pump_last_actuations[i] >= pump_periods[i]) {
      pump_states[i] = (pump_states[i] == LOW) ? HIGH : LOW;
      digitalWrite(pump_pins[i], pump_states[i]);
      pump_last_actuations[i] = now;
    }
  }
}

```

If I put the delay after millis iteration it causes the pump to only turn on based on the delay, not the timer millis. What should I do?

# Answer
> 0 votes
If all the pumps have to work for `pump_periods[i]` time on every loop, and you will have a long `delay()` anyway, you could replace the `for` loop with:

```
for (int i = 0; i < jml_pump; i++) { // For every pump:
  digitalWrite(pump_pins[i], 1);     // Start pump i
  delay(pump_periods[i]);            // Wait for pump_periods[i] ms
  digitalWrite(pump_pins[i], 0);     // Stop pump i
}
delay(120000);                       // Wait 2 minutes until mixed

```

This will block the loop, but you will have a long delay anyway. The pumps will work sequentially, and not at the same time.

Is that what you want?

---
Tags: arduino-mega, relay, loop
---


title: Switch loops with SPDT switch

text:
# Question
Title: Switch loops with SPDT switch
I have made a drone/car quadruped robot thing and I need help with the code. I have found two codes to use to control each aspect of it but I need help to connect them. I have made a radio controller with a Xbee 3 Pro that has a spdt (two position switch) and I want to use it to switch the modes. I want the car to be LOW and the drone to be HIGH (If it helps the switch is on pin digital pin 9 of a Arduino Nano). I am a beginner at the coding aspect of the project and I would appreciate all the help I can get.

https://www.youtube.com/watch?v=enT-O4NwCzc

# Answer
There is no need for a SPDT switch. A SPST works just as well.

If you have a SPDT switch with 3 positions (pole 1 closed, open, pole 2 closed) you can use it to activate one pin or the other, or neither.

Let's pretend your switch is an SPST. Ignore one of the poles (pole 2, say.)

Connect a digital pin to pole 1. connect the common (center) pin to ground.

Set your digital pin to `INPUT_PULLUP`. Now, when the pin is LOW, the switch is closed (mode A). When the pin is HIGH, the switch is open (mode B).
> 1 votes

---
Tags: xbee, switch, drone
---


title: smooth DC motor control with millis

text:
# Question
Title: smooth DC motor control with millis
So the task is to control 12v DC motor.

With first button, you can add up motor speed by certain speed step.

With second button, you can slow down motors speed by certain speed step.

With third button you cant speed up motor to its max, but problem is there that i must be done smoothly. For example i press third button and in motor starts to spin faster and faster till it reaches max speed. But now when i press this button motor jumps to it max, and i don't know why. There is no smoothness.

I cant use delay, must be done by millis

```
[code]
int speed = 0;
int motor = 5,
    fasterbutton = 7, slowerrbutton = 4, tillmaxbutton = 2;
unsigned long previousMillis = 0;
const long interval = 100;
const long smoothinterval = 5000;
boolean faster, slower, tillend;
int begginingspeed;
const int step = 3;
const int maxspeed = 255;

void setup() {
  pinMode(2, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, OUTPUT);
  pinMode(7, INPUT_PULLUP);
  Serial.begin(9600);
}
void loop() {
  tillend = digitalRead(2);
  slower = digitalRead(4);
  faster = digitalRead(7);

  //button Nr 7 start DC motor and festens up
  if (faster == !HIGH && begginingspeed < maxspeed) {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      begginingspeed += step;
      if (faster == !HIGH && speed < 1 ) {
        Serial.print('\n');
        Serial.print("MOTOR ON" );
      }
      analogWrite(motor, begginingspeed);
      Serial.print('\n');
      Serial.print("Speed = " );
      speed = begginingspeed * 100 / maxspeed;
      Serial.print(speed, DEC);
      previousMillis = currentMillis;
    }
  }

  //button Nr 4 slows down  DC motor
  else if (slower == !HIGH && begginingspeed > 0) {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      begginingspeed -= step;
      analogWrite(motor, begginingspeed);
      Serial.print('\n');
      Serial.print("Speed = " );
      speed = begginingspeed * 100 / maxspeed;
      Serial.print(speed, DEC);
      if (slower == !HIGH && speed < 1 ) {
        Serial.print('\n');
        Serial.print("MOTOR OFF" );
      }
      previousMillis = currentMillis;
    }
  }

  //button Nr 2 for smooth fastens up DC motor till max
  if (tillend == !HIGH && begginingspeed > 0) {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis <= interval) {
      for (begginingspeed = begginingspeed; begginingspeed <= 255; begginingspeed += step)
        analogWrite(motor, begginingspeed);
    }
    previousMillis = currentMillis;
  }

}
[/code]

```

# Answer
I suggest using a different logic in your program. I would first divide up the different parts of the project:

* A code part, which reads the 3 buttons and sets/increments/decrements a variable based on the button clicks, and
* a code part, which takes a variable as set point and ramps the PWM (`analogWrite()`) output up or down, until the set point is reached. (So the setpoint is the target speed/PWM value)

This division between "input code" and "output code" is rather common, since it often makes your code better structured and makes it possible to easily add new inputs for one single output.

---

Let us first look at the second part (ramping the PWM signal up and down). We need a variable, that holds the current PWM value, and one, that holds the current set point (for both we are starting with zero, thus the motor stands still here:

```
int current_speed = 0;
int speed_setpoint = 0;

```

We also need a timestamp variable for using `millis()` to regularly setting the PWM output according to the set point and the corresponding interval (here as a define). Additionally we also define the increment, with which the PWM value should be incremented on each sample:

```
unsigned long motor_timestamp;
#define MOTOR_SAMPLE_INTERVAL  100
#define MOTOR_SAMPLE_INCREMENT 3

```

We are doing all this in the global scope. Now in the loop function we first check for `millis()` and the timestamp (which gives us a regular sample interval for the motor speed) and then check, if the current speed is higher or lower than the setpoint and change the `current_speed` accordingly. At the end we write the value of `current_speed` to the output:

```
if(millis() - motor_timestamp > MOTOR_SAMPLE_INTERVAL){
    if(current_speed < speed_setpoint){
        current_speed += MOTOR_SAMPLE_INCREMENT;
    } else if(current_speed > speed_setpoint){
        current_speed -= MOTOR_SAMPLE_INCREMENT;
    }
    analogWrite(motor, current_speed);
    motor_timestamp += MOTOR_SAMPLE_INTERVAL;
 }

```

So now we `current_speed` of the motor will follow the `speed_setpoint`, but will only increment or decrement with the speed you set with the `MOTOR_SAMPLE_INTERVAL` and the `MOTOR_SAMPLE_INCREMENT`. The new target speed is simply set by giving the variable `speed_setpoint` a new value. The above code will take care of reaching it.

---

Now lets look at the first part (reading the buttons for changing a variable). At your current code, you need to hold the button down for the value to change. From your text is guess, that you want a click behavior (1 step in speed for 1 button click, meaning button press and release). For that I suggest using the Bounce2 library, which will handle the buttons - especially the debouncing - for you:

```
#include <Bounce2.h>
Bounce bounce = Bounce();

void setup(){
    bounce.attach( BOUNCE_PIN, INPUT_PULLUP );
    // DEBOUNCE INTERVAL IN MILLISECONDS
    bounce.interval(5); // interval in ms
}

void loop(){
    bounce.update();
    if(bounce.fell()){
        // Handle the button click here
    }
}

```

Inside the `if(bounce.fell())` statement, you would handle the action for the button click, in this case: updating the `speed_setpoint` variable. Define an increment value for the buttons and do the increment/decrement in the if statements. In global scope:

```
#define BUTTON_SPEED_INCREMENT 4

```

In the `loop()` function:

```
if(slower_bounce.fell()){
    speed_setpoint -= BUTTON_SPEED_INCREMENT;
}
if(faster_bounce.fell()){
    speed_setpoint += BUTTON_SPEED_INCREMENT;
}
if(tillend_bounce.fell()){
    speed_setpoint = maxspeed;
}

```

---

Now you need to put all this together. I will leave that to you. You can then tune the behavior to your liking by changing the defines.

---

Note the following points:

* The motor will accelerate linear. That should be fitting for you.
* The code will restart the PWM wave at every `MOTOR_SAMPLE_INTERVAL`. That is ok for a motor when the interval is significantly higher than the PWM interval. When you choose the interval too low (like single digit milliseconds), you need to put the `analogWrite()` call into the if statements with the increment of `speed_setpoint`. That will take 1 more statement, but will solve the problem.
* If you choose the `MOTOR_SAMPLE_INTERVAL` too low, the speed change will get stuttery
> 0 votes

# Answer
If not delay then you'll probably have to use something like an H-Bridge. L298N is a good place to start. You can use PWM to control its speed and its gradual too.

https://www.browncountylibrary.org/wp-content/uploads/2018/03/arduino\_dc\_motors.pdf

Here's the relevant documentation
> 0 votes

---
Tags: motor, millis
---


title: Relay with NodeMCU is not working

text:
# Question
Title: Relay with NodeMCU is not working
I'm using a Relay Channel and NodeMCU(8266-WIFI). When i trigger the connection, LED Turns ON in Node MCU But the Relay connection is not working. I'm not sure what is the issue, Please help to fix it..

My Pin connection as follows.

> 1. NodeMCU (VIN) -\> Relay (VCC)
> 2. NodeMCU (G) -\> Relay (G)
> 3. NodeMCU (D1) -\> Relay (IN4)

My code as follows,

```
#include <ArduinoJson.h>
#include <ESP8266WiFi.h>
#include <FirebaseCloudMessaging.h>
#include <Firebase.h>
#include <FirebaseHttpClient.h>
#include <FirebaseArduino.h>
#include <FirebaseError.h>
#include <FirebaseObject.h>

// Set these to run example.
#define FIREBASE_HOST "xxx-xxxx.firebaseio.com"
#define FIREBASE_AUTH "xxxxxx"
#define WIFI_SSID "xxxx"
#define WIFI_PASSWORD "xxxxx"

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

  // connect to wifi.
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("connecting");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println();
  Serial.print("connected: ");
  Serial.println(WiFi.localIP());

  pinMode(D1, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);

  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
  Firebase.set("LED_STATUS",0);
}

int n = 0;

void loop() {
  // Get value
  n=Firebase.getInt("LED_STATUS");

  if (n==1) {
     digitalWrite(D1, LOW);
     digitalWrite(LED_BUILTIN, LOW);
     Serial.print("LED is ON ");
     Serial.println(Firebase.getInt("LED_STATUS"));
     delay(1000);
  }
 else{
   //LED_BUILTIN
   digitalWrite(D1, HIGH);
   digitalWrite(LED_BUILTIN, HIGH);
   Serial.print("LED is OFF ");
   Serial.println(Firebase.getInt("LED_STATUS"));
   delay(1000);
 }

}

```

# Answer
> 1 votes
I found that the 3V isn't enough to power the relay. https://www.instructables.com/Getting-Started-With-ESP8266LiLon-NodeMCU-V3Flashi/ shows the board supplies USB power (pin VU).

You can remove the jumper that connects signal voltage to relay power and connect the relay board to the USB power.

After that change I could turn the relays on and off, but I could not reliably power 4 relays, 2 relays as shown below seems fine.

---
Tags: nodemcu, relay, iot, home-automation
---


title: ATTiny85 I2C LCD

text:
# Question
Title: ATTiny85 I2C LCD
My setup is as follows:

* Arduino IDE 1.6.11
* Arduino Pro Mini as ISP
* ATTiny85 1602A LCD with I2C board

The libraries I use are:

The Sketch I use to test with:

```
#include <TinyWireM.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x3F,16,2);  // set address & 16 chars / 2 lines

void setup()
{

  TinyWireM.begin();                    // initialize I2C lib
  lcd.init();                           // initialize the lcd
  lcd.backlight();
  lcd.clear();  // Print a message to the LCD.
}

void loop()
{
  lcd.setCursor(0, 0);
  lcd.print("Hello World on Attiny85");
  delay(2000);
}

```

The address is 0x3F, I found this using the scanner sketch, I also tested the LCD using the Arduino Pro Mini directly, it works fine.

The result of this setup is a single line of black blocks. My guess is that the initialization failed in some way. I have tried some things to make it work:

* Pull-ups on SDA and SCL
* Isolated from Arduino with regulated power supply
* Setting contract with the pot meter on the back
* reinstall of PC
* reinstall of Arduino IDE
* 1MHz, 8Mhz, TinyCore default and High-Low Tech
* Replaced FTDI
* Replaced Tiny85
* Replaced LCD
* Replaced Arduino Pro Mini

Some pictures:

\[EDIT\]

**Final sketch:**

```
#include <TinyWireM.h>                  // I2C Master lib for ATTinys which use USI
// #include <LiquidCrystal_I2C.h>
#include "LiquidCrystal_attiny.h"
LiquidCrystal_I2C lcd(0x27,16,2);

void setup() {

  // Now set up the LCD
  //lcd.begin(16,2);               // initialize the lcd
  pinMode(4, OUTPUT);
  lcd.init();
  lcd.backlight();
  lcd.home ();                   // go home
  lcd.print("Weatherstation");
  lcd.setCursor ( 0, 1 ); // go to position
  lcd.print("BMP180");
  delay(2000);
}
void loop() {
  digitalWrite(4, HIGH);
  delay(100);
  digitalWrite(4, LOW);
  delay(100);
}

```

# Answer
> 4 votes
After hours of Googling, I found a blog post by Dimitris Platis where he describes using an ATTiny85 with I2C LCD. I emailed the guy and he replied with a link to his LCD I2C ATTiny library on GitHub. Using this library with the TinyWireM and the right core, it instantly worked.

My final setup is with a 4.7K resistor on SDA and SCL, I will add the final sketch in the original post under \[EDIT\]. This adventure took me two weeks so I hope it helps someone else some day.

LCD library used: https://github.com/platisd/ATtiny85-LCD-library
TinyWireM used: https://github.com/adafruit/TinyWireM
Core used: https://github.com/vprimachenko/ArduinoTiny

# Answer
> 0 votes
It doesn't look like you have an Arduino Pro Mini. I2C lines on a Pro Mini are on pins A4 for SDA and A5 for SCL and those 2 pins are placed at an odd location - check picture.

Hope I was helpful :)

# Answer
> 0 votes
I've spent an hour doing this problem and searched a lot. If you still didn't find the solution by doing this. Pls try to reduce the clock speed from `Internal 8 MHz` to `Internal 1MHz`. That way it works mine.

---
Tags: i2c, lcd, attiny
---