# Question
Title: Seeking to write a ton of information to an SD card as close to live as possible
So I've recently started a project where I am using an accelerometer, along with a SD card breakout board. I've been able to get information to write properly to the SD card with no issues whatsoever. However, my speed is a bit lower than I would like, at about only 40Hz or so, where my accelerometer can log data at 260Hz (MPU-6050). Each reading contains an X, Y, Z, and timestamp value since recording started. Each reading is output into a .txt file for later separation via comma-separated-value sorting in Excel(I wish) or GNUplot, which handles the massive sample size much better.

I've referenced https://forum.arduino.cc/t/how-to-write-data-with-high-sampling-rates-to-a-sd-card/281496/9 to try and figure this out, but I couldn't get much out of it. I don't understand arrays very well beyond the fact they are just tables like in excel, and can be set up in 1, 2, 3, or more dimensions.

I've read around a bit and it seems my problem is that I'm closing and opening the file each and every write cycle. However, I don't know how to get out of doing this as the program seems to not run properly if I don't close out the file or if I use flush. My general idea of how this could flow without opening/close cycles every single time would be:

> 1. Create arrays for each variable (X, Y, Z, elapsedTime)
> 2. Take all my recordings for a given time, maybe five-hundred readings or so which would come out to about 12 seconds, or whatever possible value I can squeeze out of my Atmega328P and maintain program stability, and shove them into their respective arrays. Ideally the longer the better, but I understand I have memory constraints.
> 3. In one write-cycle, I write all the values into CSV form, or even multiple print cycles cycling through each array cell continuously until all the values are input with the proper format.
> 4. Clear the arrays of all the info they held, and return to step 2.

Really appreciate any help you guys can offer. Thank you!

```
//

#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
int recordStatus = false;                                                   //Default recordStatus is zero.
int recordingLed = 3;
const int chipSelect = 10;
Adafruit_MPU6050 mpu;

void setup(void) {
  pinMode(2, INPUT_PULLUP);
  pinMode(3, OUTPUT);
  Serial.begin(500000);
  while (!Serial)
    delay(10); // will pause Zero, Leonardo, etc until serial console opens

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

  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");
}
                                                                              //SD CARD WRITE CODE END

  Serial.println("Adafruit MPU6050 test!");                                   //MPU6050 ACCELEROMETER INITIALIZATION CODE BEGIN
  // Try to initialize!
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
  }
  Serial.println("MPU6050 Found!");

  mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
  switch (mpu.getAccelerometerRange()) {
  case MPU6050_RANGE_2_G:
    break;
  case MPU6050_RANGE_4_G:
    break;
  case MPU6050_RANGE_8_G:
    break;
  case MPU6050_RANGE_16_G:
    break;
  }
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);
  switch (mpu.getGyroRange()) {
  case MPU6050_RANGE_250_DEG:
    break;
  case MPU6050_RANGE_500_DEG:
    break;
  case MPU6050_RANGE_1000_DEG:
    break;
  case MPU6050_RANGE_2000_DEG:
    break;
  }

  mpu.setFilterBandwidth(MPU6050_BAND_260_HZ);
  Serial.print("Filter bandwidth set to: ");
  switch (mpu.getFilterBandwidth()) {
  case MPU6050_BAND_260_HZ:
    Serial.println("260 Hz");
    break;
  case MPU6050_BAND_184_HZ:
    Serial.println("184 Hz");
    break;
  case MPU6050_BAND_94_HZ:
    Serial.println("94 Hz");
    break;
  case MPU6050_BAND_44_HZ:
    Serial.println("44 Hz");
    break;
  case MPU6050_BAND_21_HZ:
    Serial.println("21 Hz");
    break;
  case MPU6050_BAND_10_HZ:
    Serial.println("10 Hz");
    break;
  case MPU6050_BAND_5_HZ:
    Serial.println("5 Hz");
    break;
  }
                                                                                //MPU6050 ACCELEROMETER INITIALIZATION CODE END
}

unsigned long startMillis;
unsigned long currentMillis;
unsigned long elapsedTime;
int rawMillis;
void loop() {
  digitalWrite(recordingLed, LOW);
  int buttonRecord = digitalRead(2);                                                //Check button for GND input
  /* Get new sensor events with the readings */
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);

// make a string for assembling the data to log:                                    //SD CARD VALUES ASSIGN BEGIN
  int X = "";
  int Y = "";
  int Z = "";
  String timeofRecord = String(millis()/1000.0, 10);
  X = (a.acceleration.x/9.81);
  Y = (a.acceleration.y/9.81);
  Z = (a.acceleration.z/9.81);
  if(buttonRecord == false){                                                        //Toggle record status upon pin 2 going to GND
    delay(500);
    recordStatus = !recordStatus;                                                   //If button is pressed, make recordStatus switch from true to false.
    startMillis = millis();
  }

if(recordStatus == true){                                                           //While record is toggled, do below
    rawMillis = millis()-startMillis;
    String elapsedTime = String(rawMillis/1000.00, 3);
    File dataFile = SD.open("datalog.txt", FILE_WRITE);
      if (dataFile) {                                                               // if the file is available, write to it:
    digitalWrite(recordingLed, HIGH);
    dataFile.print(elapsedTime);
    dataFile.print(", ");
    dataFile.print(X);
    dataFile.print(", ");
    dataFile.print(Y);
    dataFile.print(", ");
    dataFile.print(Z);
    dataFile.println("");
    dataFile.close();
  }
}
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
    }
}

```

**UPDATE**

So I've been messing with this a while, and I believe I just about have it figured out. I have arrays set up for time, X, Y, and Z and they are populating values correctly. However, I can't seem to get into my SD card file. There is no issue when the setup initializes, it's like it skips the

