body:
This is a follow up from a previous question. I have one Nano working perfectly (I think) (Nano A) and another one (Nano B) which seems to be working but has no bootloader. So I am trying to use Nano-A as an ISP programmer to burn the bootloader into Nano-B. I am pretty confident with my hardware and Arduino IDE setup. See previous question for the details; <https://arduino.stackexchange.com/questions/79743/problems-uploading-with-a-new-nano>

I have pasted below two screen sessions. The first shows the Arduino IDE Log when I (unsuccesfully) try to run "Burn Bootloader" - IT *almost* works! (but not quite). - So I beleive that there is not too much wrong with my setup.

The second session is me using running avrdude in "terminal" mode from a Windows command prompt. I have used individual "send" commands to send the ISP instructions required to programme a single word into bootloader flash memory and this all seems to work OK. So I don't understand why avrdude is not working when invoked by the IDE.

**Arduino IDE Log (lengthy)**

```
C:\Users\--\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/bin/avrdude -CC:\Users\--\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf -v -patmega328p -cstk500v1 -PCOM8 -b19200 -e -Ulock:w:0x3F:m -Uefuse:w:0xFD:m -Uhfuse:w:0xDA:m -Ulfuse:w:0xFF:m

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

         System wide configuration file is "C:\Users\--\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf"

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

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

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

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.11s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: erasing chip
avrdude: reading input file "0x3F"
avrdude: writing lock (1 bytes):

Writing | ################################################## | 100% 0.04s

avrdude: 1 bytes of lock written
avrdude: verifying lock memory against 0x3F:
avrdude: load data lock data from input file 0x3F:
avrdude: input file 0x3F contains 1 bytes
avrdude: reading on-chip lock data:

Reading | ################################################## | 100% 0.04s

avrdude: verifying ...
avrdude: 1 bytes of lock verified
avrdude: reading input file "0xFD"
avrdude: writing efuse (1 bytes):

Writing | ################################################## | 100% 0.04s

avrdude: 1 bytes of efuse written
avrdude: verifying efuse memory against 0xFD:
avrdude: load data efuse data from input file 0xFD:
avrdude: input file 0xFD contains 1 bytes
avrdude: reading on-chip efuse data:

Reading | ################################################## | 100% 0.04s

avrdude: verifying ...
avrdude: 1 bytes of efuse verified
avrdude: reading input file "0xDA"
avrdude: writing hfuse (1 bytes):

Writing | ################################################## | 100% 0.04s

avrdude: 1 bytes of hfuse written
avrdude: verifying hfuse memory against 0xDA:
avrdude: load data hfuse data from input file 0xDA:
avrdude: input file 0xDA contains 1 bytes
avrdude: reading on-chip hfuse data:

Reading | ################################################## | 100% 0.04s

avrdude: verifying ...
avrdude: 1 bytes of hfuse verified
avrdude: reading input file "0xFF"
avrdude: writing lfuse (1 bytes):

Writing | ################################################## | 100% 0.04s

avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0xFF:
avrdude: load data lfuse data from input file 0xFF:
avrdude: input file 0xFF contains 1 bytes
avrdude: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.04s

avrdude: verifying ...
avrdude: 1 bytes of lfuse verified

avrdude done.  Thank you.

C:\Users\--\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/bin/avrdude -CC:\Users\--\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf -v -patmega328p -cstk500v1 -PCOM8 -b19200 -Uflash:w:C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\arduino\avr/bootloaders/optiboot/optiboot_atmega328.hex:i -Ulock:w:0x0F:m

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

         System wide configuration file is "C:\Users\--\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf"

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

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

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

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.11s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\arduino\avr/bootloaders/optiboot/optiboot_atmega328.hex"
avrdude: writing flash (32768 bytes):

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

avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_cmd(): programmer is out of sync
avrdude: stk500_cmd(): programmer is out of sync
avrdude: 32768 bytes of flash written
avrdude: verifying flash memory against C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\arduino\avr/bootloaders/optiboot/optiboot_atmega328.hex:
avrdude: load data flash data from input file C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\arduino\avr/bootloaders/optiboot/optiboot_atmega328.hex:
avrdude: input file C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\arduino\avr/bootloaders/optiboot/optiboot_atmega328.hex contains 32768 bytes
avrdude: reading on-chip flash data:

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

avrdude: loadaddr(): (b) protocol error, expect=0x14, resp=0xc0

avrdude: stk500_paged_load(): (a) protocol error, expect=0x14, resp=0x10
avrdude: stk500_cmd(): protocol error
avr_read(): error reading address 0x7e00
    read operation not supported for memory "flash"
avrdude: failed to read all of flash memory, rc=-2
avrdude: stk500_disable(): protocol error, expect=0x14, resp=0xd1

avrdude done.  Thank you.

Error while burning bootloader.
```

**avrdude session (short)**

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

Note that when writing to the bootloader flash, using the "send" instruction, you have to supply the address as a "word" - i.e. 16bit address - hence 0x3C00. When usning the "read" instruction, the address is a "byte" (8 bit) address, hence 0x7800 - this is the same address.

Update: I have now managed to upload my original sketch to the application area of flash on this Nano using the "Sketch->upload using programmer" menu option of the Arduino IDE. So I do now have a useable Nano but I have still not solved my original problem i.e. this  Nano still does not have a bootloader. I would like to fix this problem becaue I am sure that I will want to update/modify my app int the future. So there is now an ancilliary question - i.e. is it possible to burn a  bootloader without erasing a pre-existing application? - Answer, I think is no because maybe you have to do a chip erase before writing to the bootloader area?

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

title: Can't get "Burn Bootloader" working - Arduino Nano

Answers: 1

body:
Yay! - I now have a fully working Nano with new bootloader and application loaded using this.

I have done so much that I'm not sure what the original problem was but the final change was modifying the "programmers.txt" file such that "Arduino as ISP" entry was changed as follows;

    Original line;
    arduinoasisp.protocol=stk500v1

    Changed to;
    arduinoasisp.protocol=arduino

I did this because I noticed that the menu option "Upload using programmer" (which worked) invoked avrdude with the parameter "-c arduino" whereas the "burn bootloader" option used "-c stk500v1" (which was not working).

I can't pretened that I fully understand but I'm happy that this now works and that I have now learnt enough to know where to start looking if I get similar problems in the future.

I should also add that I would never have got here without the help of @timemage - who has helped a lot - many many thanks


body:
I figured out how to install the sound onto the card from this site

<https://github.com/charliegerard/dev-notes/blob/master/arduino/wavFilesWithoutSdCard.md>

It says I need to use pin 11 on the Uno but would pin 11 on the nano work or not? I am getting these boards.

<https://www.amazon.com/gp/product/B0713XK923/ref=ox_sc_act_title_3?smid=A2WWHQ25ENKVJ1&psc=1>

Also, does anyone have good speaker suggestions, I'm going with these right now(<https://www.amazon.com/CQRobot-JST-PH2-0-Interface-Electronic-Projects/dp/B0738NLFTG/ref=sr_1_6?dchild=1&keywords=speakers+arduino]\&qid=1607285501&sr=8-6>)

I'm not sure if I'm giving enough information so just tell me if I need to provide you with more information.

title: I am looking into putting sound files onto an Arduino Nano without a microSD card

Answers: 1

body:
Uno and Nano uses the same Atmel MCU, so pin 11 is the same on both.

And a for the speakers, Arduino CAN'T driver 8ohms load! You need a amplifier.


body:
I'm trying to repurpose an RGB LED (pictured) and use an Arduino board I've just gotten to reprogram the lights. I'm very new to electronics engineering and I don't really know how to get started. How would I connect it to the Arduino? What kind of wire(s) would be best for soldering this to as well as connecting to the Arduino? Can this be programmed like any other LED?

Images:
 https://i.stack.imgur.com/u14Bd.jpg
 https://i.stack.imgur.com/2inQB.jpg

title: Connect RGB LED board to Arduino?

Answers: 2

body:
Connect each of the 3 "L" wires to 3 separate digital IO pins of an arduino e.g. D8, D9, D10 via a resistor say 470 ohms but the value is not too critical. Connect VDD to the arduino +5v.

Use the arduino IDE write a sketch that configures pins 8 9 and 10 as outputs and then see what happens when you send these pins HIGH or LOW. Theres lots more you can do. Good luck.

body:
Given that the pin is labeled VDD, it's likely that the LEDs are common anode. (You'd hook the VDD pin to a positive voltage, and then connect the other pins to ground in order to light them.)

You really need to know the specs of the LEDs in order to calculate the size of the current limiting resistors.

Say your LEDs have a 1.2v forward voltage and can take 20 mA of current (.02 amps)

You'd use the formula R = (supply_voltage - LED_voltage)/current

so R = (5-1.2)/.020  = 190 Ω. Use the next higher value. (220 Ω for 20% resistors, the cheapest/most common kind you're likely to have access to.)

Try hooking each of the LEDs through a 220 Ω resistor to ground and seeing what you get. (Note that different colors of LEDs can have different forward voltages, so the forward voltage you use in the above calculation might be different for each LED.) If it barely lights, move down to the next-lower resistor value and try again. (150 Ω for 20% resistors.) If it's crazy-bright, or gets warm to the touch, use the next higher resistor value.

You'd then control the LEDs using PWM pins on your Arduino, and vary the duty cycle on 3 different output pins to vary the apparent brightness of the different colored LEDs. Note that since these LEDS appear to be common **anode** (Common power connection, and you switch the grounds to turn them on and off) the PWM values will be reversed. Setting a PWM pin to 0 will make that LED burn the brightest, and setting it to 255 will turn it off. That's because at 0, the pin is at 5V 0% of the time and connected to ground (which lights it) 100% of the time.


body:
I'm wondering whether it is possible to wire multiple buck converters with different voltage requirements and amperage draws to the same power source (this idea is for controlling a radio-controlled boat). Going off other related questions this seems to be possible ([1][1], [2][2]).

My background is in programming, not electronics, so the terminology is difficult for me to understand. I'm getting a grasp on voltage and amperage. My problem is always understanding how electricity can be "split" into different modules. In my understanding, this below would be a parallel circuit and that should be fine.

 1. Are there any gotchas to consider with this type of circuit, or is this the totally normal way of doing things (eg. like wiring a house out of a breaker box)?
 2. Is there a better way to do this?
 3. This won't cause a short circuit, right?

[![SLA battery powering different voltages diagram][3]][3]

  [1]: https://electronics.stackexchange.com/questions/260312/are-there-limits-for-the-number-of-buck-converters-i-can-run-off-a-single-power
  [2]: https://electronics.stackexchange.com/questions/481666/using-buck-converter-and-ldo-from-the-same-power-source
  [3]: https://i.stack.imgur.com/Lmmo3.png

title: Different Output Voltages from Same Source?

Answers: 1

body:
> Are there any gotchas to consider with this type of circuit, or is this the totally normal way of doing things (eg. like wiring a house out of a breaker box)?

That's a perfectly normal way of wiring it.

> Is there a better way to do this?

No, it's how I'd do it.

> This won't cause a short circuit, right?

Not intentionally, no. However it's always good to add a fuse or two to protect everything just in case anything untoward should happen. Especially where water is concerned.


body:
I try to use [Plotter](https://github.com/devinaconley/arduino-plotter) to plot some data from my Adafruit Circuitplayground board, but the listener is kept showing "Scanning serial ports..." and not displaying any plot (as shown below in the picture).
[![enter image description here][1]][1]

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

I have java 1.8.0_271 installed (in order to run listener) and I put the listener folder under the same directory as the Arduino code file (though I'm not sure if there's a requirement of where to put the listener folder). Arduino is the latest version. Code is copied from the sample code of the Plotter library

title: listener for Plotter library doesn't work

Answers: 0


body:
I am new to Arduino programming, after days and nights trying to use array and for loop, and googling a lot of articles, I am still unable to find how to store each weighing output value from `int Sampling()` to be executed by the respective servo in sequence order.

If you have any clue to share and help me, I'll be very happy.

Below is my base code:

```c++
#include <HX711.h>
///////////////////////////////////////////////////////////////////////
#define calibration_factor -251
#define LOADCELL_DOUT_PIN 7   // data
#define LOADCELL_SCK_PIN 8    // sck
////////////////////////////////////////////////////////////////////////
HX711 scale;
////////////////////////////////////////////////////////////////////////
int servo1 = 12;
int servo2 = 13;
int proxiPin1 = 2;
int proxiPin2 = 3;
////////////////////////////////////////////////////////////////////////
int toggleState = 0;
int proxiState1 = 1;
int proxiState2 = 1;
////////////////////////////////////////////////////////////////////////
int weight;
int weightFinal;
////////////////////////////////////////////////////////////////////////
void setup()
{
  Serial.begin(9600);
  scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
  scale.set_scale(calibration_factor);
  scale.tare();

  pinMode(servo1, OUTPUT); // simulating servo1
  pinMode(servo2, OUTPUT); // simulating servo2
  pinMode(proxiPin1, INPUT_PULLUP); // proximity
  pinMode(proxiPin2, INPUT_PULLUP); // proximity

}
/////////////////////////////////////////////////////////////////////////
void loop()
{
  Serial.print(Sampling());
  Serial.print(" gram");
  Serial.println();
  ///////////////////////////////////////////////////////////////////////
  if ( weightFinal == 10 )
  {
    toggleState = true;
    servo10gr();
  }

  if ( weightFinal == 20 )
  {
    toggleState = true;
    servo20gr();
  }
}
////////////////////////////////////////////////////////////////////////
int Sampling()
{
  int weight = scale.get_units();

  if (weight >= 10  && weight< 20)
  {
    weightFinal = 10;
  }

  else if (weight >= 20  && weight < 30)
  {
    weightFinal = 20;
  }

  return weight;
}
/////////////////////////////////////////////////////////////////////////
int servo10gr()
{
  proxiState1 = digitalRead(proxiPin1);
  if ( proxiState1 == 0 && toggleState == true )
  {
    digitalWrite(servo1, HIGH);  //Simulating servo signal Pin//
    delay(500);
    digitalWrite(servo1, LOW);

    toggleState = false;
    weightFinal=0;
  }
}
/////////////////////////////////////////////////////////////////////////
int servo20gr()
{
  proxiState2 = digitalRead(proxiPin2);
  if ( proxiState2 == 0 && toggleState == true )
  {
    digitalWrite(servo2, HIGH);    //Simulating servo signal Pin//
    delay(500);
    digitalWrite(servo2, LOW);

    toggleState = false;
    weightFinal=0;
  }
}
```

title: Storing and sequencing output value (Arduino)

Answers: 1

body:
I'm still not entirely sure what you want to achieve, but maybe this will help:

You have a global variable `int weight`, and in `int Sampling()` you create another `int weight = scale.get_units()` which you give a value.

That second variable is only accessible inside of `Sampling()`. If you want to use it elsewhere for storing or in other functions, change:

`int weight = scale.get_units();`

to

`weight = scale.get_units();`

and you can then use `weight` wherever you like in your code, also in `servo10gr()` and `servo20gr()`.

You don't need to store a sequence of `weight`s to drive the servos; you can just use the current weight immediately to drive a servo and then get a new `weight`.

If, however, you want or need to keep a list of `weights` for some reason, there's a bit more work to be done.

There are better ways of going about this, but let's see first if this solves your problem.


body:
I have an ESP8266 Node MCU and am learning to use its wifi capabilities. In my home I have a router provided by my ISP that runs a network we'll call 'network1'. I also have an Eero mesh network that runs in the house, called 'network2'.

When I upload the following minimal example and use network1,
1) my 8266 device connects to network1 (the messages in the serial monitor confirm this) and
2) I can use my phone and laptop to connect to the 8266 - i.e., I can put the IP into my browser and see a webpage telling me 'Hello World'.