> if (dataFile){

entirely. The modified code is below here. There's no shutdowns, and the program loops continuously so I don't *think* I'm running out of memory or having any power issues. The red LED on the SD card is flashing as though it's being written. Even if I remove the if(dataFile) check and force the commands contained in the if statement to execute, my txt file is still left empty. Previously I was writing to this just fine. Memory problem? I have less than 500 bytes of memory available. Possibly this is the cause? Or is it the for loop causing my trouble?

```
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
int recordStatus = false;                                                   //Default recordStatus is zero.
int recordingLed = 3;
const int chipSelect = 10;
Adafruit_MPU6050 mpu;

void setup(void) {
  pinMode(2, INPUT_PULLUP);
  pinMode(3, OUTPUT);
  Serial.begin(500000);
  while (!Serial)
    delay(10);
                                                                           //SD CARD WRITE CODE BEGIN
 {
  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");
}
                                                                              //SD CARD WRITE CODE END

  Serial.println("Adafruit MPU6050 test!");                                   //MPU6050 ACCELEROMETER INITIALIZATION CODE BEGIN
  // Try to initialize!
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
  }
  Serial.println("MPU6050 Found!");

  mpu.setAccelerometerRange(MPU6050_RANGE_4_G);
  switch (mpu.getAccelerometerRange()) {
  case MPU6050_RANGE_2_G:
    break;
  case MPU6050_RANGE_4_G:
    break;
  case MPU6050_RANGE_8_G:
    break;
  case MPU6050_RANGE_16_G:
    break;
  }
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);
  switch (mpu.getGyroRange()) {
  case MPU6050_RANGE_250_DEG:
    break;
  case MPU6050_RANGE_500_DEG:
    break;
  case MPU6050_RANGE_1000_DEG:
    break;
  case MPU6050_RANGE_2000_DEG:
    break;
  }

  mpu.setFilterBandwidth(MPU6050_BAND_260_HZ);
  Serial.print("Filter bandwidth set to: ");
  switch (mpu.getFilterBandwidth()) {
  case MPU6050_BAND_260_HZ:
    Serial.println("260 Hz");
    break;
  case MPU6050_BAND_184_HZ:
    Serial.println("184 Hz");
    break;
  case MPU6050_BAND_94_HZ:
    Serial.println("94 Hz");
    break;
  case MPU6050_BAND_44_HZ:
    Serial.println("44 Hz");
    break;
  case MPU6050_BAND_21_HZ:
    Serial.println("21 Hz");
    break;
  case MPU6050_BAND_10_HZ:
    Serial.println("10 Hz");
    break;
  case MPU6050_BAND_5_HZ:
    Serial.println("5 Hz");
    break;
  }
                                                                                //MPU6050 ACCELEROMETER INITIALIZATION CODE END
}

float startMillis;
float elapsedTime[3];
float rawMillis;

float X[3];
float Y[3];
float Z[3];

void loop() {
  digitalWrite(recordingLed, LOW);
  int buttonRecord = digitalRead(2);                                                //Check button for GND input
  /* Get new sensor events with the readings */
  if(buttonRecord == false){                                                        //Toggle record status upon pin 2 being pulled down to GND
    delay(500);
    recordStatus = !recordStatus;                                                   //If button is pressed, make recordStatus switch from true to false.
    startMillis = millis();
    Serial.print("BUTTON PRESSED");
  }
  if(recordStatus == true){                                                         //While record is toggled, do below
   digitalWrite(recordingLed, HIGH);
    sensors_event_t a, g, temp;
    mpu.getEvent(&a, &g, &temp);
for(int arrayNumber = 0; arrayNumber <= 3; ++arrayNumber){
    sensors_event_t a, g, temp;
    mpu.getEvent(&a, &g, &temp);

    X[arrayNumber] = (a.acceleration.x);                                             //SD CARD VALUES ASSIGN BEGIN/DO MATH TO CALCULATE G'S
    Y[arrayNumber] = (a.acceleration.y);
    Z[arrayNumber] = (a.acceleration.z);

    rawMillis = millis()-startMillis;
    elapsedTime[arrayNumber] = rawMillis;
    Serial.println(elapsedTime[arrayNumber]);
    Serial.println(X[arrayNumber]);
    Serial.println(Y[arrayNumber]);
    Serial.println(Z[arrayNumber]);
    Serial.println(arrayNumber);                                                     // diagnostic for checking to make sure arrays are being populated properly
}

    File dataFile = SD.open("datalog.txt", FILE_WRITE);
    Serial.print("LEFT LOGGING LOOP, ENTERING WRITE LOOP");

  if (dataFile) {                                                                    // if the file is available, write to it
    for(int arrayNumber = 0; arrayNumber <= 3; ++arrayNumber){
 Serial.print("NOW INSIDE WRITE LOOP");                                              // confirmation of being inside the write loop, and writing data to the file
    String(dataString) = (
    elapsedTime[arrayNumber] + String(", " ) + X[arrayNumber] + String(", ") + Y[arrayNumber] + String(", ") + Z[arrayNumber]         //Format data for output to the comma separated format for excel/gnuplot
  );
    dataFile.println(dataString);
       }
       dataFile.close();
       Serial.println("WRITE LOOP DONE");
    }
  }
}

```

# Answer
So I spent a while longer banging my head on the wall, and I finally found a solution to my issue. @DaveNewton provided several links that lead to other links, and I found my way to here where some not-so-common knowledge is explained. It appears that for some reason the FILE\_WRITE function is slow, and takes a lot of time to execute.

This can be substituted by using

> O\_CREAT | O\_WRITE | O\_APPEND

as this first checks if the file is created, and if not, creates it. Once the or check passes for the O\_CREAT section, it moves on into the O\_WRITE command. Then the O\_APPEND checks if there is any data already present and if so, move to the end of the line to begin new data logging.

My finished code in it's entirety is below, I hope it helps someone in the future. I'm using a MicroCenter 32GB (class 10) Micro SD card to store the data, this SD card breakout board, and this MPU-6050 based accelerometer.

```
// This program is designed to log data to an SD card via an arduino Uno, and SD card breakout board, and a MPU-6050 accelerometer module.

// MPU-6050:                https://www.amazon.com/HiLetgo-MPU-6050-Accelerometer-Gyroscope-Converter/dp/B078SS8NQV
// Micro SD Card Breakout:  https://www.adafruit.com/product/254
// Micro SD Card I used:    https://www.microcenter.com/product/485584/micro-center-32gb-microsdhc-card-class-10-flash-memory-card-with-adapter

// Link to original Arduino StackExchange submission where I worked through this code:  https://arduino.stackexchange.com/questions/84961/seeking-to-write-a-ton-of-information-to-an-sd-card-as-close-to-live-as-possible

#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>

int recordStatus = false;                                                   //Default recordStatus is zero.
int recordingLed = 3;                                                       //Output to show us whether we are recording or not.
const int chipSelect = 10;                                                  //Use pin 10 as our CS pin
Adafruit_MPU6050 mpu;

void setup(void) {
  pinMode(2, INPUT_PULLUP);                                               //Set pin 2 to have a default HIGH state using the internal pull up resistor.
  pinMode(3, OUTPUT);
  Serial.begin(500000);
  SPI.begin();
  SPI.beginTransaction(SPISettings(16000000, MSBFIRST, SPI_MODE0));       //I have no idea if this really does anything, but I figure I'd just leave it since it's not causing any problems.
  while (!Serial)
    delay(10); // will pause Zero, Leonardo, etc until serial console opens
                                                                           //SD CARD WRITE CODE BEGIN
 {

  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    while (1);
  }
  Serial.println("card initialized.");
}
                                                                              //SD CARD WRITE CODE END

  Serial.println("Adafruit MPU6050 test!");                                   //MPU6050 ACCELEROMETER INITIALIZATION CODE BEGIN
  // Try to initialize!
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
  }
  Serial.println("MPU6050 Found!");

  mpu.setAccelerometerRange(MPU6050_RANGE_16_G);                            //I originally had this at 4 but was capping results, so I moved it up to 16. Feel free to lower this if you know your application will not exceed 4Gs
  switch (mpu.getAccelerometerRange()) {
  case MPU6050_RANGE_2_G:
    break;
  case MPU6050_RANGE_4_G:
    break;
  case MPU6050_RANGE_8_G:
    break;
  case MPU6050_RANGE_16_G:
    break;
  }
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);                                //I'm not using the gyro at all, but 500 degrees seems like a good value to use here.
  switch (mpu.getGyroRange()) {
  case MPU6050_RANGE_250_DEG:
    break;
  case MPU6050_RANGE_500_DEG:
    break;
  case MPU6050_RANGE_1000_DEG:
    break;
  case MPU6050_RANGE_2000_DEG:
    break;
  }

  mpu.setFilterBandwidth(MPU6050_BAND_260_HZ);                              //Select maximum frequency for recording.
  Serial.print("Filter bandwidth set to: ");
  switch (mpu.getFilterBandwidth()) {
  case MPU6050_BAND_260_HZ:
    Serial.println("260 Hz");
    break;
  case MPU6050_BAND_184_HZ:
    Serial.println("184 Hz");
    break;
  case MPU6050_BAND_94_HZ:
    Serial.println("94 Hz");
    break;
  case MPU6050_BAND_44_HZ:
    Serial.println("44 Hz");
    break;
  case MPU6050_BAND_21_HZ:
    Serial.println("21 Hz");
    break;
  case MPU6050_BAND_10_HZ:
    Serial.println("10 Hz");
    break;
  case MPU6050_BAND_5_HZ:
    Serial.println("5 Hz");
    break;

   SPI.endTransaction();
  }
                                                                                //MPU6050 ACCELEROMETER INITIALIZATION CODE END
}
float X;
float Y;
float Z;
float startMillis;
float currentMillis;
float rawMillis;
int tickMillis = LOW;

void loop() {
  int buttonRecord = digitalRead(2);                                                //Check button (pin 2) to see if it is grounded through momentary switch.
  // Get new sensor events with the readings.

if(buttonRecord == LOW){                                                           //If buttonRecord switches to GND, switch tickMillis to it's opposite value as a toggle and store startMillis, then wait 300ms as a debounce.
    tickMillis = !tickMillis;
    startMillis = millis();
    delay(300);
}
    if(tickMillis == HIGH){
    File dataFile = SD.open("datalog.txt", O_CREAT | O_WRITE | O_APPEND);           // Create datalog.txt. If already created, move to end of stored data, and begin write function
    if (dataFile) {                                                                 // if the file is available, write to it:

  for(uint8_t i = 0; i < 250; i++){                                                 // For i = 0, execute the below code. Then increment i by 1. Once past 250, exit for() loop
    digitalWrite(recordingLed, HIGH);

    sensors_event_t a, g, temp;                                                     // Commands to trigger event sensing and acceleration logging.
    mpu.getEvent(&a, &g, &temp);

    X = a.acceleration.x/9.81;                                                      // Divide normal acceleration return values to calculate G forces
    Y = a.acceleration.y/9.81;
    Z = a.acceleration.z/9.81;

    rawMillis = millis()-startMillis;                                               // Take our current millis value and subtract our beginning startMillis from it to get how long we've actually been recording.

    dataFile.print(rawMillis/1000, 3);                                              // Store data in a Comma-Seperated-Value format. The '3' after rawMillis/1000 says print out to 3 decimal places.
    dataFile.print(", ");                                                           // I just use a txt file since GNUplot can plot from that value, but a CSV library could probably be used here.
    dataFile.print(X);                                                              // Excel doesn't allow plots beyond 255 datapoints for god knows why. So GNUplot is basically a necessity to plot these accurately to timestamp.
    dataFile.print(", ");
    dataFile.print(Y);
    dataFile.print(", ");
    dataFile.print(Z);
    dataFile.println();
    }
    dataFile.flush();
    dataFile.close();
    }
   else {
    delay(500);
    Serial.println("error opening datalog.txt");
    }
  } else {
        digitalWrite(recordingLed, LOW);
    }
}

```

Thanks so much for the comments/advice everyone. It's really appreciated. The final recording frequency for this is ~170Hz, which is good enough for me.
> 0 votes

---
Tags: sd-card, array, mpu6050, accelerometer, datalogging
---


# Question
Title: Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1)
Heres my code:

```
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>

const char* ssid = "wifiSSID";
const char* password =  "wifiPassword";

int sleepTime = 0;
HTTPClient http;

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

  Serial.println("START WIFI");
  WiFi.begin(ssid, password);

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

  http.begin("http://ip-address:3000/start?appid=1%2B6vIswDqSmXONCjq4rLtTMd9O2CHEQ4Oe");
  int httpCode = http.GET();
  String payload = http.getString();

  StaticJsonDocument<256> doc;
  deserializeJson(doc, payload);
  sleepTime = doc["sleep"];

  if (sleepTime > 0) {
    Serial.println("Sleeping for: " + sleepTime);
    delay(sleepTime);
    sleepTime = 0;
  }
}

void loop() {
  // Sensor stuff
}

```

Heres the error:

```
START WIFI
.........Guru Meditation Error: Core  1 panic'ed (Interrupt wdt timeout on CPU1)
Core 1 register dump:
PC      : 0x4000c271  PS      : 0x00060034  A0      : 0x8008a48c  A1      : 0x3ffb1c60
A2      : 0x3ffb0058  A3      : 0x3f41ae58  A4      : 0x00000014  A5      : 0x3ffbfea0
A6      : 0x3ffbfee8  A7      : 0x00000001  A8      : 0x00000001  A9      : 0x3f41ae59
A10     : 0x000000a5  A11     : 0x30303030  A12     : 0x8008b043  A13     : 0x3ffbfe70
A14     : 0x00000008  A15     : 0x00000001  SAR     : 0x00000012  EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xfffffffa

ELF file SHA256: 0000000000000000

Backtrace: 0x4000c271:0x3ffb1c60 0x4008a489:0x3ffb1c80 0x4008c034:0x3ffb1ca0 0x4008bfea:0x3ffb1cc0 0x400d5e5c:0x3f725c88

Core 0 register dump:
PC      : 0x40165582  PS      : 0x00060634  A0      : 0x8015196e  A1      : 0x3ffbc120
A2      : 0x00000000  A3      : 0x00000001  A4      : 0x80084032  A5      : 0x3ffbf870
A6      : 0x00060d20  A7      : 0x00000000  A8      : 0x801503f6  A9      : 0x3ffbc0f0
A10     : 0x00000000  A11     : 0x00000001  A12     : 0x80084032  A13     : 0x3ffbf870
A14     : 0x00000000  A15     : 0x3ffbc218  SAR     : 0x00000000  EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000  LBEG    : 0x00000000  LEND    : 0x00000000  LCOUNT  : 0x00000000

ELF file SHA256: 0000000000000000

Backtrace: 0x40165582:0x3ffbc120 0x4015196b:0x3ffbc140 0x4008b031:0x3ffbc160 0x40089882:0x3ffbc180

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6388
entry 0x400806b4

```

What should I do?

# Answer
> 1 votes
I got this problem too with the latest IDF version.. check the IDF version as it seems the problem with RTOS handling both cores together.

The solution was for me to downgrade the IDF version to 3.0.0

# Answer
> 0 votes
I suppose your are using Arduino IDE (maybe 1.x.x), if so, you should install the exception decoder so your can read such hex codes. They will give an more useful hint about the error location.

Here the link: https://github.com/me-no-dev/EspExceptionDecoder

---
Tags: esp32, json
---


# Question
Title: Arduino NANO clone not detected by computer
I recently purchased 5 Arduino Nano clones and on my Windows PC they were all working fine. I then gave one to a friend and after installing the CH34OC driver on his Mac he was able to program a simple Morse code blink program that worked fine on the device. However, after uploading it the COM port was no longer showing and his Mac could no longer detect the device.

We verified that the problem was not with the Serial cable and not with the USB port and other the Arduino clones worked perfectly also. So it must be an issue with the device which when connected the RX and TX lights would stay on and the inbuilt LED would display the Morse code as was programmed. The device would then no longer even be registered by my computer as no noise was made when plugging it in and nothing showed up in device manager as if I simply pugged in a USB cable with nothing attached.

I then used my Arduino UNO to run the Arduino ISP program and then burn the bootloader onto my NANO. This was successful and the a new blink program was loaded and the TX light no longer shows when connected to my computer but it is still entirely undetected as if nothing was plugged in.

I have tries many things including but not limited to:

Holding the reset button when plugging it in

Reinstalling the driver as administrator

Switching out the cable

Changing the USB port

Using the old bootloader

Reinstalling the Arduino IDE

Restarting my computer.

Sadly nothing is working and I am out of ideas. Does anyone have any suggestions for a fix or know how I can diagnose the issue further. For example checking to see if the USB chip on the Arduino is operational or maybe the diode was faulty? Methods for testing these things would be greatly appreciated.