However, I have trouble with network2, the Eero network.
1) I *can* connect my 8266 device to network2 (the messages in the serial monitor confirm this)
but
2) I can't connect to the 8266 device with my phone/laptop. (Yes, I switch these over to network2 first.) I put the new IP into my browser and I am told the page is taking too long to respond.

I haven't done anything special with my network1 router; things just worked. With network2, I've tried various settings with my Eero - given the 8266 a static IP address, enabled port forwarding (on port 80) and established a firewall rule for it, but nothing works.

I can run many different programs through network1, and nothing works on the Eero network. Any suggestions on getting things to work?

My minimal working example:

    #include <ESP8266WiFi.h>

    const char* ssid = "network1"; // or 'network2'
    const char* password = "thepassword"; // real password used in code

    WiFiServer server(80); //just pick any port number you like

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

      // Connect to WiFi network
      Serial.print("Connecting to ");
      Serial.println(ssid);

      WiFi.begin(ssid, password);

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

      Serial.println("");
      Serial.println("WiFi connected");

      // Start the server
      server.begin();
      Serial.println("Server started");

      // Print the IP address
      Serial.println(WiFi.localIP());
      //gateway = WiFi.gatewayIP();
      Serial.print("GATEWAY: ");
      Serial.println(WiFi.gatewayIP());

      // print your subnet mask:
      //subnet = WiFi.subnetMask();
      Serial.print("NETMASK: ");
      Serial.println(WiFi.subnetMask());
    }

    void loop() {
      // Check if a client has connected
      WiFiClient client = server.available();
      if (!client) {
        return;
      }

      // Prepare the response
      String s = "HTTP/1.1 200 OK\r\n";
      s += "Content-Type: text/html\r\n\r\n";
      s += "<!DOCTYPE HTML>\r\n\r\n";
      s += "\r\n";
      s+= "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\r\n";
      s+= "<title>ESP Web Server</title>\r\n";
      s+= "\r\n";
      s += "Hello World";
      s += "\n";

      client.flush();

      // Send the response to the client
      client.print(s);
      delay(1);
    }

title: Trouble with ESP8266 on Eero network

Answers: 1

body:
I was able to find an answer though I'm not sure _why_ it works. It comes down to adding `WiFi.mode(WIFI_STA);` in the setup, as in

    void setup() {

      WiFi.mode(WIFI_STA);
      WiFi.begin(ssid, password);
      ...
      }

I was able to replicate success with another file on my ESP8266 device and Eero network as well.


body:
I am trying to send a simple GET/POST request to a dummy end point on https://requestbin.com/. I am using an ESP8266 module. I am using the arduino serial monitor to send these AT commands. I connect to wifi and then use the following AT commands

    AT+CIPSTART="TCP","54.166.71.140 ",443  (the IP address from requestbin)

I then do

    AT+CIPSEND=80

followed by

    GET / HTTP/1.0\r\nHost: fc35001f8ec49962d182320446070d.m.pipedream.net\r\n\r\n

I get the output as follows

    Recv 80 bytes

    SEND OK

    +IPD,272:HTTP/1.1 400 Bad Request
    Server: awselb/2.0
    Date: Mon, 07 Dec 2020 13:28:01 GMT
    Content-Type: text/html
    Content-Length: 122
    Connection: close

    <title>400 Bad Request</title>

400 Bad Request

    CLOSED

Is there problem with the length of CIPSEND or the format of the request itself.

title: GET/POST request via AT Commands

Answers: 0


body:
There is a common anode and common cathode of 7 segments display. But I got an unusual one.

There are 7 pins controlling 4 digits 7 segments.
[![enter image description here][1]][1]

I find the pinout by a multimeter. Basically, each pin can be anode or cathode.
[![enter image description here][2]][2]

My questions:

 1. What is the exact name of this 7 segments display?
 2. How to drive this display by Arduino, any website/sample code?
 3. If I am using the 5V tolerant board, which resistor I need to use? And how is the schematic?

  [1]: https://i.stack.imgur.com/TrzuE.jpg
  [2]: https://i.stack.imgur.com/wVI1i.png

title: Interfacing unusual 4 digits 7 segments display

Answers: 2

body:
1. I don't know. If I had to talk about it, I would say a LED segment display with a matrix layout with a complementary drive.

2. If a pin is used as a cathode, a LOW signal must be applied. If it is used as an anode, a HIGH signal must be applied.

You could define constants for each segments anode and cathode that define a pin number. e.g :

    #define CAT_1A = 2
    #define AN_1A  = 1

and so on. Then if you whant to show segment 1A set CAT_1A to LOW and AN_1A to HIGH.

Of course the whole process is more complicated. You have to define which segments must be light up to show a specific digit. You must show all four digits one by one in a fast loop and so on. But that's the same as you would do for an ordinary LED segment bar. The difference is that you have to configure pin pairs and not single pins.

3. Use your Multimeter to measure the Forward voltage of the segments. If they are red, it should be around 1.8 to 2.4 Volts. Substract this Voltage from 5 Volts. Then devide by 0.02 (20 mA) and you get the Resistor in Ohms. A standard LED is bright enough with about 20 mA.

Example:

    (5V - 1.8V) / 0.02A) = 160 Ohm

Use a resistor of say 100 Ohms at each pin. It is common available and as the current flows always through 2 pins, you have 200 Ohms together.

It is also possible that the LED bar has internal resistors. Try to meassure the resistance beetween to pins.

**Edit**
When I said, "each digit must be shown in a fast loop", I forgot to clearify that, for each digit, the segments must be switched sequentially.

You can do it even more complicated and show all Segments with a common cathode or a common annode at once.   Then you need fewer cycles, but as you use resistors for all pins (see point 3.) this could dim the LEDs remarkably. Also, becaus technically, the forward voltage of different LED may differ, so the some could be brighter the others.

There is also another thing, I did not think of, when I wrote the answer. If you power a segment, say from pin A (+5V) to pin B (GND), you have a resistor (100 Ohms), an LED (minus 1.8 Volts) and a second resitor (100 Ohms) in series. So in an ideal situation the voltage on pin B (also on the second resitor) would by around 1.6 Volts. Pin B is the cathode of the LED segment, but can also be the anode of another segment (S2).  If the cathode of S2 is connected to GND there is a very small chance, that the segment lights up. If you don't see (ghost) lights, all is fine. But if some segments light up (but much darker than the right ones) you have to find a better solution.

body:
This display seems to have 32 addressable LEDs controlled by only
7 pins. Judging from this fact, and from the provided pinout table, it
looks like a [Charlieplexed matrix][charlie].

A typical way to drive this kind of matrix is by looping over the
cathodes. You pull one cathode pin `LOW`, and then pull `HIGH` all the
anodes of the LEDs you want to shine which are connected to this
particular cathode. Wait a few milliseconds, then move to the next
cathode. It is important that all pins that are not involved in lighting
an LED remain in `INPUT` mode.

For example, let's say you want to light all the segments of the first
digit (display an “8”) while keeping everything else off. You first pull
pin 1 `LOW` (first cathode) and pull `HIGH` pins 2–5 (segments F, G, C
and D). Let that shine for a few milliseconds, then put everything to
high impedance (pins to `INPUT`) and move to the next cathode: pin 2
goes `LOW` and pin 1 (segment A) goes `HIGH`. And so on until you have
done all the cathodes.

For the coding part, I would suggest using a 7×7 matrix of booleans
telling whether a particular segment is meant to be lit. The indices of
the array would be row = cathode number and column = anode number. The
array would have the same structure as the pinout table you posted,
except for the fact that the lines and columns would have indices
ranging 0–6 instead of 1–7. This should make it easy to handle
refreshing the display.

Drawing the digits is a bit trickier than with traditional 7-segment
displays, as for each segment you will have to find its coordinates in
the matrix (cathode number and anode number). For this, I would use a
“mapping matrix” that stores the mapping (digit number, segment number)
→ (cathode number, anode number).

Below is a tentative, and untested, implementation of these strategies.
Note that I did not write a function to output a digit, but that should
be easy to implement on top of the `set_segment()` function defined
here. Besides, the question of how to draw a digit once you know how to
control individual segments is the standard 7-segment problem, for which
you should be able to find many tutorials.

Note that this code assumes you drive the display directly, using no
iterface other than current-limiting resistors. This carries the risk of
either overloading the cathode outputs or having the display be too dim,
depending on the current-limiting resistors. You may want to use
transistors for the cathodes, in which case you would have a set of
cathode pins different from the set of anode pins.

```c++
// Arduino pins connected to the display.
const uint8_t display_pins[7] = {2, 3, 4, 5, 6, 7, 8};

// Which segments are lit. Each segment is located in this matrix at
// the coordinates [cathode][anode].
bool segment_lit[7][7];

// Coordinates in the matrix above where a segment can be found.
struct SegmentCoordinates {
    uint8_t cathode;
    uint8_t anode;
};

// segments[digit][segment] gives the coordinates of
// any segment (0 = A) of any digit (0 = 1st digit).
const SegmentCoordinates segments[4][7] = {
// seg: A      B        C       D      E        F       G
    {{1, 0}, {2, 0}, {0, 3}, {0, 4}, {3, 0}, {0, 1}, {0, 2}},
    {{2, 1}, {3, 1}, {1, 4}, {5, 1}, {4, 1}, {1, 2}, {1, 3}},
    {{3, 4}, {4, 2}, {4, 3}, {0, 5}, {2, 5}, {2, 3}, {2, 4}},
    {{5, 6}, {6, 5}, {5, 4}, {3, 5}, {5, 3}, {4, 5}, {6, 4}}
};

// Turn a segment OFF (lit = false) or ON (lit = true).
void set_segment(uint8_t digit, uint8_t segment, bool lit) {
    SegmentCoordinates coordinates = segments[digit][segment];
    segment_lit[coordinates.cathode][coordinates.anode] = lit;
}

void setup(){}

void loop() {
    static uint8_t cathode;  // currently used cathode

    // Set the current cathode to OUTPUT LOW.
    digitalWrite(display_pins[cathode], LOW);
    pinMode(display_pins[cathode], OUTPUT);

    // Set the relevant anodes to OUTPUT HIGH.
    for (int anode = 0; anode < 7; anode++) {
        if (segment_lit[cathode][anode]) {
            digitalWrite(display_pins[anode], HIGH);
            pinMode(display_pins[anode], OUTPUT);
        }
    }

    // Let that shine for a while.
    delay(10);

    // Turn off everything.
    for (int pin = 0; pin < 7; pin++) {
        pinMode(display_pins[pin], INPUT);
    }

    // Move to the next cathode.
    if (++cathode >= 7) cathode = 0;
}
```

I used `delay()` here for simplicity. In production code you would
handdle the timings with `millis()` in a non-blocking fashion, in the
spirit of the “Blink without delay” tutorial.

[charlie]: https://en.wikipedia.org/wiki/Charlieplexing


body:
Q: Is it possible to send data in variables from Arduino to Nextion through SerialPrint? If so, what is the correct syntax?

I have an Arduino Uno connected to a Nextion NX4024T032 and a Sunfounder RC522, with a USB run from my PC into the Uno. I want the Nextion to show the name associated with an RFID card from simple if/then statements in the .ino file.

I created what I thought was a simple set of .ino and .tft files to test the Nextion updating from data sent from the Arduino by serial print. I have confirmed in Serial Monitor on the PC that the RFID reader is functioning and that the Uno is sending out the information I am asking it to print. But the Nextion is not changing text to match what I am trying to send it. It just displays the value entered for .txt in the HMI editor.

I am trying to do this without nextion libraries.

Pinout for the RC522 is as in the .ino below (9-13); plus GND and 3.3V on the Uno.

Pinout for the Nextion is Nextion TX to Uno 1, Nextion RX to Uno 0, plus GND and 5V on the Uno.

Here's the .ino:

    /*
     *-----------------------------------------------------
     * Aggiunti pin per arduino Mega
     * add pin configuration for arduino mega
     * http://mac86project.altervista.org/
     ---------------------------------------------------Nicola Coppola
     * Pin layout should be as follows:
     * Signal     Pin              Pin               Pin
     *            Arduino Uno      Arduino Mega      MFRC522 board
     * ------------------------------------------------------------
     * Reset      9                5                 RST
     * SPI SS     10               53                SDA
     * SPI MOSI   11               51                MOSI
     * SPI MISO   12               50                MISO
     * SPI SCK    13               52                SCK
     */

    #include <SPI.h>
    #include <MFRC522.h>

    #define SS_PIN 10
    #define RST_PIN 9
    MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.

    void setup() {
        Serial.begin(9600); // Initialize serial communications with the PC
        SPI.begin();            // Init SPI bus
        mfrc522.PCD_Init(); // Init MFRC522 card
        Serial.println("Scan PICC to see UID and type...");
    }

    void loop() {

//condensed to remove RFID code

      if (UID_string == "4294935680")
      {
        Serial.println("va0.txt=\"Maia\"");
      }

      if (UID_string == "31615")
      {
        Serial.println("va0.txt=\"Claire\"");
      }

      if (UID_string == "24498")
      {
        Serial.println("va0.txt=\"Jack\"");
      }
    }

The .tft I loaded to the Nextion using an SD card is just a text box (t0) on page0, a timer event and a value. The timer should update t0.txt on the display to equal most recent va0.txt in the serial print every 400 ms.