# Answer
It sounds rather like a fault with the Nano's CH340 chip, the one used to communicate over USB between the Nano and a PC. The Atmega 328p seems to be working, as you say the previously loaded Morse Code program still runs. I expect you can still program the Atmega entirely through its ISP.

If the CH340 has been physically damaged, you can still program the Atmega processor via the ISP but you will no longer have USB capability on-board. You could use a CH340- or FTDI-cable (USB \<-\> TTL serial) connected to Arduino-pins 0 and 1 to provide off-board USB communication if you want to continue using the Nano as usual.

Update:

> Is there any way that I can verify that the CH340 chip has indeed been damaged as if it is something smaller like a diode I may attempt to repair it.

I don't know of a way unless a visual inspection shows a bad component. Not that there might not be one, just that that level of board repair is beyond my expertise. And assuming you didn't ever see or smell smoke, I wouldn't expect the defect to be visible. No harm in going over it with a strong magnifier, though....
> 1 votes

---
Tags: serial, arduino-nano
---


# Question
Title: How to save data to SD card using Memory Shield Module SPI
I am trying to save some data to the SD card using the memory shield module that I read from HC-SR04 Ultrasonic Module. The data that gets printed indicates error. This is how my SD card module is connected.

> SD card attached to SPI bus as
> VCC -Arduino 5v
> GND- Arduino GND
> MOSI - pin 11
> MISO - pin 12
> CLK - pin 13
> CS - pin 4

Still, Arduino complains that there was an error opening the file in SD card. My sketch is this:

```
#include <SPI.h>
#include <SD.h>
#define echoPin 6 // Echo Pin
#define trigPin 7 // Trigger Pin

int maximumRange = 250; // Maximum range needed
int minimumRange = 1; // Minimum range needed
long duration, distance; // Duration used to calculate distance
const int chipSelect = 4;

void setup() {
  Serial.begin (9600);
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);

  Serial.print("Initializing SD card...");
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
}

void loop() {
  readDistance();
  if(distance>minimumRange && distance < maximumRange){
    String string = "distance is" + distance;
    // open the file. note that only one file can be open at a time,
    // so you have to close this one before opening another.
    File dataFile = SD.open("datalog.txt", FILE_WRITE);
    // if the file is available, write to it:
    if( dataFile ){
      dataFile.println(string);
      dataFile.close();
      Serial.println( string );
    }else{
      // if the file isn't open, pop up an error:
      Serial.println("error opening datalog.txt");
      dataFile.close();
    }
  }else{
    Serial.println("Out of range...");
  }
  delay(50);
}

int readDistance(){
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = duration/58.2;
}

```

Output:

```
rror opening datalog.txt
rror opening datalog.txt
error opening datalog.txt
rror opening datalog.txt
error opening datalog.txt
error opening datalog.txt
error opening datalog.txt
error opening datalog.txt
error opening datalog.txt

```

How do I solve this to save the readings to SD card?

# Answer
> 2 votes
Is there any print out based on this;

```
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
  Serial.println("Card failed, or not present");
  // don't do anything more:
  return;
}
Serial.println("card initialized.");

```

Solution;

Try change

```
const int chipSelect = 4; // change value to 10

```

If not, try change the above code to;

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

```

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


# Question
Title: opencv reading the display and doesnot provide serial communication with arduino
I was creating a project where the following part of the code reads certain area of the display(which i screen shared from mobile)

```
import cv2 as cv
import numpy as np
from PIL import ImageGrab
import serial
arduinodata = serial.Serial('com5',9600)

def led_on():
    arduinodata.write(b'1')

def led_off():
    arduinodata.write(b'0')
i=1

while True:
    screen = np.array(ImageGrab.grab(bbox=(0,0,1920,1080)))
    #define the screen resulation
    screen_res = 1920, 1080
    scale_width = screen_res[0] / screen.shape[1]
    scale_height = screen_res[1] / screen.shape[0]
    scale = min(scale_width, scale_height)
    #resized window width and height
    window_width = int(screen.shape[1] * scale)
    window_height = int(screen.shape[0] * scale)
    #cv.namedWindow('Resized Window', cv.WINDOW_NORMAL)
    cv.resizeWindow('Resized Window', window_width, window_height)
    resized = screen.resize()
    health_bar = screen[262:268, 142:365]

    health_grayed = cv.cvtColor(health_bar, cv.COLOR_BGR2GRAY)
    count1 = cv.countNonZero(health_grayed)

if i==1:
    e =count1
    i=0

if e>count1:
    led_on()
    e=count1

if e<count1:

    e=count1

```

and whenever the value of the count1 variable decreases i want the Arduino led should be turned on

this was the arduino code

```
char serialData;

void setup() {
  // put your setup code here, to run once:
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);
  Serial.begin(9600);

}

void loop()
  // put your main code here, to run repeatedly:
{
  if(Serial.available() >0)
  {
    digitalWrite(13,HIGH);
    delay(1000);
    digitalWrite(13,LOW);

   }

}

```

But the led is turning on but does not turns off . I don't know why

can anyone please help me

# Answer
This happens because you are not reading from `Serial`.

When you send data to the Arduino, it gets placed in the `Serial` buffer. `Serial.available()` then returns the number of bytes in the buffer. The bytes are removed from the buffer by `Serial.read()`ing them, which you don't do. Since you don't remove any bytes from the buffer, `Serial.available()` will always return a number greater than zero from the moment on, that the first byte arrives. After the delay you turn the LED off via `digitalWrite(13,LOW);`, but in the next loop iteration the if statement is again executed (as described above). This happens so fast, that you think the LED just stays on. In reality it gets turned of for maybe a few microseconds and then turned on again.

You are sending a single byte for the LED to react. So it would be the simplest solution to just read a single byte from the buffer inside of the if statement. The result can be discarded.

```
void loop()
{
  if(Serial.available() >0)
  {
    digitalWrite(13,HIGH);
    delay(1000);
    digitalWrite(13,LOW);
    Serial.read();
   }
}

```

The `Serial.read()` removes one byte from the buffer and returns it (so it gets discarded here). This way the LED blinks for every byte, that the Arduino receives over `Serial`.

---

Note: Depending on how fast you are sending the data you might want to make more clear, that you have individual bytes. With the above code the LED will light up for 3 seconds straight if you send 3 bytes in (relatively) fast succession (meaning consecutive bytes less than a second apart). To make it more clear, that you have 3 individual bytes, you can add a `delay()` call after turning the LED off. That gives you the chance to actually see it turning off.
> 0 votes

---
Tags: arduino-uno, python, opencv
---


# Question
Title: What is required to run a program preciously uploaded and working from Arduino IDE via PC... (Nano 33 IoT)... but now powered via VIN, not USB?
The Arduino IDE works beautifully with the Nano 33 IoT using the IDE and is powered via USB. I now want to disconnect the USB and power thru the VIN pin (6-22V). The green led comes on but the program is not there or not running. Please help. thank you!

# Answer
Once you upload your code into the Arduino, it is there, burned into the flash memory of the microcontroller and it runs no matter how you power your board.

However, if in order to run your program is dependent on the Serial interface, for instance you added a line like `while(!Serial)` and you have not connected the USB cable, the program will loop at that point and will not continue.

For more information please upload your code.
> 0 votes

---
Tags: arduino-nano-33-iot
---


# Question
Title: RN42 Bluetooth HID KEYBOARD sketch by silverball
How can I use **RN42** sketch by silverball

```
/*
  RN42_HIDRaw_Arduino.cpp - Roving Netowrks RN42 Bluetooth HID raw library
  Developed by Chris Leitner - 2012

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

  RN42 HID raw report format:
  |start(1 byte)|length(1 byte)|descriptor(1 byte)|data(length - 1 [for the descriptor])
  Keyboard:
  |0xFD|9|1|modifier|0x00|code 1|code 2|code 3|code 4|code 5|code 6
  Keyboard modifier bits (sent as one byte)
  bit 7     |bit 6      |bit 5      |bit 4  |bit 3  |bit 2  |bit 1      |bit 0
  rt GUI    |rt alt     |rt shift   |rt ctrl|lt GUI |lt alt |lt shift   |lt ctrl

  You must initialize the Serial library in your code before you call any of these functions.
  The default speed for the RN42 is 115200 - add this in the setup function Serial.begin(115200);
  */

#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

#include "RN42_HIDRaw_Arduino.h"

RN42_HIDRaw_Arduino::RN42_HIDRaw_Arduino(){
}

//Sends a raw report for a keyboard HID
void RN42_HIDRaw_Arduino::SendKeyboardRaw(char raw_data[], uint8_t mod_bit){

    //write the RN42 Keyboard raw header
    Serial.write((uint8_t)0xFD); //start byte indicator for RN42
    Serial.write((uint8_t)0x09); //length of the raw report (how many bytes)
    Serial.write((uint8_t)0x01); //descritptor byte see the RN42 HID manual for details 0x01 is keyboard
    Serial.write((uint8_t)mod_bit); //modifier bit (indicates shift, control, and other keys (see comments above)
    Serial.write((uint8_t)0x00); //unused always send 0x00
    //write the key press data
    //each of these should be an ASCII keycode indicating a keypressed
    //example 0x04 is an 'a' see the RN42 HID manual for a list of codes
    Serial.write((uint8_t)raw_data[0]);
    Serial.write((uint8_t)raw_data[1]);
    Serial.write((uint8_t)raw_data[2]);
    Serial.write((uint8_t)raw_data[3]);
    Serial.write((uint8_t)raw_data[4]);
    Serial.write((uint8_t)raw_data[5]);
}

//This function just send a raw report with no keys or modifiers pressed
void RN42_HIDRaw_Arduino::SendKeyboardRawBlank(void){

    //write the RN42 Keyboard raw header
    Serial.write((uint8_t)0xFD);
    Serial.write((uint8_t)0x09);
    Serial.write((uint8_t)0x01);
    Serial.write((uint8_t)0x00);
    Serial.write((uint8_t)0x00);
    //write the key press data
    Serial.write((uint8_t)0x00);
    Serial.write((uint8_t)0x00);
    Serial.write((uint8_t)0x00);
    Serial.write((uint8_t)0x00);
    Serial.write((uint8_t)0x00);
    Serial.write((uint8_t)0x00);
}

//Sends a raw report for a gamepad
void RN42_HIDRaw_Arduino::SendGamepadRaw(char x_left, char y_left, char z_pos, char rot_pos, uint8_t buttons1, uint8_t buttons2)
{
    //write the header part for RN42
    Serial.write((uint8_t)0xFD); //start byte
    Serial.write((uint8_t)0x06); //length of the descriptor
    //gampad positions and buttons
    //on a gamepad there typically is two analog joysticks one is typically used to
    //indicate x/y position and one is for z/rotation.
    Serial.write((uint8_t)x_left); //value between -127 to 127 indicating the x postition
    Serial.write((uint8_t)y_left); //value between -127 to 127 indicating the y postition
    Serial.write((uint8_t)z_pos); //value between -127 to 127 indicating the z postition
    Serial.write((uint8_t)rot_pos); //value between -127 to 127 indicating the rotation postition
    //one bit for each button pressed there can be a total of 16 buttons one byte in each
    //set the bit to show a button pressed and clear the bit to indicate not pressed
    Serial.write((uint8_t)buttons1);
    Serial.write((uint8_t)buttons2);
}