![tm0](https://drive.google.com/file/d/1CTKEgiSgytUblGXZQ-42rlLTxnppg0eK/view?usp=sharing)

![va0](https://drive.google.com/file/d/11kXR_Xjwrp6KINmOdk05iIZweeBiPEJK/view?usp=sharing)

![to](https://drive.google.com/file/d/1ln_rWAmwujHiTM20LhtTH0r5MXh47eIc/view?usp=sharing)

UPDATE:

While trying to understand syntax for commands to send from Arduino Uno to Nextion, I came across directions for sending data a character at a time. So, a very new version below, with all RFID parts removed.

     * Pin layout should be as follows:
     * Signal     Pin              Pin               Pin
     *            Arduino Uno      Arduino Mega      MFRC522 board
     * ------------------------------------------------------------
     * Reset      9                5                 RST
     * SPI SS     10               53                SDA
     * SPI MOSI   11               51                MOSI
     * SPI MISO   12               50                MISO
     * SPI SCK    13               52                SCK
     */

    #include <SPI.h>
    #include <SoftwareSerial.h>
    #define SS_PIN 10
    #define RST_PIN 9
    SoftwareSerial mySerial(0,1);

    void setup() {
        Serial.begin(9600); // Initialize serial communications with the PC
        SPI.begin();            // Init SPI bus

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

      Serial.println("Serial On"); //Print this messages when the serial port is connected
      mySerial.begin(9600); // set the data rate for the SoftwareSerial port

    }

    //NOTE:Credit to RamjetX : http://forum.arduino.cc/index.php?topic=89143.0

    void writeString(String stringData) { // Used to serially push out a String with Serial.write()

      for (int i = 0; i < stringData.length(); i++)
      {
        mySerial.write(stringData[i]);   // Push each char 1 by 1 on each loop pass
      }

      mySerial.write(0xff); //We need to write the 3 ending bits to the Nextion as well
      mySerial.write(0xff); //it will tell the Nextion that this is the end of what we want to send.
      mySerial.write(0xff);

    } // end writeString function

    void loop() {
      String sendThis = "";
      sendThis = "t0.txt=\"working\""; //Declare and initialise the string we will send

      delay(300); //

      writeString(sendThis); // Use a function to write the message character by character to the Nextion because
      mySerial.write(sendThis) gives you an error due to a datatype mismatch*/
    }

Conclusion: The SerialPrintln() statements still send text to the serial monitor, but mySerial.write does not show in the serial monitor and the Nextion screen still does not update to show "working" as passed in t0.txt .

title: Nextion won't update text using data passed in Arduino Uno serial print

Answers: 0


body:
I'm trying to use an Arduino to control my [Bionaire window fan][1]. I followed several guides to build an IR receiver circuit to record the patterns sent by the remote for its five buttons [![Fan Remote][2]][2]. From there, I've tried both an IR transmitter circuit with IRSendRaw and a separate Raspberry Pi circuit using an IR transceiver hat and LIRC [![enter image description here][3]][3], but the fan does not seem to pick up either. I've verified that the Pi receiver recognizes the commands from the Arduino transmitter circuit just as it does from the fan's actual remote and vice-versa, but even if I put the fan directly against the IR LED, it does not respond to any of the commands from the circuit.

What else might I need to do to make this work properly? As an alternative, what would be the best way to go about directly activating the 'buttons' on the remote circuit board pictured above?

Thanks in advance for your help

For future refernece, these are the signals I recorded for the remote, which match up with [this post on electronics stackexchange][4].

    power: 4E87E0AB
    1300 -400 1300 -350 450 -1200 1300 -400 1300 -350 1300 -400 450 -1200 500 -1200 450 -1200 1300 -400 1300 -350 450
    temp_up: 4EA240AE
    1300 -400 1300 -350 450 -1200 1300 -400 1300 -350 1300 -400 450 -1200 450 -1250 450 -1200 450 -1250 1300 -350 1300
    temp_down: 1D2FEFF6
    1300 -400 1300 -350 450 -1250 1300 -350 1300 -350 500 -1200 1300 -350 500 -1200 450 -1200 500 -1200 450 -1200 450
    mode: 39D41DC6
    1300 -350 1300 -400 450 -1200 1300 -350 1300 -400 450 -1200 500 -1200 1300 -350 500 -1200 450 -1200 450 -1250 450
    air_flow: E0984BB6
    1300 -400 1300 -350 500 -1200 1300 -350 1300 -400 450 -1200 450 -1250 450 -1200 1300 -350 500 -1200 450 -1200 500

This is the sketch I'm trying to use to transmit data (just a modified version of the send raw demo from the library). Note that I also tried with only 23 items in the array (as originally recorded), but that made no difference:

```
#include <IRremote.h>

IRsend irsend;

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

}

void loop() {
  int khz = 38; // 38kHz carrier frequency for the NEC protocol
  Serial.println("Sending power");
  unsigned int irSignal[] = {1300,350, 1300,350, 500,1200, 1300,350, 1300,400, 1300,350, 450,1250, 450,1200, 450,1200, 1300,400, 1300,350, 500, 1200};
  irsend.sendRaw(irSignal, 24, khz); //Note the approach used to automatically calculate the size of the array.

  delay(1000); //In this example, the signal will be repeated every 5 seconds, approximately.
}
```

**EDIT** to show that I seem to be able to replicate the real signal.

In the following output from the IRecvDump2 example, the top two signal dumps are from the real remote and the bottom two are from my RPi sending the recorded signal. They're very slightly different, but seem (to me) to be within the variation of the recording of the true signal anyway.

What else could I be missing? Could there be some brightness threshold such that even holding the Pi directly up to (i.e. touching) the fan receiver wouldn't work? Some other sort of wake-up signal that for whatever reason the Arduino isn't recording/receiving?

```
Encoding  : UNKNOWN
Code      : 4E87E0AB (32 bits)
Timing[23]:
     +1300, - 400     +1300, - 350     + 450, -1200     +1350, - 350
     +1300, - 350     +1300, - 400     + 450, -1200     + 500, -1200
     + 450, -1200     +1300, - 400     +1250, - 400     + 450
unsigned int  rawData[23] = {1300,400, 1300,350, 450,1200, 1350,350, 1300,350, 1300,400, 450,1200, 500,1200, 450,1200, 1300,400, 1250,400, 450};  // UNKNOWN 4E87E0AB

Encoding  : UNKNOWN
Code      : 4E87E0AB (32 bits)
Timing[23]:
     +1300, - 400     +1300, - 350     + 450, -1250     +1300, - 350
     +1300, - 400     +1300, - 350     + 450, -1200     + 500, -1200
     + 450, -1200     +1300, - 400     +1300, - 350     + 450
unsigned int  rawData[23] = {1300,400, 1300,350, 450,1250, 1300,350, 1300,400, 1300,350, 450,1200, 500,1200, 450,1200, 1300,400, 1300,350, 450};  // UNKNOWN 4E87E0AB

Encoding  : UNKNOWN
Code      : 4E87E0AB (32 bits)
Timing[23]:
     +1350, - 350     +1300, - 350     + 450, -1200     +1300, - 350
     +1300, - 350     +1300, - 400     + 450, -1200     + 450, -1200
     + 450, -1200     +1350, - 350     +1300, - 350     + 450
unsigned int  rawData[23] = {1350,350, 1300,350, 450,1200, 1300,350, 1300,350, 1300,400, 450,1200, 450,1200, 450,1200, 1350,350, 1300,350, 450};  // UNKNOWN 4E87E0AB

Encoding  : UNKNOWN
Code      : 4E87E0AB (32 bits)
Timing[23]:
     +1350, - 300     +1350, - 350     + 450, -1200     +1300, - 350
     +1300, - 350     +1350, - 350     + 450, -1200     + 450, -1200
     + 450, -1200     +1300, - 350     +1350, - 350     + 450
unsigned int  rawData[23] = {1350,300, 1350,350, 450,1200, 1300,350, 1300,350, 1350,350, 450,1200, 450,1200, 450,1200, 1300,350, 1350,350, 450};  // UNKNOWN 4E87E0AB
```

  [1]: https://www.costco.com/Bionaire-Twin-Window-Fan.product.100110337.html
  [2]: https://i.stack.imgur.com/ItdkL.jpg
  [3]: https://i.stack.imgur.com/UvviG.jpg
  [4]: https://electronics.stackexchange.com/questions/494863/what-ir-protocol-is-this

title: Unable to control fan with IR circuit despite capturing and reproducing the IR transmissions

Answers: 1

body: Interesting question with a lot of paths. I know nothing about your controller but in working with IR remotes in the past I found almost all IR remotes use the infrared frequency range (300 GHz - 400 GHz). This range should not be confused with the modulation rate (carrier frequency) of the remote control. The remote control codes are sent to the receiver using the modulation rate. The modulation rate for the remotes and set top boxes is between 36 kHz and 60 kHz, typically 36 kHz to 39kHz. Try this link it may be a bit redundant but it may help. http://www.pehratek.com/documents/FAQ-Infrared-Light-Control.pdf


body:
I am using the AnalogBinLogger from the SdFat example library. I  am using it to record 8 analog channels at 5kHz! which is amazing (thank you SdFat).

Is it possible to include a separate column to provide a time-stamp in microseconds for when the samples were recorded? Or will this impair the speed at which I can log data?

Or; how reliable is the sample rate? To what degree of confidence can I assume that the sketch executes (in my case) every 200 microseconds?

I'm performing frequency analysis on the data so knowing when the data is captured or if there is any drift or skew is important to me.

Thank you in advance Arduino Crew!

...appended...
To answer @jsotola:
The sketch I am using (see below) comes with the SdFat library, which is beyond my basic understanding of code. I can write a for loop and an if statement but the stuff that goes on in this sketch is levels above where I am at right now. Trust me, if I could've I would've.

To answer @Gerben:
The 5kHz sampling rate is the default sampling rate that comes with the example sketch. As long as I can be confident that the samples are taken every 200us then I wont need the timestamp but I don't know how confident I can be or how to write a timestamp into the code.

``````````````````````````````````````````````````````````````````````
/**
 * This program logs data from the Arduino ADC to a binary file.
 *
 * Samples are logged at regular intervals. Each Sample consists of the ADC
 * values for the analog pins defined in the PIN_LIST array.  The pins numbers
 * may be in any order.
 *
 * Edit the configuration constants below to set the sample pins, sample rate,
 * and other configuration values.
 *
 * If your SD card has a long write latency, it may be necessary to use
 * slower sample rates.  Using a Mega Arduino helps overcome latency
 * problems since 13 512 byte buffers will be used.
 *
 * Each 512 byte data block in the file has a four byte header followed by up
 * to 508 bytes of data. (508 values in 8-bit mode or 254 values in 10-bit mode)
 * Each block contains an integral number of samples with unused space at the
 * end of the block.
 *
 * Data is written to the file using a SD multiple block write command.
 */
#ifdef __AVR__
#include <SPI.h>
#include "SdFat.h"
#include "FreeStack.h"
#include "AnalogBinLogger.h"
//------------------------------------------------------------------------------
// Analog pin number list for a sample.  Pins may be in any order and pin
// numbers may be repeated.
const uint8_t PIN_LIST[] = {0, 1, 2, 3, 4, 5, 6, 7};
//------------------------------------------------------------------------------
// Sample rate in samples per second.
const float SAMPLE_RATE = 5000;  // Must be 0.25 or greater.

// The interval between samples in seconds, SAMPLE_INTERVAL, may be set to a
// constant instead of being calculated from SAMPLE_RATE.  SAMPLE_RATE is not
// used in the code below.  For example, setting SAMPLE_INTERVAL = 2.0e-4
// will result in a 200 microsecond sample interval.
const float SAMPLE_INTERVAL = 1.0/SAMPLE_RATE;

// Setting ROUND_SAMPLE_INTERVAL non-zero will cause the sample interval to
// be rounded to a a multiple of the ADC clock period and will reduce sample
// time jitter.
#define ROUND_SAMPLE_INTERVAL 1
//------------------------------------------------------------------------------
// ADC clock rate.
// The ADC clock rate is normally calculated from the pin count and sample
// interval.  The calculation attempts to use the lowest possible ADC clock
// rate.
//
// You can select an ADC clock rate by defining the symbol ADC_PRESCALER to
// one of these values.  You must choose an appropriate ADC clock rate for
// your sample interval.
// #define ADC_PRESCALER 7 // F_CPU/128 125 kHz on an Uno
// #define ADC_PRESCALER 6 // F_CPU/64  250 kHz on an Uno
// #define ADC_PRESCALER 5 // F_CPU/32  500 kHz on an Uno
// #define ADC_PRESCALER 4 // F_CPU/16 1000 kHz on an Uno
// #define ADC_PRESCALER 3 // F_CPU/8  2000 kHz on an Uno (8-bit mode only)
//------------------------------------------------------------------------------
// Reference voltage.  See the processor data-sheet for reference details.
// uint8_t const ADC_REF = 0; // External Reference AREF pin.
uint8_t const ADC_REF = (1 << REFS0);  // Vcc Reference.
// uint8_t const ADC_REF = (1 << REFS1);  // Internal 1.1 (only 644 1284P Mega)
// uint8_t const ADC_REF = (1 << REFS1) | (1 << REFS0);  // Internal 1.1 or 2.56
//------------------------------------------------------------------------------
// File definitions.
//
// Maximum file size in blocks.
// The program creates a contiguous file with FILE_BLOCK_COUNT 512 byte blocks.
// This file is flash erased using special SD commands.  The file will be
// truncated if logging is stopped early.
const uint32_t FILE_BLOCK_COUNT = 256000;

// log file base name.  Must be six characters or less.
#define FILE_BASE_NAME "analog"

// Set RECORD_EIGHT_BITS non-zero to record only the high 8-bits of the ADC.
#define RECORD_EIGHT_BITS 0
//------------------------------------------------------------------------------
// Pin definitions.
//
// Digital pin to indicate an error, set to -1 if not used.
// The led blinks for fatal errors. The led goes on solid for SD write
// overrun errors and logging continues.
const int8_t ERROR_LED_PIN = 3;

// SD chip select pin.
const uint8_t SD_CS_PIN = SS;
//------------------------------------------------------------------------------
// Buffer definitions.
//
// The logger will use SdFat's buffer plus BUFFER_BLOCK_COUNT additional
// buffers.  QUEUE_DIM must be a power of two larger than
//(BUFFER_BLOCK_COUNT + 1).
//
#if RAMEND < 0X8FF
#error Too little SRAM
//
#elif RAMEND < 0X10FF
// Use total of two 512 byte buffers.
const uint8_t BUFFER_BLOCK_COUNT = 1;
// Dimension for queues of 512 byte SD blocks.
const uint8_t QUEUE_DIM = 4;  // Must be a power of two!
//
#elif RAMEND < 0X20FF
// Use total of five 512 byte buffers.
const uint8_t BUFFER_BLOCK_COUNT = 4;
// Dimension for queues of 512 byte SD blocks.
const uint8_t QUEUE_DIM = 8;  // Must be a power of two!
//
#elif RAMEND < 0X40FF
// Use total of 13 512 byte buffers.
const uint8_t BUFFER_BLOCK_COUNT = 12;
// Dimension for queues of 512 byte SD blocks.
const uint8_t QUEUE_DIM = 16;  // Must be a power of two!
//
#else  // RAMEND
// Use total of 29 512 byte buffers.
const uint8_t BUFFER_BLOCK_COUNT = 28;
// Dimension for queues of 512 byte SD blocks.
const uint8_t QUEUE_DIM = 32;  // Must be a power of two!
#endif  // RAMEND
//==============================================================================
// End of configuration constants.
//==============================================================================
// Temporary log file.  Will be deleted if a reset or power failure occurs.
#define TMP_FILE_NAME "tmp_log.bin"

// Size of file base name.  Must not be larger than six.
const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;

// Number of analog pins to log.
const uint8_t PIN_COUNT = sizeof(PIN_LIST)/sizeof(PIN_LIST[0]);

// Minimum ADC clock cycles per sample interval
const uint16_t MIN_ADC_CYCLES = 15;

// Extra cpu cycles to setup ADC with more than one pin per sample.
const uint16_t ISR_SETUP_ADC = PIN_COUNT > 1 ? 100 : 0;

// Maximum cycles for timer0 system interrupt, millis, micros.
const uint16_t ISR_TIMER0 = 160;
//==============================================================================
SdFat sd;

SdBaseFile binFile;

char binName[13] = FILE_BASE_NAME "00.bin";

#if RECORD_EIGHT_BITS
const size_t SAMPLES_PER_BLOCK = DATA_DIM8/PIN_COUNT;
typedef block8_t block_t;
#else  // RECORD_EIGHT_BITS
const size_t SAMPLES_PER_BLOCK = DATA_DIM16/PIN_COUNT;
typedef block16_t block_t;
#endif // RECORD_EIGHT_BITS

block_t* emptyQueue[QUEUE_DIM];
uint8_t emptyHead;
uint8_t emptyTail;

block_t* fullQueue[QUEUE_DIM];
volatile uint8_t fullHead;  // volatile insures non-interrupt code sees changes.
uint8_t fullTail;

// queueNext assumes QUEUE_DIM is a power of two
inline uint8_t queueNext(uint8_t ht) {
  return (ht + 1) & (QUEUE_DIM -1);
}
//==============================================================================
// Interrupt Service Routines

// Pointer to current buffer.
block_t* isrBuf;

// Need new buffer if true.
bool isrBufNeeded = true;

// overrun count
uint16_t isrOver = 0;

// ADC configuration for each pin.
uint8_t adcmux[PIN_COUNT];
uint8_t adcsra[PIN_COUNT];
uint8_t adcsrb[PIN_COUNT];
uint8_t adcindex = 1;

// Insure no timer events are missed.
volatile bool timerError = false;
volatile bool timerFlag = false;
//------------------------------------------------------------------------------
// ADC done interrupt.
ISR(ADC_vect) {
  // Read ADC data.
#if RECORD_EIGHT_BITS
  uint8_t d = ADCH;
#else  // RECORD_EIGHT_BITS
  // This will access ADCL first.
  uint16_t d = ADC;
#endif  // RECORD_EIGHT_BITS

  if (isrBufNeeded && emptyHead == emptyTail) {
    // no buffers - count overrun
    if (isrOver < 0XFFFF) {
      isrOver++;
    }

    // Avoid missed timer error.
    timerFlag = false;
    return;
  }
  // Start ADC
  if (PIN_COUNT > 1) {
    ADMUX = adcmux[adcindex];
    ADCSRB = adcsrb[adcindex];
    ADCSRA = adcsra[adcindex];
    if (adcindex == 0) {
      timerFlag = false;
    }
    adcindex =  adcindex < (PIN_COUNT - 1) ? adcindex + 1 : 0;
  } else {
    timerFlag = false;
  }
  // Check for buffer needed.
  if (isrBufNeeded) {
    // Remove buffer from empty queue.
    isrBuf = emptyQueue[emptyTail];
    emptyTail = queueNext(emptyTail);
    isrBuf->count = 0;
    isrBuf->overrun = isrOver;
    isrBufNeeded = false;
  }
  // Store ADC data.
  isrBuf->data[isrBuf->count++] = d;

  // Check for buffer full.
  if (isrBuf->count >= PIN_COUNT*SAMPLES_PER_BLOCK) {
    // Put buffer isrIn full queue.
    uint8_t tmp = fullHead;  // Avoid extra fetch of volatile fullHead.
    fullQueue[tmp] = (block_t*)isrBuf;
    fullHead = queueNext(tmp);

    // Set buffer needed and clear overruns.
    isrBufNeeded = true;
    isrOver = 0;
  }
}
//------------------------------------------------------------------------------
// timer1 interrupt to clear OCF1B
ISR(TIMER1_COMPB_vect) {
  // Make sure ADC ISR responded to timer event.
  if (timerFlag) {
    timerError = true;
  }
  timerFlag = true;
}
//==============================================================================
// Error messages stored in flash.
#define error(msg) {sd.errorPrint(F(msg));fatalBlink();}
//------------------------------------------------------------------------------
//
void fatalBlink() {
  while (true) {
    if (ERROR_LED_PIN >= 0) {
      digitalWrite(ERROR_LED_PIN, HIGH);
      delay(200);
      digitalWrite(ERROR_LED_PIN, LOW);
      delay(200);
    }
  }
}
//==============================================================================
#if ADPS0 != 0 || ADPS1 != 1 || ADPS2 != 2
#error unexpected ADC prescaler bits
#endif
//------------------------------------------------------------------------------
// initialize ADC and timer1
void adcInit(metadata_t* meta) {
  uint8_t adps;  // prescaler bits for ADCSRA
  uint32_t ticks = F_CPU*SAMPLE_INTERVAL + 0.5;  // Sample interval cpu cycles.

  if (ADC_REF & ~((1 << REFS0) | (1 << REFS1))) {
    error("Invalid ADC reference");
  }
#ifdef ADC_PRESCALER
  if (ADC_PRESCALER > 7 || ADC_PRESCALER < 2) {
    error("Invalid ADC prescaler");
  }
  adps = ADC_PRESCALER;
#else  // ADC_PRESCALER
  // Allow extra cpu cycles to change ADC settings if more than one pin.
  int32_t adcCycles = (ticks - ISR_TIMER0)/PIN_COUNT - ISR_SETUP_ADC;

  for (adps = 7; adps > 0; adps--) {
    if (adcCycles >= (MIN_ADC_CYCLES << adps)) {
      break;
    }
  }
#endif  // ADC_PRESCALER
  meta->adcFrequency = F_CPU >> adps;
  if (meta->adcFrequency > (RECORD_EIGHT_BITS ? 2000000 : 1000000)) {
    error("Sample Rate Too High");
  }
#if ROUND_SAMPLE_INTERVAL
  // Round so interval is multiple of ADC clock.
  ticks += 1 << (adps - 1);
  ticks >>= adps;
  ticks <<= adps;
#endif  // ROUND_SAMPLE_INTERVAL

  if (PIN_COUNT > sizeof(meta->pinNumber)/sizeof(meta->pinNumber[0])) {
    error("Too many pins");
  }
  meta->pinCount = PIN_COUNT;
  meta->recordEightBits = RECORD_EIGHT_BITS;

  for (int i = 0; i < PIN_COUNT; i++) {
    uint8_t pin = PIN_LIST[i];
    if (pin >= NUM_ANALOG_INPUTS) {
      error("Invalid Analog pin number");
    }
    meta->pinNumber[i] = pin;

    // Set ADC reference and low three bits of analog pin number.
    adcmux[i] = (pin & 7) | ADC_REF;
    if (RECORD_EIGHT_BITS) {
      adcmux[i] |= 1 << ADLAR;
    }

    // If this is the first pin, trigger on timer/counter 1 compare match B.
    adcsrb[i] = i == 0 ? (1 << ADTS2) | (1 << ADTS0) : 0;
#ifdef MUX5
    if (pin > 7) {
      adcsrb[i] |= (1 << MUX5);
    }
#endif  // MUX5
    adcsra[i] = (1 << ADEN) | (1 << ADIE) | adps;
    adcsra[i] |= i == 0 ? 1 << ADATE : 1 << ADSC;
  }

  // Setup timer1
  TCCR1A = 0;
  uint8_t tshift;
  if (ticks < 0X10000) {
    // no prescale, CTC mode
    TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS10);
    tshift = 0;
  } else if (ticks < 0X10000*8) {
    // prescale 8, CTC mode
    TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11);
    tshift = 3;
  } else if (ticks < 0X10000*64) {
    // prescale 64, CTC mode
    TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11) | (1 << CS10);
    tshift = 6;
  } else if (ticks < 0X10000*256) {
    // prescale 256, CTC mode
    TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS12);
    tshift = 8;
  } else if (ticks < 0X10000*1024) {
    // prescale 1024, CTC mode
    TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS12) | (1 << CS10);
    tshift = 10;
  } else {
    error("Sample Rate Too Slow");
  }
  // divide by prescaler
  ticks >>= tshift;
  // set TOP for timer reset
  ICR1 = ticks - 1;
  // compare for ADC start
  OCR1B = 0;

  // multiply by prescaler
  ticks <<= tshift;

  // Sample interval in CPU clock ticks.
  meta->sampleInterval = ticks;
  meta->cpuFrequency = F_CPU;
  float sampleRate = (float)meta->cpuFrequency/meta->sampleInterval;
  Serial.print(F("Sample pins:"));
  for (uint8_t i = 0; i < meta->pinCount; i++) {
    Serial.print(' ');
    Serial.print(meta->pinNumber[i], DEC);
  }
  Serial.println();
  Serial.print(F("ADC bits: "));
  Serial.println(meta->recordEightBits ? 8 : 10);
  Serial.print(F("ADC clock kHz: "));
  Serial.println(meta->adcFrequency/1000);
  Serial.print(F("Sample Rate: "));
  Serial.println(sampleRate);
  Serial.print(F("Sample interval usec: "));
  Serial.println(1000000.0/sampleRate, 4);
}
//------------------------------------------------------------------------------
// enable ADC and timer1 interrupts
void adcStart() {
  // initialize ISR
  isrBufNeeded = true;
  isrOver = 0;
  adcindex = 1;

  // Clear any pending interrupt.
  ADCSRA |= 1 << ADIF;

  // Setup for first pin.
  ADMUX = adcmux[0];
  ADCSRB = adcsrb[0];
  ADCSRA = adcsra[0];

  // Enable timer1 interrupts.
  timerError = false;
  timerFlag = false;
  TCNT1 = 0;
  TIFR1 = 1 << OCF1B;
  TIMSK1 = 1 << OCIE1B;
}
//------------------------------------------------------------------------------
void adcStop() {
  TIMSK1 = 0;
  ADCSRA = 0;
}
//------------------------------------------------------------------------------
// Convert binary file to csv file.
void binaryToCsv() {
  uint8_t lastPct = 0;
  block_t buf;
  metadata_t* pm;
  uint32_t t0 = millis();
  char csvName[13];
  StdioStream csvStream;

  if (!binFile.isOpen()) {
    Serial.println(F("No current binary file"));
    return;
  }
  binFile.rewind();
  if (binFile.read(&buf , 512) != 512) {
    error("Read metadata failed");
  }
  // Create a new csv file.
  strcpy(csvName, binName);
  strcpy(&csvName[BASE_NAME_SIZE + 3], "csv");

  if (!csvStream.fopen(csvName, "w")) {
    error("open csvStream failed");
  }
  Serial.println();
  Serial.print(F("Writing: "));
  Serial.print(csvName);
  Serial.println(F(" - type any character to stop"));
  pm = (metadata_t*)&buf;
  csvStream.print(F("Interval,"));
  float intervalMicros = 1.0e6*pm->sampleInterval/(float)pm->cpuFrequency;
  csvStream.print(intervalMicros, 4);
  csvStream.println(F(",usec"));
  for (uint8_t i = 0; i < pm->pinCount; i++) {
    if (i) {
      csvStream.putc(',');
    }
    csvStream.print(F("pin"));
    csvStream.print(pm->pinNumber[i]);
  }
  csvStream.println();
  uint32_t tPct = millis();
  while (!Serial.available() && binFile.read(&buf, 512) == 512) {
    if (buf.count == 0) {
      break;
    }
    if (buf.overrun) {
      csvStream.print(F("OVERRUN,"));
      csvStream.println(buf.overrun);
    }
    for (uint16_t j = 0; j < buf.count; j += PIN_COUNT) {
      for (uint16_t i = 0; i < PIN_COUNT; i++) {
        if (i) {
          csvStream.putc(',');
        }
        csvStream.print(buf.data[i + j]);
      }
      csvStream.println();
    }
    if ((millis() - tPct) > 1000) {
      uint8_t pct = binFile.curPosition()/(binFile.fileSize()/100);
      if (pct != lastPct) {
        tPct = millis();
        lastPct = pct;
        Serial.print(pct, DEC);
        Serial.println('%');
      }
    }
    if (Serial.available()) {
      break;
    }
  }
  csvStream.fclose();
  Serial.print(F("Done: "));
  Serial.print(0.001*(millis() - t0));
  Serial.println(F(" Seconds"));
}
//------------------------------------------------------------------------------
// read data file and check for overruns
void checkOverrun() {
  bool headerPrinted = false;
  block_t buf;
  uint32_t bgnBlock, endBlock;
  uint32_t bn = 0;

  if (!binFile.isOpen()) {
    Serial.println(F("No current binary file"));
    return;
  }
  if (!binFile.contiguousRange(&bgnBlock, &endBlock)) {
    error("contiguousRange failed");
  }
  binFile.rewind();
  Serial.println();
  Serial.println(F("Checking overrun errors - type any character to stop"));
  if (binFile.read(&buf , 512) != 512) {
    error("Read metadata failed");
  }
  bn++;
  while (binFile.read(&buf, 512) == 512) {
    if (buf.count == 0) {
      break;
    }
    if (buf.overrun) {
      if (!headerPrinted) {
        Serial.println();
        Serial.println(F("Overruns:"));
        Serial.println(F("fileBlockNumber,sdBlockNumber,overrunCount"));
        headerPrinted = true;
      }
      Serial.print(bn);
      Serial.print(',');
      Serial.print(bgnBlock + bn);
      Serial.print(',');
      Serial.println(buf.overrun);
    }
    bn++;
  }
  if (!headerPrinted) {
    Serial.println(F("No errors found"));
  } else {
    Serial.println(F("Done"));
  }
}
//------------------------------------------------------------------------------
// dump data file to Serial
void dumpData() {
  block_t buf;
  if (!binFile.isOpen()) {
    Serial.println(F("No current binary file"));
    return;
  }
  binFile.rewind();
  if (binFile.read(&buf , 512) != 512) {
    error("Read metadata failed");
  }
  Serial.println();
  Serial.println(F("Type any character to stop"));
  delay(1000);
  while (!Serial.available() && binFile.read(&buf , 512) == 512) {
    if (buf.count == 0) {
      break;
    }
    if (buf.overrun) {
      Serial.print(F("OVERRUN,"));
      Serial.println(buf.overrun);
    }
    for (uint16_t i = 0; i < buf.count; i++) {
      Serial.print(buf.data[i], DEC);
      if ((i+1)%PIN_COUNT) {
        Serial.print(',');
      } else {
        Serial.println();
      }
    }
  }
  Serial.println(F("Done"));
}
//------------------------------------------------------------------------------
// log data
// max number of blocks to erase per erase call
uint32_t const ERASE_SIZE = 262144L;
void logData() {
  uint32_t bgnBlock, endBlock;

  // Allocate extra buffer space.
  block_t block[BUFFER_BLOCK_COUNT];

  Serial.println();

  // Initialize ADC and timer1.
  adcInit((metadata_t*) &block[0]);

  // Find unused file name.
  if (BASE_NAME_SIZE > 6) {
    error("FILE_BASE_NAME too long");
  }
  while (sd.exists(binName)) {
    if (binName[BASE_NAME_SIZE + 1] != '9') {
      binName[BASE_NAME_SIZE + 1]++;
    } else {
      binName[BASE_NAME_SIZE + 1] = '0';
      if (binName[BASE_NAME_SIZE] == '9') {
        error("Can't create file name");
      }
      binName[BASE_NAME_SIZE]++;
    }
  }
  // Delete old tmp file.
  if (sd.exists(TMP_FILE_NAME)) {
    Serial.println(F("Deleting tmp file"));
    if (!sd.remove(TMP_FILE_NAME)) {
      error("Can't remove tmp file");
    }
  }
  // Create new file.
  Serial.println(F("Creating new file"));
  binFile.close();
  if (!binFile.createContiguous(TMP_FILE_NAME, 512 * FILE_BLOCK_COUNT)) {
    error("createContiguous failed");
  }
  // Get the address of the file on the SD.
  if (!binFile.contiguousRange(&bgnBlock, &endBlock)) {
    error("contiguousRange failed");
  }
  // Use SdFat's internal buffer.
  uint8_t* cache = (uint8_t*)sd.vol()->cacheClear();
  if (cache == 0) {
    error("cacheClear failed");
  }

  // Flash erase all data in the file.
  Serial.println(F("Erasing all data"));
  uint32_t bgnErase = bgnBlock;
  uint32_t endErase;
  while (bgnErase < endBlock) {
    endErase = bgnErase + ERASE_SIZE;
    if (endErase > endBlock) {
      endErase = endBlock;
    }
    if (!sd.card()->erase(bgnErase, endErase)) {
      error("erase failed");
    }
    bgnErase = endErase + 1;
  }
  // Start a multiple block write.
  if (!sd.card()->writeStart(bgnBlock, FILE_BLOCK_COUNT)) {
    error("writeBegin failed");
  }
  // Write metadata.
  if (!sd.card()->writeData((uint8_t*)&block[0])) {
    error("Write metadata failed");
  }
  // Initialize queues.
  emptyHead = emptyTail = 0;
  fullHead = fullTail = 0;

  // Use SdFat buffer for one block.
  emptyQueue[emptyHead] = (block_t*)cache;
  emptyHead = queueNext(emptyHead);

  // Put rest of buffers in the empty queue.
  for (uint8_t i = 0; i < BUFFER_BLOCK_COUNT; i++) {
    emptyQueue[emptyHead] = &block[i];
    emptyHead = queueNext(emptyHead);
  }
  // Give SD time to prepare for big write.
  delay(1000);
  Serial.println(F("Logging - type any character to stop"));
  // Wait for Serial Idle.
  Serial.flush();
  delay(10);
  uint32_t bn = 1;
  uint32_t t0 = millis();
  uint32_t t1 = t0;
  uint32_t overruns = 0;
  uint32_t count = 0;
  uint32_t maxLatency = 0;

  // Start logging interrupts.
  adcStart();
  while (1) {
    if (fullHead != fullTail) {
      // Get address of block to write.
      block_t* pBlock = fullQueue[fullTail];

      // Write block to SD.
      uint32_t usec = micros();
      if (!sd.card()->writeData((uint8_t*)pBlock)) {
        error("write data failed");
      }
      usec = micros() - usec;
      t1 = millis();
      if (usec > maxLatency) {
        maxLatency = usec;
      }
      count += pBlock->count;

      // Add overruns and possibly light LED.
      if (pBlock->overrun) {
        overruns += pBlock->overrun;
        if (ERROR_LED_PIN >= 0) {
          digitalWrite(ERROR_LED_PIN, HIGH);
        }
      }
      // Move block to empty queue.
      emptyQueue[emptyHead] = pBlock;
      emptyHead = queueNext(emptyHead);
      fullTail = queueNext(fullTail);
      bn++;
      if (bn == FILE_BLOCK_COUNT) {
        // File full so stop ISR calls.
        adcStop();
        break;
      }
    }
    if (timerError) {
      error("Missed timer event - rate too high");
    }
    if (Serial.available()) {
      // Stop ISR calls.
      adcStop();
      if (isrBuf != 0 && isrBuf->count >= PIN_COUNT) {
        // Truncate to last complete sample.
        isrBuf->count = PIN_COUNT*(isrBuf->count/PIN_COUNT);
        // Put buffer in full queue.
        fullQueue[fullHead] = isrBuf;
        fullHead = queueNext(fullHead);
        isrBuf = 0;
      }
      if (fullHead == fullTail) {
        break;
      }
    }
  }
  if (!sd.card()->writeStop()) {
    error("writeStop failed");
  }
  // Truncate file if recording stopped early.
  if (bn != FILE_BLOCK_COUNT) {
    Serial.println(F("Truncating file"));
    if (!binFile.truncate(512L * bn)) {
      error("Can't truncate file");
    }
  }
  if (!binFile.rename(binName)) {
    error("Can't rename file");
  }
  Serial.print(F("File renamed: "));
  Serial.println(binName);
  Serial.print(F("Max block write usec: "));
  Serial.println(maxLatency);
  Serial.print(F("Record time sec: "));
  Serial.println(0.001*(t1 - t0), 3);
  Serial.print(F("Sample count: "));
  Serial.println(count/PIN_COUNT);
  Serial.print(F("Samples/sec: "));
  Serial.println((1000.0/PIN_COUNT)*count/(t1-t0));
  Serial.print(F("Overruns: "));
  Serial.println(overruns);
  Serial.println(F("Done"));
}
//------------------------------------------------------------------------------
void setup(void) {
  if (ERROR_LED_PIN >= 0) {
    pinMode(ERROR_LED_PIN, OUTPUT);
  }
  Serial.begin(115200);

  // Read the first sample pin to init the ADC.
  analogRead(PIN_LIST[0]);

  Serial.print(F("FreeStack: "));
  Serial.println(FreeStack());

  // Initialize at the highest speed supported by the board that is
  // not over 50 MHz. Try a lower speed if SPI errors occur.
  if (!sd.begin(SD_CS_PIN, SD_SCK_MHZ(50))) {
    sd.initErrorPrint();
    fatalBlink();
  }
}
//------------------------------------------------------------------------------
void loop(void) {
  // Read any Serial data.
  do {
    delay(10);
  } while (Serial.available() && Serial.read() >= 0);
  Serial.println();
  Serial.println(F("type:"));
  Serial.println(F("c - convert file to csv"));
  Serial.println(F("d - dump data to Serial"));
  Serial.println(F("e - overrun error details"));
  Serial.println(F("r - record ADC data"));

  while(!Serial.available()) {
    SysCall::yield();
  }
  char c = tolower(Serial.read());
  if (ERROR_LED_PIN >= 0) {
    digitalWrite(ERROR_LED_PIN, LOW);
  }
  // Read any Serial data.
  do {
    delay(10);
  } while (Serial.available() && Serial.read() >= 0);

  if (c == 'c') {
    binaryToCsv();
  } else if (c == 'd') {
    dumpData();
  } else if (c == 'e') {
    checkOverrun();
  } else if (c == 'r') {
    logData();
  } else {
    Serial.println(F("Invalid entry"));
  }
}
#else  // __AVR__
#error This program is only for AVR.
#endif  // __AVR__

title: Can I record us (microseconds) with AnalogBinLogger example in SdFat's library?

Answers: 0


body:
I have used many Arduino boards with adapters and other power supplies. While connecting with a powerbank for portable projects I have noticed that the power goes off after a couple of seconds and then turn on again after sometimes. Why this is happening with power bank?
I have used following powerbanks:
1. Basus
2. Xiaomi

title: Arduino boards are not working with powerbanks!

Answers: 1

body:
Most USB powerbanks will automatically turn off if there is not a minimum current draw to keep them turned on.  The Arduino is obviously drawing current below the limit for the devices you have.

A couple of options:

 1. Add some additional load to keep the powerbank on indefinitely.  Of course this may waste power but that's part of the price to pay.
 2. Find a power bank that is less sophisticated.  I have one with a manual on/off switch.  It powers the Arduino just fine until it runs out of power.
 3. Find a different powerbank that has a lower threshold for staying on.  Some vendors give you this spec and others don't.
 4. Modify the powerbank to stay on.  I'm not sure there is a general way to do this but you might experiment with it and see.


body:
An application of ATtiny with SD card is complicated due to missing of hardware SPI in attiny.
The "ATmega" code for creating of a "SD file" is:

    #include <SPI.h>
    #include <SD.h>

    File file;
    int const pinCS = 2;

    void setup()

    {
    SD.begin(pinCS);
    file = SD.open("Test.txt", FILE_WRITE);
    file.println("anything");
    file.close();}

    void loop()
    {}