void RN42_HIDRaw_Arduino::SendMouseRaw(uint8_t buttons, uint8_t x_stop, uint8_t y_stop, uint8_t wheel){
    //write the header part for RN42
    Serial.write((uint8_t)0xFD);
    Serial.write((uint8_t)0x05);
    Serial.write((uint8_t)0x02);
    //gampad positions and buttons
    Serial.write((uint8_t)buttons);
    Serial.write((uint8_t)x_stop);
    Serial.write((uint8_t)y_stop);
    Serial.write((uint8_t)wheel);
}

```

And act Like Keyboard.h do ? just simply putting `keyboard.press;`

JUst noob question.

# Answer
> 1 votes
if you are using an Arduino, I recommend you to use the BPlib, it's a free arduino library that contains functions that are similar to the Keyboard.h.

The following link is from the Arduino website: https://www.arduino.cc/reference/en/libraries/bplib/

When you download the Lib, take a look at the examples given by the creator of the Library, all the example code have the explanation of each funcition used, and you can also check for some documentation online. I hope that this help you!

---
Tags: bluetooth, arduino-pro-mini
---


# Question
Title: Unable to get readings for "Motor with Encoder"
I've posted to the DFRobot forum, who makes the FIT0186 motors, but no one seems to be replying there. So, excuse the copy pasting. It's probably an issue with the motor/encoder, but perhaps it has to do with the arduino. I'm using a Nano, and a TB6612 based motor driver from DFRobot.

I'm trying to get the built-in encoder working for the FIT0186.

The example wiki code doesn't work, and I've modified it as far as I can using sensible changes. I'm plugging both Hall Sensor A and B outputs to the interrupts.

Currently, when I plug in the 12V, it triggers an interrupt, but then other than that initial pulse, no interrupts are triggerred.

The motor is moving as expected. Attaching my code. Has anyone got the encoder working?

```
const byte encoder0pinA = 2;
const byte encoder0pinB = 3;
volatile int posA;
volatile int posB;

int DIR1 = 8;
int PWM1 = 9;

void setup()
{
  Serial.begin(115200);
  pinMode(DIR1, OUTPUT);
  pinMode(PWM1, OUTPUT);
  pinMode(encoder0pinA,INPUT);
  pinMode(encoder0pinB,INPUT);
  attachInterrupt(digitalPinToInterrupt(encoder0pinA), encoderA, RISING);
  attachInterrupt(digitalPinToInterrupt(encoder0pinB), encoderB, RISING);

}

void loop()
{
  Serial.print("Pulse:");
  Serial.println(posA);
  Serial.println(posB);

  noInterrupts();
  posA = 0;
  posB = 0;
  interrupts();

  delay(100);

  int value;
  digitalWrite(DIR1, HIGH);

  for(value = 0 ; value <= 255; value += 5)
  {
    analogWrite(PWM1, value);   //PWM Speed Control
    delay(20);
  }

  Serial.print("Pulse:");
  Serial.println(posA);
  Serial.println(posB);

  delay(100);

  for(value = 255 ; value >= 0; value -= 5)
  {
    analogWrite(PWM1, value);   //PWM Speed Control
    delay(20);
  }

  Serial.print("Pulse:");
  Serial.println(posA);
  Serial.println(posB);
  delay(100);

  digitalWrite(DIR1, LOW);
  for(value = 0 ; value <= 255; value += 5)
  {
    analogWrite(PWM1, value);   //PWM Speed Control
    delay(20);
  }

  Serial.print("Pulse:");
  Serial.println(posA);
  Serial.println(posB);

  delay(100);
  for(value = 255 ; value >= 0; value -= 5)
  {
    analogWrite(PWM1, value);   //PWM Speed Control
    delay(20);
  }

}

void encoderA()
{
    posA++;
}

void encoderB()
{
    posB++;
}

```

# Answer
> 1 votes
From what you have indicated (being wired correctly) there is a high probability you have a bad connection. It could be one of many things such as a loose wire, broken wire, problem with the module, etc... Swp A & B and see what happens.

---
Tags: arduino-nano, motor, interrupt, rotary-encoder, hall-effect
---


# Question
Title: Can you use multiple arduinos to run two programs simultaneously?
If I want to run 2 different programs simultaneously, can I do this with 2 arduinos wired together?

Context: I’m building a robot that will balance with reaction wheels while doing other tasks. I would like to have the balancing program running continuously in the background while the servos that control the robot are moving. Can I accomplish this by having a 2nd arduino running the balancing while the 1st arduino controls the rest of the robot?

# Answer
> 1 votes
The answer is yes, you can run two programs one in each Arduino. There are no restrictions on doing this. There are probably millions of Arduinos currently operating without any interaction with each other. In your robot they would need some sort of communications between them. This is if there is to be any type of interaction between them. I do not know your skill set but it may be possibly do it with one with some tight code.

---
Tags: i2c
---


# Question
Title: run a function for a certain amount of time!
i'm working on a project where i need to run a function for 20 minutes and the function writes to memory using EEPROM every minute. How can i make the function run for 20 minutes, i was thinking of using millis to measure the time between starting time and current but i'm afraid that when the millis rolls over and the the difference in time becomes negative my program will break and my function will run forever . Is there any way to make a function run for a certain amount of time, or will millis handle the rollover if we use unsigned variables for all variables for millis();

# Answer
> 1 votes
See this answer for an explanation. Using unsigned variables, and *subtracting* will definitely work.

Not only will unsigned variables not become negative (by their very nature) but the rollover will be handled smoothly and accurately.

# Answer
> 1 votes
Another way to solve this problem is using cronAlarm. It can provide precise control on timings and you can schedule your job also. https://www.arduino.cc/reference/en/libraries/cronalarms/

---
Tags: arduino-uno, timers, time, millis
---


# Question
Title: Arduino randomly stops sending data to python over serial
I want to send commands to Arduino over USB Serial from my python program and Arduino should send back received command to make sure data wasn't lost. However Arduino randomly stops sending data back. For debugging purposes I made builtin LED blink in the loop function. When Arduino stops sending data the LED slows down blinking (about 2-3 times). I tried this on Arduino Uno and Arduino Nano to make sure it is not damaged board.

Here is my Python code responsible for communication:

```

class Communication(ABC):
    def __init__(self) -> None:
        self.history: list = []
        self.response_history: list = []
        self.last_responses: dict = dict()
        self.queue: collections.deque[str] = collections.deque()
        self.is_sending: bool = False
        self.command_recived_condition: threading.Condition = threading.Condition()

    def append_commands(self, commands: str) -> None:
        commands = map(lambda x: "c"+x, map(lambda x: x+";", filter(len, commands.split(";"))))
        for command in commands:
            self.queue.append(command)

    def append_and_send(self, commands: str) -> None:
        self.append_commands(commands)
        if not self.is_sending:
            self.sender: threading.Thread = threading.Thread(target=Communication.send_commands, args=(self, ))
            self.sender.start()

    @abstractmethod
    def send_command(self, command: str) -> bool:
        """ Sends command to the controller, waits for the response and tries again if command was not recived succesfully """
        pass

    @abstractmethod
    def listen(self) -> None:
        pass

    @abstractmethod
    def check_for_response(self, command: str) -> None:
        pass

    def send_commands(self):
        self.is_sending = True
        commands = self.queue
        while len(commands) > 0:
            command = commands.popleft()
            self.send_command(command)

        self.is_sending = False

class Serial_comunication(Communication):
    def __init__(self, port: str) -> None:
        super().__init__()
        self.serialcom = serial.Serial(port, 4800)

        self.listen()

        time.sleep(0.1)
        self.send_command("PING;")
        time.sleep(0.1)

    def listen(self) -> None:
        def listen_util() -> None:
            chars = []

            while True:
                if self.serialcom.inWaiting() > 0:
                    time.sleep(0.01)
                    try:
                        char: str = self.serialcom.read().decode()
                    except UnicodeDecodeError:
                        print("decoding err")
                        continue
                    print(char, end=" ")

                    if char[-1] == '#':
                        response_str = "".join(chars)
                        category, content = response_str.split("::")
                        self.last_responses[category] = content
                        self.response_history.append(response_str)
                        chars.clear()
                        print("\n", response_str)
                        if category == 'Info: recived':
                            with self.command_recived_condition:
                                self.command_recived_condition.notify()
                    else:
                        chars.append(char)

                time.sleep(0.01)

        self.listener = threading.Thread(target=listen_util)
        self.listener.start()

    def check_for_response(self, command: str) -> None:
        print("check")

        if self.last_responses.get('Info: recived') == command:
            print('possitive')
            return True

        return False

    def send_command(self, command: str) -> None:

        while True:
            time.sleep(0.1)
            self.serialcom.write(command.encode())
            print("sent", command)

            with self.command_recived_condition:
                self.command_recived_condition.wait()
                print("waited")

            if self.check_for_response(command.strip().strip(';')):
                break

```

And my Arduino Code responsible for communication:

```
#define INPUT_SIZE 50
char input[INPUT_SIZE + 1];

bool check_for_orders(Order& cmd, char *val, uint8_t& place)
{
    if (Serial.available() > 0)
    {
        // Read input from Serial until ; what means command has ended
        size_t size = Serial.readBytesUntil(';', input, INPUT_SIZE);
        input[size] = 0; // Add null terminator

        Serial.print(F("Info: recived::"));
        delay(10);
        Serial.print(input);
        Serial.print(F("#"));
        Serial.flush();

        // Check if command is not empty
        if (input[0] != 0)
        {
            // syntax is "order:pattern_place:value"
            cmd = static_cast<Order>(atoi(strtok(((char*)input)+1, ":"))); // Get order numer and convert to enum
            place = atoi(strtok(NULL, ":")); // Get place number from input (only 0 or 1 is allowed)
            char *value = strtok(NULL, ":"); // Get value from second part of string

            if (value == 0) // If value is empty then syntax is invalid
            {
                return false;
            }

            // Otherwise copy order name and value to c-strings from main function
            strcpy(val, value);
            free(value);

            return true;
        }
        else // Probably never gonna happen
        {
            return false;
        }
    }
    return false;
}

```

The check\_for\_orders function is run every time loop function is run.

Here is what python printed when I sent the following commands \["PING;", "c0:0:0;", "c0:1:0; c15:0:100,600,20,2,0,200,255,170,255,200;"\]

```
sent PING;
I n f o :   r e c i v e d : : P I N G #
 Info: recived::PING
waited
check
possitive
sent c0:0:0;
I n f o :   r e c i v e d : : c 0 : 0 : 0 #
 Info: recived::c0:0:0
waited
check
possitive
sent c0:1:0;
I n f o :   r e c i v e d : : c 0 : 1 : 0 #
 Info: recived::c0:1:0
waited
check
possitive
sent c15:0:100,600,20,2,0,200,255,170,255,200;
I n f o :   r e c i v e d : : c 1 5 : 0 : 1 0 0 , 6 0 0 , 2 0 , 2 , 0 , 2 0 0 , 2 5 5 , 1 7 0 , 2 5 5 , 2 0 0 #
 Info: recived::c15:0:100,600,20,2,0,200,255,170,255,200
waited
check
possitive
sent c1:0:1;
/* and it got stuck */