This code creates on SD card a file "Test.txt" and to this file records text "anathing".
Is it possible to rewrite this code for "ATtiny85"?

title: Record data to SD card with ATtiny85

Answers: 1

body:
The ATtiny85 has no dedicated SPI port. It has, however, an “USI” port
(Universal Serial Interface) that should be able to do the job. The lack
of SPI should not be a problem, but the lack of memory _will_ be a
problem.

Files on an SD card are written one sector (512 bytes) at a time.
For this reason, the SD library uses a 512 bytes buffer in RAM.
That cannot work on an ATtiny85, as the buffer would consume the whole
RAM.

You may be able to do something using the [Petit FAT library][petit],
provided you can work around the severe limitations of its write
interface:

> The write function has some restrictions listed below:
>
> * Cannot create file. Only existing file can be written.
> * Cannot expand file size.
> * Cannot update time stamp of the file.
> * Write operation can start/stop on the sector boundary only.
> * Read-only attribute of the file cannot block write operation.

The first two points imply that you would have to create the file and
allocate the sectors for it in your computer.

This [blog post][] mentions a port of the library to the Arduino
environment, and its use on an ATtiny84, which has similar capabilities
to the ATtiny85 (only with more pins).

[petit]: http://elm-chan.org/fsw/ff/00index_p.html
[blog post]: https://harizanov.com/2012/05/toying-with-attiny84-and-sd-card-in-arduino-ide/


body:
This is the code I'm working with. I'm using it for video stabilization system. It was working fine but for some reason now it gives me this error? Is it because I deleted the library and installed again? Please help. I'm new to arduino. Hopefully I formatted this correctly.
```
#include <Servo.h>
#include "I2Cdev.h"
#include "MPU6050_6Axis_MotionApps20.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif

MPU6050 mpu;
Servo myServo;   // define servo
int servoPin=9;
float PWM = 0;
float Yaw = 0;

#define OUTPUT_READABLE_YAWPITCHROLL
#define INTERRUPT_PIN 2
#define LED_PIN 13

bool blinkState = false;

// MPU control/status vars
bool dmpReady=false;    // set true if DMP init was successful
uint8_t mpuIntStatus;   // holds actual interrupt status byte from MPU
uint8_t devStatus;      // return status after each device operation (0 = success, !0 = error)
uint16_t packetSize;    // expected DMP packet size (default is 42 bytes)
uint16_t fifoCount;     // count of all bytes currently in FIFO
uint8_t fifoBuffer[64]; // FIFO storage buffer

// orientation/motion vars
Quaternion q;           // [w, x, y, z]         quaternion container
VectorInt16 aa;         // [x, y, z]            accel sensor measurements
VectorInt16 aaReal;     // [x, y, z]            gravity-free accel sensor measurements
VectorInt16 aaWorld;    // [x, y, z]            world-frame accel sensor measurements
VectorFloat gravity;    // [x, y, z]            gravity vector
float euler[3];         // [psi, theta, phi]    Euler angle container
float ypr[3];           // [yaw, pitch, roll]   yaw/pitch/roll container and gravity vector
//packet structure for InvenSense teapot demo

volatile bool mpuInterrupt=false;
void dmpDataReady(){
  mpuInterrupt=true;
}
// ================================================================
// ===                      INITIAL SETUP                       ===
// ================================================================
void setup()
{
  // join I2C bus (I2Cdev library doesn't do this automatically)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
  Wire.begin();
  Wire.setClock(400000);

#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
  Fastwire::setup(400, true);

#endif

  Serial.begin(115200);
  while (!Serial);      // wait for Leonardo enumeration, others continue immediately

  // initialize device
  Serial.println(F("Initializing I2C devices..."));
  pinMode(INTERRUPT_PIN, INPUT);
  // testing connection...
  Serial.println(F("Testing device connections..."));
  Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
  // load and configure the DMP
  Serial.println(F("Initializing DMP"));
  devStatus = mpu.dmpInitialize();

  // INPUT CALIBRATED OFFSETS HERE; SPECIFIC FOR EACH UNIT AND EACH MOUNTING CONFIGURATION!!!!
  //fix offsets #s when we use mount
  mpu.setXGyroOffset(0);
  mpu.setYGyroOffset(0);
  mpu.setZGyroOffset(0);
  //mpu.setXAccelOffset(-651); //unneccesary
  //mpu.setYAccelOffset(670);  //also unneccesary
  mpu.setZAccelOffset(17);

  // make sure it worked (returns 0 if so)
  if (devStatus == 0){
    // Calibration Time: generate offsets and calibrate our MPU6050
     // mpu.CalibrateAccel(6);
     // mpu.CalibrateGyro(6);
     // mpu.PrintActiveOffsets();
    // turn on the DMP, now that it's ready
       Serial.println(F("Enabling DMP..."));
        mpu.setDMPEnabled(true);

    // enable Arduino interrupt detection
    Serial.print(F("Enabling interrupt detection (Arduino external interrupt 0)"));
    Serial.print(digitalPinToInterrupt(INTERRUPT_PIN));
    Serial.println(F(")..."));
    attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING);

    mpuIntStatus = mpu.getIntStatus();
    Serial.println(F("DMP ready! Waiting for first interrupt..."));
        dmpReady = true;
    // get expected DMP packet size for later comparison
    packetSize = mpu.dmpGetFIFOPacketSize();
  }else
  {
    // ERROR!
    // 1 = initial memory load failed, 2 = DMP configuration updates failed (if it's going to break, usually the code will be 1)
    Serial.print(F("DMP Initialization failed code = "));
    Serial.println(devStatus);
    Serial.println(F(")"));
  }

  // configure LED for output
  pinMode(LED_PIN, OUTPUT);
  myServo.attach(servoPin);
  PWM=0;
}

//main program loop

void loop()
{
  // if programming failed, don't try to do anything
    if (!dmpReady) return;
    // wait for MPU interrupt or extra packet(s) available
    while (!mpuInterrupt && fifoCount < packetSize) {
        if (mpuInterrupt && fifoCount < packetSize) {
          // try to get out of the infinite loop
          fifoCount = mpu.getFIFOCount();
        }
        // other program behavior stuff here
    }

  //reset inerrupt flag Get INT_STATUS byte
  mpuInterrupt=false;
  mpuIntStatus = mpu.getIntStatus();

  // get current FIFO count
  fifoCount = mpu.getFIFOCount();

  // check for overflow (this should never happen unless our code is too inefficient)
  if (fifoCount<packetSize){

    // reset so we can continue cleanly
  }else if ((mpuIntStatus & _BV(MPU6050_INTERRUPT_FIFO_OFLOW_BIT)) || fifoCount >= 1024) {

    mpu.resetFIFO();
    Serial.println(F("FIFO overflow!"));

  }else if (mpuIntStatus & _BV (MPU6050_INTERRUPT_DMP_INT_BIT)){

   while (fifoCount>=packetSize)
  {
    // check for correct available data length
    //if (fifoCount < packetSize)
    //return; //  fifoCount = mpu.getFIFOCount();

    // read a packet from FIFO
    mpu.getFIFOBytes(fifoBuffer, packetSize);

    // track FIFO count here in case there is > 1 packet available
    fifoCount -= packetSize;
   }
     #ifdef OUTPUT_READABLE_QUATERNION
     //display quaternion values in easty matrix form: w x y x
    mpu.dmpGetQuaternion(&q, fifoBuffer);
            Serial.print("quat\t");
            Serial.print(q.w);
            Serial.print("\t");
            Serial.print(q.x);
            Serial.print("\t");
            Serial.print(q.y);
            Serial.print("\t");
            Serial.print(q.z);

    #endif
    #ifdef OUTPUT_READABLE_EULER
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetEuler(euler, &q);
            Serial.print("euler\t");
            Serial.print(euler[0] * 180/M_PI);
            Serial.print("\t");
            Serial.print(euler[1] * 180/M_PI);
            Serial.print("\t");
            Serial.println(euler[2] * 180/M_PI);
        #endif
        #ifdef OUTPUT_READABLE_YAWPITCHROLL
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
            Yaw = ypr[0]*180/M_PI;
            Serial.print("ypr\t");
            Serial.print(ypr[0] * 180/M_PI);
            Serial.print("\t");
            Serial.print(ypr[1] * 180/M_PI);
            Serial.print("\t");
            Serial.println(ypr[2] * 180/M_PI);
        #endif
        #ifdef OUTPUT_READABLE_REALACCEL
            // display real acceleration, adjusted to remove gravity
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetAccel(&aa, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
            Serial.print("areal\t");
            Serial.print(aaReal.x);
            Serial.print("\t");
            Serial.print(aaReal.y);
            Serial.print("\t");
            Serial.println(aaReal.z);
        #endif
        #ifdef OUTPUT_READABLE_WORLDACCEL
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetAccel(&aa, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
            mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);
            Serial.print("aworld\t");
            Serial.print(aaWorld.x);
            Serial.print("\t");
            Serial.print(aaWorld.y);
            Serial.print("\t");
            Serial.println(aaWorld.z);
        #endif

    // blink LED to indicate activity
    blinkState = !blinkState;
    digitalWrite(LED_PIN, blinkState);
  }
  PWM= map(Yaw, -180, 180, 1860, 1140);
  myServo.write(PWM);
  Serial.println(PWM);
  Serial.println(Yaw);
}
```
If the error code is needed please let me know. It's too long to attach in the body

title: Why do I get error "Error compiling for board Arduino Uno" with my mpu6050 video stabilization code?

Answers: 0


body:
I have a project where I want to remotely turn on and off a relay using an Arduino,(ESP8266) over the internet.

 1.  I have a remote web server that hosts my existing hobby website, cPanel hosted by GoDaddy Sites.
 2.  An Arduino (ESP8266) connects to this website listening for relay on/off commands.
 3.  Open a browser and load the webpage dashboard to sent commands to Arduino.

 Yes I could have the Arduino poll the website ever so often to check for a value changed in a database, but I don't want to do that, Just seems unethical to me.

I was looking at WebSockets and thought that might be what I'm looking for but I know too little about it or there's not enough relevant documentation online about it to use it in this type of project.

I am looking forward to your comments and answers, but please do not tell me to host the site on the Arduino, and also using an app or other service is not going to work either, We are working with my own webpage and thats it no thirdparty apps, Thanks.

title: Send commands from cPanel website to client ESP8266

Answers: 1

body:
I don't believe you will have the capability to implement a Websocket interface on the GoDaddy cPanel web site.  I think you are limited to just serving up HTML content and associated files.  Websocket requires a server-side resource to talk to which you cannot implement.

I see nothing wrong with having a simple HTML page, that doesn't even need to really contain HTML that your ESP8266 can "GET" and examine and determine to turn your relay on or off.


body:
I am making a Christmas Tree with Arduino. I found a 12 led chaser code on internet so I made 12 rows of leds and hook them up to my Arduino pro mini.
They are working just fine.

However, I also want to add music with piezo buzzer while running the LEDs. Is that possible somehow or should I use another microcontroller for piezo? I also used pin 10 for piezo buzzer and used pin 14(a0) for led assigned for pin 10 previously..

Here are the codes:
12 led chaser

```c++
#define t   30
#define t1  20
#define t2  100
#define t3  50

void setup() {
  // set up pins 2 to 13 as outputs
  for (int i = 2; i <= 13; i++) {
    pinMode(i, OUTPUT);
  }
}
/////////////////////////////////////////////////////////////////////////////////Effect 1
void loop(){

effect_1();
effect_1();

 effect_2();
 effect_2();

 effect_3();
 effect_3();

 effect_4();
 effect_4();

 effect_5();
 effect_5();

 effect_6();
 effect_6();

 effect_7();
 effect_7();
  }
//left to right and right to left
void effect_1()
{
for(int i=2; i<14; i++){
digitalWrite(i, HIGH);
delay(t1);
digitalWrite(i+1, HIGH);
delay(t1);
digitalWrite(i+2, HIGH);
delay(t1);
digitalWrite(i, LOW);
delay(t1);
digitalWrite(i+1, LOW);
delay(t1);
}
for(int i=13; i>1; i--){
digitalWrite(i, HIGH);
delay(t1);
digitalWrite(i-1, HIGH);
delay(t1);
digitalWrite(i-2, HIGH);
delay(t1);
digitalWrite(i, LOW);
delay(t1);
digitalWrite(i-1, LOW);
delay(t1);
}
}
/////////////////////////////////////////////////////////////////////////////////Effect 2
void effect_2()
{
int count = 13; // keeps track of second LED movement

  // move first LED from left to right and second from right to left
  for (int i = 2; i < 13; i++) {
    clear();
    digitalWrite(i, HIGH);      // chaser 1
    digitalWrite(count, HIGH); // chaser 2
    count--;
    // stop LEDs from appearing to stand still in the middle
    if (count != 7) {
      delay(t2);
    }
  }

  // move first LED from right to left and second LED from left to right
  for (int i = 13; i > 2; i--) {
    clear();
    digitalWrite(i, HIGH);      // chaser 1
    digitalWrite(count, HIGH); // chaser 2
    count++;
    // stop LEDs from appearing to stand still in the middle
    if (count != 8) {
      delay(t2);
    }
  }
}

////////////////////////////////////////////////////////////////////////////////Effect 3

void effect_3()
{
for(int i=2; i<14; i++){
  digitalWrite(i, HIGH);
  delay(t3);
}
for(int i=2; i<14; i++){
  digitalWrite(i, LOW);
  delay(t3);
}

for(int i = 14; i>=2; i--){
  digitalWrite(i, HIGH);
  delay(t3);
}
for(int i = 14; i>=2; i--){
  digitalWrite(i, LOW);
  delay(t3);
}
}
  ///////////////////////////////////////////////////////////////////////////Effect 4
void effect_4()
{
for(int j = 2; j <= 13; j++){
  digitalWrite(j, HIGH);
  delay(t2);
  j=j+1;
  }
for(int j = 2; j <= 13; j++){
  digitalWrite(j, LOW);
  delay(t2);
  }

  for(int k = 15; k > 2; k--){
  digitalWrite(k, HIGH);
  delay(t2);
  k=k-1;
  }
for(int k = 15; k > 2; k--){
  digitalWrite(k, LOW);
  delay(t2);
  }
}
//////////////////////////////////////////////////////////////////////////////Effect 5
  void effect_5()
{
 for(int pin = 13; pin >= 2; pin--)
  {
  digitalWrite(pin, HIGH);
  delay(t1);
  digitalWrite(pin+1, LOW);
  delay(t1);
  }
  for(int pin = 13; pin >= 2; pin--)
  {
  digitalWrite(pin+1, HIGH);
  delay(t1);
  digitalWrite(pin+2, LOW);
  delay(t1);
  }
  for(int pin = 13; pin >= 2; pin--)
  {
  digitalWrite(pin+2, HIGH);
  delay(t1);
  digitalWrite(pin+3, LOW);
  delay(t1);
  }
  for(int pin = 13; pin >= 2; pin--)
  {
  digitalWrite(pin+3, HIGH);
  delay(t1);
  digitalWrite(pin+4, LOW);
  delay(t1);
  }
    for(int pin = 13; pin >= 2; pin--)
  {
  digitalWrite(pin+4, HIGH);
  delay(t1);
  digitalWrite(pin+5, LOW);
  delay(t1);
  }
  for(int pin = 13; pin >= 2; pin--)
  {
  digitalWrite(pin+5, HIGH);
  delay(t1);
  digitalWrite(pin+6, LOW);
  delay(t1);
  }
  for(int pin = 13; pin >= 2; pin--)
  {
  digitalWrite(pin+6, HIGH);
  delay(t1);
  digitalWrite(pin+7, LOW);
  delay(t1);
  }
   for(int pin = 13; pin >= 2; pin--)
  {
  digitalWrite(pin+7, HIGH);
  delay(t1);
  digitalWrite(pin+8, LOW);
  delay(t1);
  }
  for(int pin = 9; pin >= 2; pin--)
  {
  digitalWrite(pin+8, HIGH);
  delay(t1);
  digitalWrite(pin+9, LOW);
  delay(t1);
  }
    for(int pin = 9; pin >= 2; pin--)
  {
  digitalWrite(pin+9, HIGH);
  delay(t1);
  digitalWrite(pin+10, LOW);
  delay(t1);
  }
  for(int pin = 9; pin >= 2; pin--)
  {
  digitalWrite(pin+10, HIGH);
  delay(t1);
  digitalWrite(pin+11, LOW);
  delay(t1);
  }
  for(int pin = 14; pin >= 2; pin--)
  {
  digitalWrite(pin+11, HIGH);
  delay(t1);
  }
  for(int pin = 13; pin >= 2; pin--)
  {
    digitalWrite(pin, LOW);
  delay(t1);
    }
  }
  /////////////////////////////////////////////////////////////////////////////Effect 6
void effect_6()
{
for(int j=2; j<14; j++){
  digitalWrite(j, LOW);
  delay(t);
  digitalWrite(j, HIGH);
  delay(t);
  digitalWrite(j-2, LOW);
  delay(t);
  digitalWrite(j, HIGH);
}
for(int k = 15; k>2; k--){
  digitalWrite(k, LOW);
  delay(t);
  digitalWrite(k, HIGH);
  delay(t);
  digitalWrite(k+2, LOW);
  delay(t);
  digitalWrite(k, HIGH);
}
for(int k = 2; k<14; k++){
  digitalWrite(k, LOW);
  delay(t);
  digitalWrite(k, HIGH);
  delay(t);
  digitalWrite(k-2, LOW);
  delay(t);
  digitalWrite(k, HIGH);
}
for(int k = 15; k>2; k--){
  digitalWrite(k, LOW);
  delay(t);
  digitalWrite(k, HIGH);
  delay(t);
  digitalWrite(k+4, LOW);
  delay(t);
  digitalWrite(k, HIGH);
}
for(int k = 2; k<14; k++){
  digitalWrite(k, LOW);
  delay(t);
  digitalWrite(k, HIGH);
  delay(t);
  digitalWrite(k-4, LOW);
  delay(t);
  digitalWrite(k, HIGH);
}
}
///////////////////////////////////////////////////////////////////////////////////Effect 7
void effect_7()
{
for(int j=2; j<14; j++){
  digitalWrite(j, HIGH);
  delay(t);
  digitalWrite(j+2, LOW);
  delay(t);
}
for(int k = 15; k>2; k--){
  digitalWrite(k, HIGH);
  delay(t);
  digitalWrite(k+2, LOW);
  delay(t);
}
}

// function to switch all LEDs off
void clear(void)
{
  for (int i = 2; i <= 13; i++) {
    digitalWrite(i, LOW);
  }
}
```