```

Do someone know why something here is getting stuck and/or how to solve this problem?

# Answer
> 2 votes
I removed `free(value)` \- rookie mistake - but that didn't completely solved the problem (but reduced frequency of occurrences). Seems like declaring array like `char val[50]` and passing it to function as `char* val` was a bad idea. I changed array declaration to `char *val = new char[50]` and now seems like everything works fine.

---
Tags: serial, arduino-nano, python
---


# Question
Title: Dropping a 75V power supply to power an Arduino Mega
I'm looking to power an Arduino Mega using this IPC-5 power supply from Teknic since I will have a free port (the other powers a servo). I would like to use this extra port to power my Arduino rather than draw power from another source. The problem is that this is 75V coming out which would eat up the Arduino.

Is it as simple as hooking up a resistor in series with the Arduino to bring the voltage down to about 7V for the Arduino? If that's the case, then how can I determine the unknowns to find the appropriate resistor?

Correct me if I'm wrong, but if I apply Ohm's Law and Kirchhoff's Rules, I can set up this relationship: 75V = IR + 7V. Can I make an assumption for the current to solve for the resistance?

This is my first real Arduino project, so my knowledge of many things that y'all may consider common knowledge is lacking.

# Answer
The short answer is NO, you can't do that. Consider the size of the resistor needed to dissipate all that wattage and the fact that the current is not stable so it is practically impossible.

What you need is a DC to DC converter.
> 3 votes

# Answer
> Is it as simple as hooking up a resistor in series with the Arduino to bring the voltage down to about 7V for the Arduino?

No, it certainly is not.

> Can I make an assumption for the current to solve for the resistance?

No, you cannot. You *never* assume anything in electronics without a very very good reason.

You require a suitably rated voltage regulator (a switching DC/DC regulator for those kind of voltages) to convert the voltage properly.
> 1 votes

---
Tags: arduino-mega, power
---


# Question
Title: Save Watchdog ISR Return Address in EEPROM
If the WDT ever fires, from the ISR I save some info in EEPROM for later diagnostics before I drive the reset pin. Stack size, heap size, etc.

It might also be useful to know where the code was when the WDT fired, i.e. the ISR's return address. How do I get that?

# Answer
> 5 votes
GCC has a handy function `__builtin_return_address(depth)` which should do what you want. To get the return address of the current function (which should be the same whether it's a normal function or an ISR on AVR) you set the `depth` to 0:

```
void *addr = __builtin_return_address(0);

```

**EDIT**

The address returned above is a word address. Multiply by two to get a byte address as found in the disassembly from `avr-objdump -SC firmware.elf >disassembled.txt`

The latter is found at `~/.platformio/packages/toolchain-atmelavr/bin/avr-objdump`

---
Tags: interrupt, atmega328, watchdog
---


# Question
Title: I am trying to automate my sun shade on my back porch with a Nema17 Stepper motor
I am very new to Arduino (and fritzing so please excuse my poor layout). I am trying to automate my patio sun shade, eventually it will incorporate a photocell but I wanted a proof of concept first with buttons. The first and last buttons represent limit switches and the middle button represents a toggle switch (which will eventually become the photocell).

An example of what I am trying to do is; If the upper limit switch is active and I press the toggle button, the stepper runs until it hits the lower limit switch, if the lower limit switch is active and I press the toggle button then the stepper should run the other direction until it hits the upper limit switch.

I have serial prints to show what is happening, if I hold either of the "limit switches" then the serial monitor displays (rather spams) the corresponding print line, however the stepper motor is not moving how I would expect it to. I have to be holding a limit switch and holding the toggle for it to move in a direction, even then it only moves approximately 1 step per second. If I release the limit switch and continue to hold the toggle then the stepper steps one back and one forward for the duration that I depress the switch. The code I have is based off of someone attempting the same thing but with a DC motor, I tried to accommodate it to a stepper motor and am having trouble.

```
    // constants won't change. They're used here to set pin numbers:
const int uplimitPin = 9;     // pin number for upper limit switch
const int togglebuttonPin = 10;     // pin number for the toggle switch
const int downlimitPin = 11;     // pin number for the lower limit switch
const int dirPin =  2;      // direction pin for stepper
const int stepPin =  3;      // step pin for stepper

// variables will change:
boolean uplimitState = 0;         // variable for reading the status of the upper limit switch
boolean togglebuttonState = 0;         // variable for reading the toggle switch status
boolean downlimitState = 0;   // variable for reading the status of the lower limit switch

int shadePosition = 2;  // Tells progam what position the shade is in

/**
 *  setup inputs for switches and outs for motor pins
 *  serial begin to read the switches to test for errors
 */
void setup() {
    // initialize the stepper pins as outputs:
    pinMode(dirPin, OUTPUT);
    pinMode(stepPin, OUTPUT);
    // initialize the pushbutton pins as an inputs:
    pinMode(uplimitPin, INPUT);
    pinMode(togglebuttonPin, INPUT);
    pinMode(downlimitPin, INPUT);
    Serial.begin(9600);
}

/**
 * this function turns motor foward
 */
void shadeDown() {
     // turn motor foward:
    digitalWrite(dirPin, HIGH);
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(1000);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(1000);
}

/**
 * this function turns motor backwards
 */
void shadeUp() {
     // turn motor in other direction:
    digitalWrite(dirPin, LOW);
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(1000);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(1000);
}

/**
 * Stop the motor form moving
 */
void stopShade() {
  digitalWrite(stepPin, LOW);

}

/**
 *
 */
void loop() {
   // read the state of the pushbutton value:
   uplimitState = digitalRead(uplimitPin);
   togglebuttonState = digitalRead(togglebuttonPin);
   downlimitState = digitalRead(downlimitPin);

   // check if the limit is active. If it is, the limitState is HIGH:
   if (uplimitState == HIGH) {
      shadePosition = 2;
      Serial.println(F("The shade is up"));
      stopShade();
   }else if (downlimitState == HIGH) {
      shadePosition = 1;
      Serial.println(F("The shade is down"));
      stopShade();
  }

  if (togglebuttonState == HIGH) {
    if( shadePosition  == 1 ){
      shadeUp();
      delay(100);
      shadePosition = 2;
      delay(100);
    }else if (shadePosition == 2 ) {
      delay(100);
      shadeDown();
      delay(100);
      shadePosition = 1;
    }

  }
}

```

# Answer
> 1 votes
# System State Machine

As JRobert suggested, a state machine would make the code a lot cleaner! Below is some pseudocode (I'll leave the debugging up to you ;)) of how you might set that up.

When you break up your system into 4 distinct states, it's easy to reason about what should be happening at each state and what is required to get to the next state. You can draw a diagram showing this (google "state machine") to help you reason.

```
...

enum SystemState {
    SystemState_Opening,
    SystemState_Closing,
    SystemState_Open,
    SystemState_Closed
};

void main()
{
    // Set initial state
    SystemState state;
    if (digitalRead(upLimitState))
    {
        state = SystemState_Closed;
    }
    else
    {
        state = SystemState_Open;
    }

    // Run state machine
    while (1)
    {
        switch (state)
        {
            case SystemState_Closed:
            {
                if (digitalRead(toggleButtonPin))
                {
                    state = SystemState_Opening;
                }
                break;
            }
            case SystemState_Open:
            {
                // TODO: Implement this yourself!
                break;
            }
            case SystemState_Closing:
            {
                if (digitalRead(upLimitState))
                {
                    state = SystemState_Closed;
                }
                shadeUp();
                break;
            }
            case SystemState_Opening:
            {
                // TODO: Implement this yourself!
                break;
            }
    }
}

```

# What's Wrong With Your Code

The actual issue with the code you provided is that you're only calling the `shadeUp()` function once. You need to call it many times to send the step pin many pulses to rotate the motor.

Each time you send a pulse to the step pin (eg. `shadeUp()`), you rotate the motor by one step (or microstep) which is likely only 1.8 degrees!

# Answer
> 0 votes
Assuming you're asking how debug the unexpected behavior your described (and not having any steppers on-hand to have a go at your code) I'll offer some observations and suggestions.

Pushbuttons "bounce" (not really, but their output signal looks like they bounce). For the limit switches, you won't really care - the first make (and I'm assuming positive logic, for simplicity of the discussion) tells you that the shade has reached it's limit, and you don't need to (probably shouldn't!) wait for the switch to settle before stopping the shade. The 'break' of a limit switch is uninteresting except possibly to confirm that the shade is moving when you expected it to, and again, who cares about the bounces? But the toggle button's bounces may well confound your logic unless you debounce it (can be done either electrically or in software - search the topic). And even though the eventual photocell may not bounce (or it may: are there shade-trees within it's view, f/ex?), right now, you're testing with a button which certainly does.

This is a would be a good application to implement as a state-machine, and even if you don't do that formally, diagramming a state-machine to operate your shade should make it clear what your code will need to do. If you're new to software as well as to Arduino, learning about state-machines might be a longer detour than you want to take at the moment, but if this kind of control system is what interests you, you will encounter them sooner or later, because they model your control system pretty directly, both graphically (because you usually sketch them out first) and in software.

State diagrams turn out to be one of the best tools a software designer has to communicate the details of a proposed control system between them and the typically-non-software-trained people who are the experts at building and/or using the devices being automated (think printing presses, copiers, assembly robots, .... ). The picture says it all.

---
Tags: arduino-uno, stepper-motor, home-automation
---


# Question
Title: Bluetooth connection to HC-05 paired but not connected (in Linux)
I have an Arduino Uno connected to an HC-05 Bluetooth sender/receiver chip. I am trying to create a Bluetooth connection between my Acer laptop running under Ubuntu 14.04 LTS and the HC-05 chip.

Ubuntu detects the HC-05 chip, as can be seen below.

```
phodor@ubuntu: hcitool scan
Scanning ...
    11:22:33:44:55:66   HC-05

```

I am able to create a pair between my laptop Bluetooth device and the HC-05 chip. However, I am unable to create a connection with that pair from the Ubuntu interface. The "Connection" button cannot be clicked on, as you can see on the figure below.

I tried creating a connection using the terminal, but after that the terminal still did not detect any connection.

```
phodor@ubuntu: sudo hcitool cc 11:22:33:44:55:66
[sudo] password for phodor:
phodor@ubuntu: hcitool con
Connections:

```

I also checked that my computer Bluetooth device was working.

```
phodor@ubuntu: hcitool dev
Devices:
    hci0    AA:BB:CC:DD:EE:FF

```

Any idea why the connection cannot be created ? Any idea on how to do it using the Ubuntu interface or the terminal ?

# Answer
You can find the answer in the Bluetooth connection to HC-05 paired but not connected

Step;

1.Once you have paired the HC-05 as you've described, bind the device by entering;

```
sudo rfcomm bind 0 "MAC address" 1

```

2.To trigger the connection & display the data using minicom, run;

```
sudo minicom -D /dev/rfcomm0

```

You'll notice that port /dev/rfcomm0 will be available from the arduino IDE as well.

3.To exit minicom, press ctrl+A and then X.
> 1 votes

# Answer
you can try this website for more information

http://wiki.micropython.org/official-accessories/Bluetooth-module-HC05
> 0 votes

---
Tags: bluetooth, ubuntu, hc-05
---


title: unbrick Nano RP2040 connect using Uno

text:
# Question
Title: unbrick Nano RP2040 connect using Uno
I think I have bricked my Nano RP2040. How do I unbrick using a Uno or Mega? I found instructions for using another Nano, but only have the one.

# Answer
> 3 votes
You don't actually need a Uno or mega to unbrick the device. You need to place a jumper wire between the GND and REC pins. This will force the bootloader to load, a mass-storage device will appear on the computer. You can than upload a UF2 file to the drive to restore it.

You can read more about it in the arduino documentation. https://docs.arduino.cc/tutorials/nano-rp2040-connect/rp2040-01-technical-reference#forcing-bootloader

If it is really bad you might also need to use a flash\_nuke.uf2 file first. This removes all files on the Arduino Nano RP2040 connect.

---
Tags: arduino-nano
---


title: Global Variable not updating…

text:
# Question
Title: Global Variable not updating…
I'm building a small project to maintain a copper plating tank's temperature and filter pump duty cycle. I'm using the Adafruit Feather platform to hold an 8 segment matrix coupled with a Teensy 3.2 (on a Feather shield) to calculate and display temp. There is a 10K Pot on A0 and an 8 segment NeoPixel Strip to set and display pump duty cycle from 1 to 8 corresponding to .125\*hour and 100% on. There is also a push and hold set switch to operate temperature target point setting using the same pot.

Things that work: Almost Everything! Thing that doesn't work:

Changing the Duty Cycle knob (which changes the duty cycle global variable) after turning the unit on doesn't seem to change the on/off times other than to successfully change the NeoPixel display. If the unit is turned on at a particular duty cycle, the program will run that duty cycle successfully. While running, if I change the duty Cycle to 8, I don't get a "100% On". In other words the change in the duty cycle variable doesn't seem to change the on time and off time variables in the code while running.

Q: What do I need to do to make the duty cycle setting work on the fly?

Oh... That Volatile Float declaration was my last desperate attempt, Please ignore / forgive. ;-)

Hopefully the fix is as simple as the code. ;-) I just don't see it and my (perhaps flawed) understanding of global variables is hit a wall.

Any help will be much appreciated. Thanks.

Jeff

Code:

```

/***************************************************
  Copper Plating Tank Control - v1.1
  by Jeff W. Parisse - July 7st, 2021
  www.coppercholla.com

  This program runs a programmable interval timer for chemical pump
  duty cycle and a programmable temperature setting and heating control
  for maintaining plating solution temperature.

  Processor: PJRC Teensy 3.2
  Additional Libraries: Adafruit Industries LLC
  Temperature Sensor: Adafruit MAX31865 w/P1000 Platinum Wire Probe
  Pin Outs:
    Setting Knob: Pin A0
    Matrix Display: Feather Matrix I2C 0x70
    Neopixels: Pin 5
    MAX31865: CLK Blue
    MAX31865: SDO Yellow
    MAX31865: SDI White
    MAX31865: CS Pin 6 Green
    Temp Set Switch: Pin 8
    Chemical Pump: Pin 9
    Tank Heater: Pin 10

 ****************************************************/

#include <Adafruit_MAX31865.h>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"
#include <Adafruit_NeoPixel.h>

#define knobPin A0
#define ledPin 5
#define csPin 6
#define switchPin 8
#define pumpPin 9
#define heaterPin 10
#define ledCount 8
#define sampleNum 4
#define RREF      4296.0
#define RNOMINAL  1000.0

Adafruit_MAX31865 thermo = Adafruit_MAX31865(csPin);
Adafruit_7segment matrix = Adafruit_7segment();
Adafruit_NeoPixel strip(ledCount, ledPin, NEO_GRB + NEO_KHZ800);

float targetTemp = 77.0;                // Starting Value
float readTemp = 0;
float toleranceTemp = 0.25;
float tempSum = 0;
float cTemp = 0;
float fTemp = 0;
volatile float dutyCycle = 4;
unsigned long previousTime = 0;
unsigned long oneHour = 3600000;       // 1 Hour in Milliseconds
unsigned long timeOn = 450000;         // 7.5 Minutes in Milliseconds
unsigned long pumpInterval = timeOn;
boolean pumpState = true;

void setup() {
  thermo.begin(MAX31865_3WIRE);;
  matrix.begin(0x70);
  strip.begin();
  strip.show();
  pinMode(csPin, OUTPUT);
  pinMode(heaterPin, OUTPUT);
  pinMode(pumpPin, OUTPUT);
  pinMode(switchPin, INPUT_PULLUP);
  digitalWrite(csPin, LOW);
  digitalWrite(heaterPin, LOW);
  digitalWrite(pumpPin, LOW);
}

void loop() {
  // Read Set Switch
  int setSwitch = (digitalRead(switchPin));
  while (setSwitch == LOW) {
    int readKnob = analogRead(knobPin);
    targetTemp = map(readKnob, 1, 1023, 67, 87);
    matrix.print(targetTemp, 1);
    matrix.writeDisplay();
    setSwitch = (digitalRead(switchPin));
  }

  // Read, Convert, and Display Temp
  tempSum = 0;
  for (int i = 1; i <= sampleNum; i++) {
    readTemp = thermo.temperature(RNOMINAL, RREF);
    tempSum = tempSum + readTemp;
  }
  cTemp = tempSum / sampleNum;
  fTemp = (cTemp * 1.8) + 32;
  matrix.print(fTemp, 1);
  matrix.writeDisplay();

  // Heater Logic
  if (fTemp < targetTemp - toleranceTemp) {
    digitalWrite(heaterPin, HIGH);
  }
  else if (fTemp > targetTemp + toleranceTemp) {
    digitalWrite(heaterPin, LOW);
  }

  // Read and Display Duty Cycle
  int readKnob = analogRead(knobPin);
  dutyCycle = map(readKnob, 1, 1023, 1, 8);
  for (int i = 0; i <= ledCount; i++) {
    strip.setPixelColor(i, 0, 0, 0);
  }
  strip.show();
  for (int i = 0; i <= dutyCycle - 1; i++) {
    strip.setPixelColor(i, 0, 0, 20);
  }
  strip.show();

  // Pump Timer
  digitalWrite(pumpPin, pumpState);
  unsigned long timeOn = ((dutyCycle / 8UL) * oneHour);
  unsigned long timeOff = (oneHour - timeOn);
  unsigned long currentTime = millis();
  if (currentTime - previousTime >= pumpInterval) {
    if (pumpState) {
      pumpInterval = timeOff;
    }
    else {
      pumpInterval = timeOn;
    }
    pumpState = !(pumpState);
    previousTime = currentTime;
  }
}

```

# Answer
> 2 votes
I do not really understand what may be the cause of your problem, but I have identified two issues that could potentially be related.

You have:

> ```
> dutyCycle = map(readKnob, 1, 1023, 1, 8);
>
> ```

Because of some rounding issues in the Arduino `map()` function, this may not work as you expect: the output will be 8 only if the input reaches 1023. If `readKnob` is 1022, `dutyCycle` will be 7. This may explain why you never see the pump being constantly on.

The way `map()` works makes most sense if you think in terms of *half-open* intervals, open on the right. If you write:

```
dutyCycle = map(readKnob, 0, 1024, 1, 9);

```

you will get a perfect mapping from \[0, 1024) to \[1, 9). Perfect in the sense that there will be exactly 128 input values mapped to each output value:

```
[  0, 128) → 1
[128, 256) → 2
[256, 384) → 3
...

```

And later:

> ```
> for (int i = 0; i <= ledCount; i++) {
>     strip.setPixelColor(i, 0, 0, 0);
> }
>
> ```

The strip has `ledCount` pixels, numbered 0 to `ledCount-1`. This loop will set the color of pixels 0 through `ledCount` inclusive. The last iteration goes beyond the end of the strip, and it is most likely corrupting memory, i.e. overwriting whatever data happens to sit right after the memory area used for the strip. If this is overwriting some variable related to the duty cycle, that may explain the weird behavior you experience.

---
Tags: variables
---


# Question
Title: Undocumented industrial servo with 8-wire encoder: how to read this encoder?
I have scavenged an industrial servo with its attached ballscrew linear actuator from an old large format scanner, and I am trying to figure out how to make a 'servo drive' aka 'servo driver' aka 'servo controller'.

I'm a total novice at arduino, and am mostly a copy/paste coder - so of course this makes my goal harder.

I can find a lot of information on how to read a simple AB offset encoder that needs ***four*** wires to work, but the encoder I have has eight wires:

A+, A-, B+, B-, Z+, Z-, +5v, 0v(aka GND)

With +5v supplied to it's wire and GND connected to 0v, rotating the motor shaft by hand, my meter reads:

* A+: +3.97v as the 'high' and +.036v as 'low'
* A-: same
* B+: same
* B-: same
* Z+: same - but only goes high at one location on the 360 degree
rotation
* Z-: same - but only goes high at one location on the 360 degree rotation - the same location as Z+

NOTE: Both Z pulses coincide with pulses on A+, B+, and B- ... but those are NOT coincident on A-. So maybe A- has the Z+/- trigger in it's place? I don't know. It was VERY challenging to stop rotating the shaft AT a pulse because of the tiny size of the divisions.

All voltages seen by my digital multimeter were positive voltages.

I do not understand how to properly use the encoder with so many wires. I can sort of understand that the positive and negative are probably opposite signals from each other, sort of error protection or something? I know that the Z= and Z- are roattion counters at either 90, 180, or some other offset angle to allow ticking full rotations. But am unsure about this all and am reading a lot of material that is beyond me. I'm stumped.

I can install the following code on an UNO and the UNO reads the encoder just fine off the A+ and B+ lines, with increasing count for one direction of rotation and decreasing count for the other direction. So it is reflecting the movement as it should...

BUT- I am getting 8000 pulses per shaft revolution rather than the 2000 pulses per revolution in the documentation. So something's not right here. I should see 2000 pulses per revolution... is this because of the lack of use of the other wires? Or something else?

Code i'm using for just A+ and B+:

```
    /*
*Quadrature Decoder
*/
#include "Arduino.h"
#include <digitalWriteFast.h>

// Quadrature encoders
// Left encoder
#define c_LeftEncoderInterruptA 0
#define c_LeftEncoderInterruptB 1
#define c_LeftEncoderPinA 2
#define c_LeftEncoderPinB 3
#define LeftEncoderIsReversed

volatile bool _LeftEncoderASet;
volatile bool _LeftEncoderBSet;
volatile bool _LeftEncoderAPrev;
volatile bool _LeftEncoderBPrev;
volatile long _LeftEncoderTicks = 0;

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

  // Quadrature encoders
  // Left encoder
  pinMode(c_LeftEncoderPinA, INPUT);      // sets pin A as input
  digitalWrite(c_LeftEncoderPinA, LOW);  // turn on pullup resistors
  pinMode(c_LeftEncoderPinB, INPUT);      // sets pin B as input
  digitalWrite(c_LeftEncoderPinB, LOW);  // turn on pullup resistors
  attachInterrupt(c_LeftEncoderInterruptA, HandleLeftMotorInterruptA, CHANGE);
  attachInterrupt(c_LeftEncoderInterruptB, HandleLeftMotorInterruptB, CHANGE);
}

void loop()
{
  Serial.print("Encoder Ticks: ");
  Serial.print(_LeftEncoderTicks);
  Serial.print("  Revolutions: ");
  Serial.print(_LeftEncoderTicks/2000.0); //2000 Counts Per Revolution, per the engineering manual
  Serial.print("\n");
}