Melody tone for buzzer:
```c++
/*
  We Wish You a Merry Christmas - Traditional Christmas song
  Connect a piezo buzzer or speaker to pin 11 or select a new pin.
  More songs available at https://github.com/robsoncouto/arduino-songs

                                              Robson Couto, 2019
*/
#define NOTE_B0  31
#define NOTE_C1  33
#define NOTE_CS1 35
#define NOTE_D1  37
#define NOTE_DS1 39
#define NOTE_E1  41
#define NOTE_F1  44
#define NOTE_FS1 46
#define NOTE_G1  49
#define NOTE_GS1 52
#define NOTE_A1  55
#define NOTE_AS1 58
#define NOTE_B1  62
#define NOTE_C2  65
#define NOTE_CS2 69
#define NOTE_D2  73
#define NOTE_DS2 78
#define NOTE_E2  82
#define NOTE_F2  87
#define NOTE_FS2 93
#define NOTE_G2  98
#define NOTE_GS2 104
#define NOTE_A2  110
#define NOTE_AS2 117
#define NOTE_B2  123
#define NOTE_C3  131
#define NOTE_CS3 139
#define NOTE_D3  147
#define NOTE_DS3 156
#define NOTE_E3  165
#define NOTE_F3  175
#define NOTE_FS3 185
#define NOTE_G3  196
#define NOTE_GS3 208
#define NOTE_A3  220
#define NOTE_AS3 233
#define NOTE_B3  247
#define NOTE_C4  262
#define NOTE_CS4 277
#define NOTE_D4  294
#define NOTE_DS4 311
#define NOTE_E4  330
#define NOTE_F4  349
#define NOTE_FS4 370
#define NOTE_G4  392
#define NOTE_GS4 415
#define NOTE_A4  440
#define NOTE_AS4 466
#define NOTE_B4  494
#define NOTE_C5  523
#define NOTE_CS5 554
#define NOTE_D5  587
#define NOTE_DS5 622
#define NOTE_E5  659
#define NOTE_F5  698
#define NOTE_FS5 740
#define NOTE_G5  784
#define NOTE_GS5 831
#define NOTE_A5  880
#define NOTE_AS5 932
#define NOTE_B5  988
#define NOTE_C6  1047
#define NOTE_CS6 1109
#define NOTE_D6  1175
#define NOTE_DS6 1245
#define NOTE_E6  1319
#define NOTE_F6  1397
#define NOTE_FS6 1480
#define NOTE_G6  1568
#define NOTE_GS6 1661
#define NOTE_A6  1760
#define NOTE_AS6 1865
#define NOTE_B6  1976
#define NOTE_C7  2093
#define NOTE_CS7 2217
#define NOTE_D7  2349
#define NOTE_DS7 2489
#define NOTE_E7  2637
#define NOTE_F7  2794
#define NOTE_FS7 2960
#define NOTE_G7  3136
#define NOTE_GS7 3322
#define NOTE_A7  3520
#define NOTE_AS7 3729
#define NOTE_B7  3951
#define NOTE_C8  4186
#define NOTE_CS8 4435
#define NOTE_D8  4699
#define NOTE_DS8 4978
#define REST      0

// change this to make the song slower or faster
int tempo = 140;

// change this to whichever pin you want to use
int buzzer = 11;

// notes of the moledy followed by the duration.
// a 4 means a quarter note, 8 an eighteenth , 16 sixteenth, so on
// !!negative numbers are used to represent dotted notes,
// so -4 means a dotted quarter note, that is, a quarter plus an eighteenth!!
int melody[] = {

  // We Wish You a Merry Christmas
  // Score available at https://musescore.com/user/6208766/scores/1497501

  NOTE_C5,4, //1
  NOTE_F5,4, NOTE_F5,8, NOTE_G5,8, NOTE_F5,8, NOTE_E5,8,
  NOTE_D5,4, NOTE_D5,4, NOTE_D5,4,
  NOTE_G5,4, NOTE_G5,8, NOTE_A5,8, NOTE_G5,8, NOTE_F5,8,
  NOTE_E5,4, NOTE_C5,4, NOTE_C5,4,
  NOTE_A5,4, NOTE_A5,8, NOTE_AS5,8, NOTE_A5,8, NOTE_G5,8,
  NOTE_F5,4, NOTE_D5,4, NOTE_C5,8, NOTE_C5,8,
  NOTE_D5,4, NOTE_G5,4, NOTE_E5,4,

  NOTE_F5,2, NOTE_C5,4, //8
  NOTE_F5,4, NOTE_F5,8, NOTE_G5,8, NOTE_F5,8, NOTE_E5,8,
  NOTE_D5,4, NOTE_D5,4, NOTE_D5,4,
  NOTE_G5,4, NOTE_G5,8, NOTE_A5,8, NOTE_G5,8, NOTE_F5,8,
  NOTE_E5,4, NOTE_C5,4, NOTE_C5,4,
  NOTE_A5,4, NOTE_A5,8, NOTE_AS5,8, NOTE_A5,8, NOTE_G5,8,
  NOTE_F5,4, NOTE_D5,4, NOTE_C5,8, NOTE_C5,8,
  NOTE_D5,4, NOTE_G5,4, NOTE_E5,4,
  NOTE_F5,2, NOTE_C5,4,

  NOTE_F5,4, NOTE_F5,4, NOTE_F5,4,//17
  NOTE_E5,2, NOTE_E5,4,
  NOTE_F5,4, NOTE_E5,4, NOTE_D5,4,
  NOTE_C5,2, NOTE_A5,4,
  NOTE_AS5,4, NOTE_A5,4, NOTE_G5,4,
  NOTE_C6,4, NOTE_C5,4, NOTE_C5,8, NOTE_C5,8,
  NOTE_D5,4, NOTE_G5,4, NOTE_E5,4,
  NOTE_F5,2, NOTE_C5,4,
  NOTE_F5,4, NOTE_F5,8, NOTE_G5,8, NOTE_F5,8, NOTE_E5,8,
  NOTE_D5,4, NOTE_D5,4, NOTE_D5,4,

  NOTE_G5,4, NOTE_G5,8, NOTE_A5,8, NOTE_G5,8, NOTE_F5,8, //27
  NOTE_E5,4, NOTE_C5,4, NOTE_C5,4,
  NOTE_A5,4, NOTE_A5,8, NOTE_AS5,8, NOTE_A5,8, NOTE_G5,8,
  NOTE_F5,4, NOTE_D5,4, NOTE_C5,8, NOTE_C5,8,
  NOTE_D5,4, NOTE_G5,4, NOTE_E5,4,
  NOTE_F5,2, NOTE_C5,4,
  NOTE_F5,4, NOTE_F5,4, NOTE_F5,4,
  NOTE_E5,2, NOTE_E5,4,
  NOTE_F5,4, NOTE_E5,4, NOTE_D5,4,

  NOTE_C5,2, NOTE_A5,4,//36
  NOTE_AS5,4, NOTE_A5,4, NOTE_G5,4,
  NOTE_C6,4, NOTE_C5,4, NOTE_C5,8, NOTE_C5,8,
  NOTE_D5,4, NOTE_G5,4, NOTE_E5,4,
  NOTE_F5,2, NOTE_C5,4,
  NOTE_F5,4, NOTE_F5,8, NOTE_G5,8, NOTE_F5,8, NOTE_E5,8,
  NOTE_D5,4, NOTE_D5,4, NOTE_D5,4,
  NOTE_G5,4, NOTE_G5,8, NOTE_A5,8, NOTE_G5,8, NOTE_F5,8,
  NOTE_E5,4, NOTE_C5,4, NOTE_C5,4,

  NOTE_A5,4, NOTE_A5,8, NOTE_AS5,8, NOTE_A5,8, NOTE_G5,8,//45
  NOTE_F5,4, NOTE_D5,4, NOTE_C5,8, NOTE_C5,8,
  NOTE_D5,4, NOTE_G5,4, NOTE_E5,4,
  NOTE_F5,2, NOTE_C5,4,
  NOTE_F5,4, NOTE_F5,8, NOTE_G5,8, NOTE_F5,8, NOTE_E5,8,
  NOTE_D5,4, NOTE_D5,4, NOTE_D5,4,
  NOTE_G5,4, NOTE_G5,8, NOTE_A5,8, NOTE_G5,8, NOTE_F5,8,
  NOTE_E5,4, NOTE_C5,4, NOTE_C5,4,

  NOTE_A5,4, NOTE_A5,8, NOTE_AS5,8, NOTE_A5,8, NOTE_G5,8, //53
  NOTE_F5,4, NOTE_D5,4, NOTE_C5,8, NOTE_C5,8,
  NOTE_D5,4, NOTE_G5,4, NOTE_E5,4,
  NOTE_F5,2, REST,4
};

// sizeof gives the number of bytes, each int value is composed of two bytes (16 bits)
// there are two values per note (pitch and duration), so for each note there are four bytes
int notes = sizeof(melody) / sizeof(melody[0]) / 2;

// this calculates the duration of a whole note in ms
int wholenote = (60000 * 4) / tempo;

int divider = 0, noteDuration = 0;

void setup() {
  // iterate over the notes of the melody.
  // Remember, the array is twice the number of notes (notes + durations)
  for (int thisNote = 0; thisNote < notes * 2; thisNote = thisNote + 2) {

    // calculates the duration of each note
    divider = melody[thisNote + 1];
    if (divider > 0) {
      // regular note, just proceed
      noteDuration = (wholenote) / divider;
    } else if (divider < 0) {
      // dotted notes are represented with negative durations!!
      noteDuration = (wholenote) / abs(divider);
      noteDuration *= 1.5; // increases the duration in half for dotted notes
    }

    // we only play the note for 90% of the duration, leaving 10% as a pause
    tone(buzzer, melody[thisNote], noteDuration * 0.9);

    // Wait for the specief duration before playing the next note.
    delay(noteDuration);

    // stop the waveform generation before the next note.
    noTone(buzzer);
  }
}

void loop() {
  // no need to repeat the melody.
}
```

title: Multitasking with Arduino?

Answers: 1

body:
I think the method suggested by chrisl is probably the best for you to use here.  If you want to make a more-conventional multitasking system, you would set a timer such as TIMER2 to the minimum time slice, then at the start of your code (after setup) you'd have something like this:

ISR(TIMER2_COMPA_vect)
{
  myIntHandler();
}

Here myIntHandler() does whatever needs to get done on each tick of TIMER2.  I use this general approach in my open-source DaqPort code to do simultaneous oscilloscope data acquisition and signal generation, while still handling serial commands in the background.
But that's probably overkill for your project. You can find out more about DaqPort at
<https://www.daqarta.com/dw_rraa.htm>