// Interrupt service routines for the left motor's quadrature encoder
void HandleLeftMotorInterruptA(){
  _LeftEncoderBSet = digitalReadFast(c_LeftEncoderPinB);
  _LeftEncoderASet = digitalReadFast(c_LeftEncoderPinA);

  _LeftEncoderTicks+=ParseEncoder();

  _LeftEncoderAPrev = _LeftEncoderASet;
  _LeftEncoderBPrev = _LeftEncoderBSet;
}

// Interrupt service routines for the right motor's quadrature encoder
void HandleLeftMotorInterruptB(){
  // Test transition;
  _LeftEncoderBSet = digitalReadFast(c_LeftEncoderPinB);
  _LeftEncoderASet = digitalReadFast(c_LeftEncoderPinA);

  _LeftEncoderTicks+=ParseEncoder();

  _LeftEncoderAPrev = _LeftEncoderASet;
  _LeftEncoderBPrev = _LeftEncoderBSet;
}

int ParseEncoder(){
  if(_LeftEncoderAPrev && _LeftEncoderBPrev){
    if(!_LeftEncoderASet && _LeftEncoderBSet) return 1;
    if(_LeftEncoderASet && !_LeftEncoderBSet) return -1;
  }else if(!_LeftEncoderAPrev && _LeftEncoderBPrev){
    if(!_LeftEncoderASet && !_LeftEncoderBSet) return 1;
    if(_LeftEncoderASet && _LeftEncoderBSet) return -1;
  }else if(!_LeftEncoderAPrev && !_LeftEncoderBPrev){
    if(_LeftEncoderASet && !_LeftEncoderBSet) return 1;
    if(!_LeftEncoderASet && _LeftEncoderBSet) return -1;
  }else if(_LeftEncoderAPrev && !_LeftEncoderBPrev){
    if(_LeftEncoderASet && _LeftEncoderBSet) return 1;
    if(!_LeftEncoderASet && !_LeftEncoderBSet) return -1;
  }
}

```

. . . Can someone explain the function of, and how to use, all eight wires? Explain why I'm getting 4X the counts that I should with that code above? PLEASE? . . .

I'm posting images of the pages from the machine's engineering handbook that have info about the servo and encoder. The info there shows that it was more or less controlled like an RC servo from the mainboard's perspective - just PWM. But it had the drive/driver/controller parts right on the mainboard of the machine.

If it will be of use I can post pictures of the encoder board itself, but at this point I did not think that necessary.

# Answer
> 2 votes
I had some trouble figuring this out too. I did some more googling and found this site below via an Arduino forum post: 8 wire connection for quadrature encoder, differential wiring

Here is what they say:

> "These terms refer not to the waveforms of signals, but instead to the way the signals are wired.
>
> Single-ended wiring uses one signal wire per channel and all signals are referenced to a common ground.
>
> TTL and Open Collector are types of single-ended wiring.
>
> Differential wiring uses two wires per channel that are referenced to each other. The signals on these wires are always 180 electrical degrees out of phase, or exact opposites. This wiring is useful for higher noise immunity, at the cost of having more electrical connections. Differential wiring is often employed in longer wire runs as any noise picked up on the wiring is common mode rejected."

So basically we have our Power supply wire and ground, and 2 wires per signal (A+/A-, B+/B-, Z+/Z-).

2 + 6 wires = 8 wires

Now all I have to figure out is how to connect those 6 wires to an Arduino. I get how to connect the A+, B+, Z+ signals on 3 interrupt pins, now I'm just wondering if the other 3 (A-, B-, Z-) should be connected to 3 more interrupt pins.

# Answer
> 0 votes
You have already found out, how the encoder works (basically like any other rotary encoder, only with more outputs for different angle values). That is great work.

You get a value 4 times as big because of 2 little mistakes:

1. When you use `attachInterrupt()`, you set it to trigger on a `CHANGE` of the line. One pulse consists of 2 changes (for example LOW to HIGH and then HIGH to LOW). So the interrupt get's triggered twice per encoder pulse. That's a factor of 2 for the resulting value.
2. You attach an interrupt to both of the lines, but both lines output one pulse per one encoder tick. So the value get's incremented twice per tick, what means another factor of 2. You only need an interrupt on one of the lines. The other line is only there to indicate the direction of the rotation. When the interrupt for the first line triggers, you should check the value of the second line. If it is HIGH, the encoder is rotating in one direction. If it is LOW, it rotates in the oposite direction. The lines are internally connected to little buttons/switches, that are fixed to the casing with a little offset between then. They get activated by little nubs, that are connected to the axis. Depending on from which direction the nub comes during a rotation, the first or the second button/switch will get activated first. A little after that, also the second switch will activate. So you can monitor one line, and if a pulse starts on it, you check if there already is a pulse on the other line. If yes, the other line was activated first.

So all in all this results in the factor 4 in the encoder results.

---

Note, that your `ParseEncoder()` function is a little redundant and overcomplicated. In the inner if statements you check for some values, that cannot happen in there because of the outer if statement. But this function will reduce itself to simply one if statement (or less, if you use the value directly without if), since with the above, you only need to check the value of 1 line.

---
Tags: rotary-encoder
---


# Question
Title: Can I get the hex file from an Arduino without the .ino code
I have a CNC router table that came into my local makerspace. The board looks like it has some standard parts, but also has some parts I don't recognize. At the heart of it is an Arduino Uno. I would like to get the code from the UNO, as a back up. I will have to do testing on this board, but I don't want to overwrite something I don't have a back up of.

is there a way to get the firmware off of the arduino, without having the ino files that generated it?

(This is a standard function on many other platforms such as PIC, I just don't know how to do it in Arudino. I am assuming the functionality also exists.)

# Answer
Cool I got it using avrdude. $ `avrdude -c arduino -P /dev/ttyUSB0 -b 9600 -p m328p -U flash:r:CNCArdunio.hex:i`

```
> -c the platform (basically)
> -P the port where your harware is.
> -b the baudrate.
> -p the chip architecture.
> -U momory type flash  :r option to read to file  :i option to format into Intel HEX.

```

caveats.Upon closer inspection this is either a very early model UNO, or a cheap clone. It comes up at /dev/ttyUSB0, and required that I press the reset button shortly before sending the avrdude command, else it resulted in

```
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00

```
> 4 votes

---
Tags: arduino-uno, programming, hex
---


title: External Power for MicroServo (SG92R)

text:
# Question
Title: External Power for MicroServo (SG92R)
Why won't my MicroServo run at external 5v power supply? , I've tested my power supply and can light up 1 LED and also run the servo mainly on arduino and it works just fine. Im currently using a computer power supply using the red wire(5v). I'm not very knowledgeable with voltage and stuff and im hoping someone can answer.

and here is my power supply...

I've checked the power supply terminals but nothing is wrong there. Also, i've tried 10k potentiometer to be supplied by it but when i read it in ***serial.begin*** it just reads **"0, 0, 0, 0, 1023, 1023, 1023, 1023"** over and over again. Sorry about the formats im still new.

# Answer
The image you uploaded shown quite clearly that you have not connected the grounds between the Arduino circuit and the servo circuit. In order for it to work, the servo should reference the signal line to ground, currently only PC power supply is providing ground, so the Arduino signal line is floating.

Check out the attached image and connect the GND as shown in dotted yellow line.
> 1 votes

---
Tags: servo
---


# Question
Title: Multiple I2C BREAKOUTS with pull-up resistors doesn't work [UPDATE]
\[UPDATE\] Now it works fine but the as soon as I add the GY-521 module (hardware not software), it starts sending me crapy info

Project uses:

Arduino Pro Mini as brain

FTDI as a programmer

GY-521 gyro/accel

MPL3115A2 baro/altimeter

DS3231 real time clock

Micro SD card adapter to datalog

The GY-521, MPL3115A2 and the DS3231 uses I2C and they are breakout boards so they include pull-up resistors on the board. Now the GY-521 and the MPL3115A2 works fine together but as soon as I add the DS3231, it all freezzes. My code is fine and I'm sure of that.

Now my theory is that all of those pull-up resistors caused some kind of problem in the circuit. I know that normal I2C require 4.7k ohm pull-up resistors. Now I BELIEVE that the GY-521 uses 4.7k pull-up resistors, the MPL3115A2 uses 10k pull-up resistors and the DS3231 also uses 10k pull-up resistors.

I don't know if this setup could work and I would like to know if I can add some external resistors to calm the whole I2C constellation a bit. Note that I do not want to sodder anything to the breakouts nor do I want to modify them.

Here is the code:

Tab1: MAIN

```
  //==================================================

#include <SPI.h>                        //include the SPI library
#include <SD.h>                         //include the SD card library
#include <Wire.h>                       //include I2C library
#include "I2Cdev.h"                     //include another I2C library
#include "Wire.h"                       //include another I2C library (yes, again)
#include "MPU6050_6Axis_MotionApps20.h" //include the MPU6050 library
#include "SparkFunMPL3115A2.h"          //include the MPL3115A2 library
#include <DS3231.h>                     //include the DS3231 library

//==================================================

#define testtest           //*** COMMENT THIS LINE BEFORE UPLOADING OFFICIAL CODE TO FINAL PROJECT ***

#define chipSelect 10      //pin for the CS/SS
#define led 2              //led and/or buzzer

volatile bool mpuInterrupt = false; //just one of those bools

bool ledState     = false; //state of the led and/or buzzer
bool dmpReady     = false; //state of the mpu6050

int yprInt[3];             //gyro data in a integer because the extra precision of the float is total bullshit
int altitude;              //altitude above takeoff point in meters
int altitudeCalibration;   //calibration for the altimeter
int temperature;           //temperature in degrees Celcius

float counter = 0;         //time counter, a somewhat internal clock that starts when the module starts dataloging

uint8_t mpuIntStatus;      //holds actual interrupt status byte from MPU
uint8_t devStatus;         //return status after each device operation (0 = success, !0 = error)
uint8_t fifoBuffer[64];    //FIFO storage buffer

uint16_t packetSize;       //expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;        //count of all bytes currently in FIFO

String day;                //day of the week
String ymd;                //date: year,month,day
String hms;                //time: hour,minute,second

MPU6050 mpu;               //MPU6050 object declaration as mpu
Quaternion q;              //quaternion container
VectorFloat gravity;       //gravity vector

MPL3115A2 myPressure;      //MPL3115A2 object declaration as myPressure
DS3231  rtc(SDA, SCL);     //DS3231 object declaration as rtc

//==================================================

void setup()
{
  generalSetup();

  gyroSetup();
  baroSetup();

  dataSetup();
}

//==================================================

void loop()
{
  gyro();      //read angles
  baro();      //read altitude and temperature
  timeClock(); //read day, date, time

  dataPrint();   //serial print the information

  dataLog();   //write data in sd card

  timer();     //time delay and led flash
}

```

Tab2: SETUP

```
//==================================================

void generalSetup()
{
  Serial.begin(115200); //start serial communication
  Wire.begin();         //start I2C communication
  rtc.begin();          //start DS3231

  pinMode(led, OUTPUT); //led or buzzer; used to easily find a lost device
}

//==================================================

void dmpDataReady() {
  mpuInterrupt = true;
}

void gyroSetup()
{
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
  TWBR = 24;
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
  Fastwire::setup(400, true);
#endif
  //while (!Serial);
  mpu.initialize();
  devStatus = mpu.dmpInitialize();
  mpu.setXGyroOffset(220);
  mpu.setYGyroOffset(76);
  mpu.setZGyroOffset(-85);
  mpu.setZAccelOffset(1788);

  if (devStatus == 0)
  {
    mpu.setDMPEnabled(true);
    attachInterrupt(0, dmpDataReady, RISING);
    mpuIntStatus = mpu.getIntStatus();
    dmpReady = true;
    packetSize = mpu.dmpGetFIFOPacketSize();
  }

  else
  {
    return;
  }
}

//==================================================

void baroSetup()
{
  myPressure.begin();             //start MPL3115A2 communication
  myPressure.setModeAltimeter();
  myPressure.setOversampleRate(7);
  myPressure.enableEventFlags();
  altitudeCalibration = myPressure.readAltitude(); //read altitude
}

//==================================================

void dataSetup()
{
  if (SD.begin());
}

//==================================================

```

Tab3: FUNCTIONS

```
//==================================================

void gyro()
{
  float yprFlo[3]; //gyro data in a float

  mpu.resetFIFO();
  mpuInterrupt = false;
  mpuIntStatus = mpu.getIntStatus();
  fifoCount = mpu.getFIFOCount();

  if (mpuIntStatus & 0x02)
  {
    while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();
    mpu.getFIFOBytes(fifoBuffer, packetSize);
    fifoCount -= packetSize;
    mpu.dmpGetQuaternion(&q, fifoBuffer);
    mpu.dmpGetGravity(&gravity, &q);
    mpu.dmpGetYawPitchRoll(yprFlo, &q, &gravity);

    for (int i = 0; i < 3; i++)
    {
      yprFlo[i] = yprFlo[i] * 180 / M_PI; //simplify the variable for serial printing and dataloging
    }

    for (int i = 0; i < 3; i++)
    {
      yprInt[i] = yprFlo[i]; //changing the variable from a float to a int
    }
  }
}

//==================================================

void baro()
{
  altitude = myPressure.readAltitude() - altitudeCalibration; //read altitude
  temperature = myPressure.readTemp();  //read temperature
}

//==================================================

void dataPrint() //serial print all the data
{
  Serial.print(day);
  Serial.print(" ");
  Serial.print(ymd);
  Serial.print(" -- ");
  Serial.print(hms);
  Serial.print(", ");
  Serial.print(counter);
  Serial.print(", ");
  Serial.print(yprInt[0]);
  Serial.print(", ");
  Serial.print(yprInt[1]);
  Serial.print(", ");
  Serial.print(yprInt[2]);
  Serial.print(", ");
  Serial.print(altitude);
  Serial.print(" ,");
  Serial.print(temperature);
  Serial.println();
}

//==================================================

void dataLog()//wirte all the data in a note file on the sd card
{
  if (altitude > 1) //if the device is higher then 1m, then we sstart recording everything
  {
    File dataFile = SD.open("datalog.txt", FILE_WRITE);

    if (dataFile)
    {
      dataFile.print(day);
      dataFile.print(" ");
      dataFile.print(ymd);
      dataFile.print(" -- ");
      dataFile.print(hms);
      dataFile.print(", ");
      dataFile.print(counter);
      dataFile.print(", ");
      dataFile.print(yprInt[0]);
      dataFile.print(", ");
      dataFile.print(yprInt[1]);
      dataFile.print(", ");
      dataFile.print(yprInt[2]);
      dataFile.print(", ");
      dataFile.print(altitude);
      dataFile.print(" ,");
      dataFile.print(temperature);
      dataFile.println();
      dataFile.close();
    }
  }
}

//==================================================

void timeClock()
{
  day = rtc.getDOWStr();
  ymd = rtc.getDateStr();
  hms = rtc.getTimeStr();
}

//==================================================

void timer()
{
  counter = counter + 0.5;

  #ifndef testtest
  ledState = !ledState;
  digitalWrite(led, ledState);
  #endif

  delay(500);
}

//==================================================

```

# Answer
In fact the MPU-6050 on the GY521 and the DS3231 both use I2C address 0x68. Had you looked at the source of the header files you included for each, this would have been apparent.

By consulting the data sheet for each chip you will likely find a way to either change the I2C address by changing a configuration pin, or else to potentially enable/disable the chip by changing one with a GPIO. This will, however, likely require surgical modification of the carrier board.

You could also move whichever device you expect to access least to a distinct "soft" I2C bus bit-banged on other GPIO pins. No endorsment is implied, but the the first such library that came up in a web search was:

http://playground.arduino.cc/Main/SoftwareI2CLibrary

you can likely find other options for yourself, or can potentially create your own.

There are also other chips in the family of the MPU-6050 which speak SPI instead of or as well as I2C, however these tend to be more expensive.
> 1 votes

# Answer
According to my calculations the total pull-up is:

```
1 / (1/10 + 1/10 + 1/4.7) = 2.423 k

```

As I show on my page about I2C a 2.2 k pull-up resistor gives a reasonably good signal:

Thus I don't think the resistors are the issue. And I don't see how adding more would "calm the whole I2C constellation a bit".
> 2 votes

# Answer
When additional resistors are added in parallel, which is what is going on when you add new I2C devices to the I2C bus, the overall resistor is lowered. This could cause a problem with devices that cannot provide enough current with a low pull-up resistance. Hence, the device will not function well when the pull-up resistance is lower than a specific value. To fix the problem, I recommend removing all parallel pull-up resistors and just keep one at each line to achieve a good resistor value of approximately 4.7 k-ohms.
> 2 votes

---
Tags: sensors, i2c, arduino-pro-mini, resistor
---


# Question
Title: Push button unexpected increment/decrement. I'm using attachInterrupt
I'm new to Arduino and need assistance from knowledgeable people. I'm having a problem with my code, which allows the user to increase or decrease the number by pressing buttons. From time to time, the number does not change by one, but by two or three. This occurs on a sporadic basis. This is known as "bouncing." I googled "attachInterrupt debounce" in vain, but I couldn't find a suitable solution. My code is here.

```
int digit_state = 0;
void increment(void){
  digit_state = digit_state + 1;
  }
void decrement(void){
  digit_state = digit_state - 1;
  }
String user_input = "";
String password = "3452";
int enterbutton = 11;
int increment_button = 2;
int decrement_button = 3;
int counter = 0;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(enterbutton,INPUT);
  attachInterrupt(digitalPinToInterrupt(increment_button),increment,FALLING);
  attachInterrupt(digitalPinToInterrupt(decrement_button),decrement,FALLING);
}

void loop() {
  // put your main code here, to run repeatedly:
  lastButtonState = reading;
  while(counter<=3){
    delay(500);
    Serial.println(digit_state);
    if(digitalRead(enterbutton)==LOW){
      user_input = user_input + digit_state;
      Serial.println("Saved input so far is "+user_input);
      if(user_input == password){
        Serial.println("検証できた");
      }
      delay(500);
      digit_state = 0;
      counter++;
  }
}
}

```

As the user presses, I need to stop it from bouncing and get an accurate password all the time.

# Answer
First: It is not necessary to use interrupts for buttons, because when humans press buttons they will be at least actived for about 100ms, which is very slow for a microcontroller. You would just need to rewrite your code to be non-blocking (for example by ditching all `delay()` calls and instead use `millis()` like in the `BlinkWithoutDelay` example, that comes with the Arduino IDE). Then you can also use existing libraries for debouncing like Bounce2.

---

A very simple approach would be to set a timeout after each button press, where no new button press will be registrated, like 10ms (should be plenty enough for debouncing, though you can test for your setup yourself). This can be done with `millis()` by maintaining a timestamp of the last button press:

```
#define DEBOUNCE_TIME  10
volatile unsigned long button_press_timestamp = 0;

void increment(void){
  if(millis()-button_press_timestamp > DEBOUNCE_TIME){
      digit_state = digit_state + 1;
      button_press_timestamp = millis();
  }
}

```

First in global scope we are defining our debounce time and a variable for holding the timestamp, when the last button press was registered. In the ISR (here only `increment()` as example) we then check the difference between this timestamp and the current time. If that is bigger than the debounce time we execute the buttons action (incrementing in this case). Then we update the timestamp to the current time.

On a button press the first falling edge will trigger the button action. Any falling edges from the bouncing will appear inside the debounce time and thus will be ignored (the ISR gets called but the code in the if statement is not executed).

This debouncing principle is not perfect but easy to implement and it might be enough for you.
> 1 votes

---
Tags: interrupt, debounce
---


# Question
Title: How to send data from esp-01 Wi-Fi module to arduino
The L1 is the value i will get from firebase database, but now i wanna send the value that i receive in realtime database to arduino to on LED, how to solve? any suggestion? which mean when arduino receive value 1 from firebase then led will on

ESP8266 code :

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

// Set these to run
#define FIREBASE_HOST ""
#define FIREBASE_AUTH ""
#define WIFI_SSID "Home "
#define WIFI_PASSWORD ""

int value1;

void setup() {
  //Initializes the serial connection at 9600 get sensor data from arduino.
  Serial.begin(9600);

  delay(1000);

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
  }

  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
  Firebase.setInt("L1",0);
}

void loop()
{
  while(Serial.available())
  {
        value1 =  Firebase.getString("L1").toInt();
  }

  delay(1000);
}

```

Arduino code:

```
#define LED 13;

int value1;

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

void loop()
{
  if (value1 == 1)
  {
     digitalWrite(LED, HIGH);
  }
}

```

# Answer
> 1 votes
ESP8266 code :

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

// Set these to run
#define FIREBASE_HOST ""
#define FIREBASE_AUTH ""
#define WIFI_SSID "Home "
#define WIFI_PASSWORD ""

int value1;
String string_value;
void setup() {
  //Initializes the serial connection at 9600 get sensor data from arduino.
  Serial.begin(9600);

  delay(1000);

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
  }

  Firebase.begin(FIREBASE_HOST, FIREBASE_AUTH);
  Firebase.setInt("L1",0);
}

void loop()
{

        value1 =  Firebase.getString("L1").toInt();
        string_value = String(value1);
        Serial.print(string_value);

  delay(1000);
}

```

Arduino code:

```
    #define LED 13

int value1;
String data;

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

void loop()
{

  bool Sr =false;

  while(Serial.available()){

        data=Serial.readString();
        value1 =data.toInt();
        Sr=true;

    }

    delay(500);

    if(Sr){

        if (value1 == 1)
        {
           digitalWrite(LED, HIGH);
        }else if(value1 == 0){

            digitalWrite(LED, LOW);
          }
   }
}

```

For More details:

https://www.youtube.com/watch?v=ji71cHaGW8w

# Answer
> 0 votes
Your ESP needs to

* receive data from Firebase over WiFi;
* send the received data (or the useful part of it) to the Arduino, over its serial port.

Your Arduino needs to:

* watch its own serial port for data becoming available;
* read the data;
* decide whether turn the LED on or off.

Your loop() code on the Esp is watching its serial port, but from your description, it shouldn't expect any data from its serial port - that is connected to the Arduino. You need to watch for data arriving *via WiFi* instead.

Your Arduino code is testing the variable `value` but value never gets set to anything. You should set it according to what you receive from the Esp.

Also, since I'm not familiar with Firebase, does the Esp need to tell Firebase each time it wants new data? Or does Firebase send data at intervals without you having to ask for it? If it's the former, your Esp will need code to ask for the data and wait for it to arrive before it can send it on to the Arduino.

---
Tags: arduino-uno, esp8266
---