body:
seems i damaged one of my Nanos. i have to say i am new to Arduino and have basic electronik skills and i realized after shopping via amazon that the Nanos i have are clones with CH340G.
never the less they are working. i was building a light driven open/close circuit for my chickens. using L293D motordriver, LCD, photocell. my sketch was just reading the photocell and outputting it on the LCD. not yet using the L293D in the sketch but assembled it already (without Motors and MV+).
The program was running for ~ 2 minutes. i was testing the reading for the photocell and was wondering why at low light the reading was still quite high ~ 600+. then all disappeared from the LCD apart of the background light.
as i couldnt get it running i tried to upload Blink again -> not working

    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x96 code here
    ...
    avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x96
    Problem beim Hochladen auf das Board. Hilfestellung dazu unter http://www.arduino.cc/en/Guide/Troubleshooting#upload.

after a while i was reading about programmers so i turned another Nano into a ArduinoISP trying to write either Booloader or Sketch via ISP bypassing USB (as i understood the different articles)
which gave

    avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x15
    avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x15

    avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x14

    avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x01
    avrdude: stk500_initialize(): (a) protocol error, expect=0x14, resp=0x10
    avrdude: initialization failed, rc=-1
         Double check connections and try again, or use -F to override
         this check.

    avrdude: stk500_disable(): unknown response=0x12
    Der ausgewählte serielle Port avrdude: stk500_disable(): unknown response=0x12
     ist nicht vorhanden oder das Board ist nicht angeschlossen

then i used Atmega_Board_Detector and Atmega_Board_Programmer which both seem to work.
output of Boarddetector:

  Atmega chip detector.
  Written by Nick Gammon.
  Version 1.20
  Compiled on Dec 27 2018 at 15:13:27 with Arduino IDE 10808.
  Attempting to enter ICSP programming mode ...
  Entered programming mode OK.
  Signature = 0x1E 0x95 0x0F
  Processor = ATmega328P
  Flash memory size = 32768 bytes.
  LFuse = 0xFF
  HFuse = 0xDE
  EFuse = 0xFD
  Lock byte = 0xEF
  Clock calibration = 0x9E
  Bootloader in use: Yes
  EEPROM preserved through erase: No
  Watchdog timer always on: No
  Bootloader is 512 bytes starting at 7E00

  Bootloader:

  7E00: 0x11 0x24 0x84 0xB7 0x14 0xBE 0x81 0xFF 0xF0 0xD0 0x85 0xE0 0x80 0x93 0x81 0x00
  7E10: 0x82 0xE0 0x80 0x93 0xC0 0x00 0x88 0xE1 0x80 0x93 0xC1 0x00 0x86 0xE0 0x80 0x93
  7E20: 0xC2 0x00 0x80 0xE1 0x80 0x93 0xC4 0x00 0x8E 0xE0 0xC9 0xD0 0x25 0x9A 0x86 0xE0
  7E30: 0x20 0xE3 0x3C 0xEF 0x91 0xE0 0x30 0x93 0x85 0x00 0x20 0x93 0x84 0x00 0x96 0xBB
  7E40: 0xB0 0x9B 0xFE 0xCF 0x1D 0x9A 0xA8 0x95 0x81 0x50 0xA9 0xF7 0xCC 0x24 0xDD 0x24
  7E50: 0x88 0x24 0x83 0x94 0xB5 0xE0 0xAB 0x2E 0xA1 0xE1 0x9A 0x2E 0xF3 0xE0 0xBF 0x2E
  7E60: 0xA2 0xD0 0x81 0x34 0x61 0xF4 0x9F 0xD0 0x08 0x2F 0xAF 0xD0 0x02 0x38 0x11 0xF0
  7E70: 0x01 0x38 0x11 0xF4 0x84 0xE0 0x01 0xC0 0x83 0xE0 0x8D 0xD0 0x89 0xC0 0x82 0x34
  7E80: 0x11 0xF4 0x84 0xE1 0x03 0xC0 0x85 0x34 0x19 0xF4 0x85 0xE0 0xA6 0xD0 0x80 0xC0
  7E90: 0x85 0x35 0x79 0xF4 0x88 0xD0 0xE8 0x2E 0xFF 0x24 0x85 0xD0 0x08 0x2F 0x10 0xE0
  7EA0: 0x10 0x2F 0x00 0x27 0x0E 0x29 0x1F 0x29 0x00 0x0F 0x11 0x1F 0x8E 0xD0 0x68 0x01
  7EB0: 0x6F 0xC0 0x86 0x35 0x21 0xF4 0x84 0xE0 0x90 0xD0 0x80 0xE0 0xDE 0xCF 0x84 0x36
  7EC0: 0x09 0xF0 0x40 0xC0 0x70 0xD0 0x6F 0xD0 0x08 0x2F 0x6D 0xD0 0x80 0xE0 0xC8 0x16
  7ED0: 0x80 0xE7 0xD8 0x06 0x18 0xF4 0xF6 0x01 0xB7 0xBE 0xE8 0x95 0xC0 0xE0 0xD1 0xE0
  7EE0: 0x62 0xD0 0x89 0x93 0x0C 0x17 0xE1 0xF7 0xF0 0xE0 0xCF 0x16 0xF0 0xE7 0xDF 0x06
  7EF0: 0x18 0xF0 0xF6 0x01 0xB7 0xBE 0xE8 0x95 0x68 0xD0 0x07 0xB6 0x00 0xFC 0xFD 0xCF
  7F00: 0xA6 0x01 0xA0 0xE0 0xB1 0xE0 0x2C 0x91 0x30 0xE0 0x11 0x96 0x8C 0x91 0x11 0x97
  7F10: 0x90 0xE0 0x98 0x2F 0x88 0x27 0x82 0x2B 0x93 0x2B 0x12 0x96 0xFA 0x01 0x0C 0x01
  7F20: 0x87 0xBE 0xE8 0x95 0x11 0x24 0x4E 0x5F 0x5F 0x4F 0xF1 0xE0 0xA0 0x38 0xBF 0x07
  7F30: 0x51 0xF7 0xF6 0x01 0xA7 0xBE 0xE8 0x95 0x07 0xB6 0x00 0xFC 0xFD 0xCF 0x97 0xBE
  7F40: 0xE8 0x95 0x26 0xC0 0x84 0x37 0xB1 0xF4 0x2E 0xD0 0x2D 0xD0 0xF8 0x2E 0x2B 0xD0
  7F50: 0x3C 0xD0 0xF6 0x01 0xEF 0x2C 0x8F 0x01 0x0F 0x5F 0x1F 0x4F 0x84 0x91 0x1B 0xD0
  7F60: 0xEA 0x94 0xF8 0x01 0xC1 0xF7 0x08 0x94 0xC1 0x1C 0xD1 0x1C 0xFA 0x94 0xCF 0x0C
  7F70: 0xD1 0x1C 0x0E 0xC0 0x85 0x37 0x39 0xF4 0x28 0xD0 0x8E 0xE1 0x0C 0xD0 0x85 0xE9
  7F80: 0x0A 0xD0 0x8F 0xE0 0x7A 0xCF 0x81 0x35 0x11 0xF4 0x88 0xE0 0x18 0xD0 0x1D 0xD0
  7F90: 0x80 0xE1 0x01 0xD0 0x65 0xCF 0x98 0x2F 0x80 0x91 0xC0 0x00 0x85 0xFF 0xFC 0xCF
  7FA0: 0x90 0x93 0xC6 0x00 0x08 0x95 0x80 0x91 0xC0 0x00 0x87 0xFF 0xFC 0xCF 0x80 0x91
  7FB0: 0xC0 0x00 0x84 0xFD 0x01 0xC0 0xA8 0x95 0x80 0x91 0xC6 0x00 0x08 0x95 0xE0 0xE6
  7FC0: 0xF0 0xE0 0x98 0xE1 0x90 0x83 0x80 0x83 0x08 0x95 0xED 0xDF 0x80 0x32 0x19 0xF0
  7FD0: 0x88 0xE0 0xF5 0xDF 0xFF 0xCF 0x84 0xE1 0xDE 0xCF 0x1F 0x93 0x18 0x2F 0xE3 0xDF
  7FE0: 0x11 0x50 0xE9 0xF7 0xF2 0xDF 0x1F 0x91 0x08 0x95 0x80 0xE0 0xE8 0xDF 0xEE 0x27
  7FF0: 0xFF 0x27 0x09 0x94 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0x04 0x04

  MD5 sum of bootloader = 0xFB 0xF4 0x9B 0x7B 0x59 0x73 0x7F 0x65 0xE8 0xD0 0xF8 0xA5 0x08 0x12 0xE7 0x9F
  Bootloader name: optiboot_atmega328

  First 256 bytes of program memory:

  00: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  10: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  20: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  30: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  40: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  50: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  60: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  70: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  80: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  90: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  A0: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  B0: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  C0: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  D0: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  E0: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  F0: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF

  Programming mode off.
Output of Board Programmer:

  Atmega chip programmer.
  Written by Nick Gammon.
  Version 1.38
  Compiled on Dec 27 2018 at 15:15:38 with Arduino IDE 10808.
  Attempting to enter ICSP programming mode ...
  Entered programming mode OK.
  Signature = 0x1E 0x95 0x0F
  Processor = ATmega328P
  Flash memory size = 32768 bytes.
  LFuse = 0xFF
  HFuse = 0xDE
  EFuse = 0xFD
  Lock byte = 0xEF
  Clock calibration = 0x9E
  Type 'L' to use Lilypad (8 MHz) loader, or 'U' for Uno (16 MHz) loader ...
  Using Uno Optiboot 16 MHz loader.
  Bootloader address = 0x7E00
  Bootloader length = 512 bytes.
  Type 'Q' to quit, 'V' to verify, or 'G' to program the chip with the bootloader ...
  Erasing chip ...
  Writing bootloader ...
  Committing page starting at 0x7E00
  Committing page starting at 0x7E80
  Committing page starting at 0x7F00
  Committing page starting at 0x7F80
  Written.
  Verifying ...
  No errors found.
  Writing fuses ...
  LFuse = 0xFF
  HFuse = 0xDE
  EFuse = 0xFD
  Lock byte = 0xEF
  Clock calibration = 0x9E
  Done.
  Programming mode off.
  Type 'C' when ready to continue with another chip ...

other observations:
when trying to upload a sketch the rx LED blinks where thin a few times but not bright and at the speed it usually does. the L LED blinks at power on a few times.

i have 2 questions:

1. can you see anything in my circuit that could have damaged the NANO?

2. any idea to recover the NANO?

i am more curious on the first question as i don't want to take out another one. the second is more curiosity what can be done on a Nano.
and i am clueless why it died as i run all the experiments individually on an UNO

attached pictures and my fight with Fritzing for the schematics.
[![enter image description here][1]][1]
[![enter image description here][2]][2]
[![enter image description here][3]][3]
[![enter image description here][4]][4]
Many Thanks already

  [1]: https://i.stack.imgur.com/aNv8K.jpg
  [2]: https://i.stack.imgur.com/LrWQY.jpg
  [3]: https://i.stack.imgur.com/1R3Xu.jpg
  [4]: https://i.stack.imgur.com/hJgt1.jpg

UPDATE:
just recognized that also my working NANOs can not be programmed via ArduinoISP Sketch using a Programmer NANO. so as the tools from Nick Gammon.
are working https://github.com/nickgammon/arduino_sketches. i assume my chip is working and it is up to the USB Chip or connection.

UPDATE2:
my NANO is fully back in live. what ever happened seems to have corrupted my flash. so after the TIPs from @Majenko with the 10uF Cap between Reset and GND i was able to programm via a "Programmernano". but here is another catch
when you first flash bootloader and then right away flash a sketch via programmer as well, this erases again the bootloader. you can check this with the
Atmega chip detector.
Written by Nick Gammon.

  Bootloader is 2048 bytes starting at 7800

  Bootloader:

  7800: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  7810: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  7820: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  7830: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF

So i just flash the Bootloader via ArduinoISP and then connect the NANO directly to USB to flash a sketch

title: Nano damaged. Power LED OK. USB Detected. No Sketch upload. No Program running

Answers: 2

body:
Try replacing the diode as in this link, it worked for me: [https://forum.arduino.cc/index.php?topic=166089.0][1]

 A short on VCC might damage the diode.

As for the answer to the first question, yes there is a flaw in the design, if the external power is lost the LCD and the L293D will be powered from USB through the above diode.

"Small change" , see Juraj's comment below.

  [1]: https://forum.arduino.cc/index.php?topic=166089.0

body:
Based on the output from my sketches that you have posted, the CPU chip is fine (Atmega328P). Since you cannot program via the USB port is looks likely that the CH340G is damaged.

A fall-back position is to use another one of the sketches (Atmega_Hex_Uploader) in the link you posted, and upload code via the SPI interface. To make this work you need to purchase a micro-SD card interface as described [here](http://www.gammon.com.au/forum/?id=11638) for around $US 15.

As for why it failed, this should be investigated promptly. Possibly [the answer by Dorian](https://arduino.stackexchange.com/a/60064/10794) will help.


body:
i need some help for my masterthesis.
I plan an Light and Sound installation and for this I decided to use the shape of an Dodecahedron and I want to put LED RGB Pixel Stripes on the surfaces to light the space. Imagine it like a huge ceiling light in shape of a half Dodecahedron.

What I have:

 - 1 x Arduino Starter Kit
 - 4 x RGB LED Pixel Stripe: BTF-LIGHTING WS2811, 5M, 60 LEDs/m, 300LEDs RGB, DC12V
  - (0,3W/LED = 90W/5 M (1 LED Stripe) = 360 W/20 M an in total 40A (4 LED Stripes))
 - 2 x LED Stripe: Minger SMD 2835, 5m, 300 LEDs, Dimmable, 6000K Kaltweiß, DC12V
(?)

The half of the Dodecahedron has 6 surfaces. Each surface gets like 300 to 350 cm RGB LEDs and 150 cm of Cold White.

My plan is to program the RGB LEDs with Strobe-Light (10 Hz) and changing colours and at the End of the installation the Cold White ("Daylight") is lighten up the space. (But this is another challenge for me ;))

How to connect all of them with my Arduino Uno? Any ideas?
Thank you very much!

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

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

title: 20 m LED WS2811 Pixel Stripe 12 V

Answers: 2

body: So, addressable RGB LED strips.  You can drive each string from an Arduino output, or daisy chain the signal thru all of them and just pump out the needed data using Adafruit Neopixel library, or the FastLED library. Make multiple power connections to keep the amount of 12V current going thru any one strip to a reasonable level.

body:
Your big challenge is going to be power. Sum up the current requirements of ALL of your LED strips. Find a power supply that puts out ≈20% more than that. Read up on the max power you can pass through each strip, You can daisy-chain the power on multiple strips up to the current handling ability of the strips. Say the docs say a strip can pass max 5A through it, and each draws 1A. So you could chain the power connections of 5 of them one to the next, but no more than that. Also make sure you use power wire that's rated for your current needs. Remember your ground wires need to be heavy enough for your current needs as well. (The signal wires can be much lighter gauge.)

The signal lines don't need to follow the same topology as the power connections, but it's simpler to wire up if they do. (You could make the control lines of ALL of the LED strips in one long "snake" but run the power wires in a star pattern so the power wires don't exceed the current carrying limits of the strips or of your power wires. You could also wire both the power and the signal lines in a star pattern, and drive each point of the star with a separate Arduino pin.) You should be able to find a [**chart online that gives you the current carrying ability of different gauges of wire**][1]. There, too, use wire that's rated a little over the current need, just to be safe. (That chart also talks about maximum length of wire to keep the voltage drop below 2%, which is a good idea.)

  [1]: http://info.waytekwire.com/blog/automotive-wire-gauge-guide/


body:
    Arduino: 1.8.5 (Windows 10), Board: "Arduino/Genuino Uno"

    avrdude: can't open input file C:\Users\PETER_~1\AppData\Local\Temp\arduino_build_223764/nyu_probe_activity1_code.ino.hex: No such file or directory
    avrdude: read from file 'C:\Users\PETER_~1\AppData\Local\Temp\arduino_build_223764/nyu_probe_activity1_code.ino.hex' failed
    An error occurred while uploading the sketch
    Invalid library found in D:\programs\ArDuInO\arduino-1.8.5\libraries\OLED_Mono_I2C: D:\programs\ArDuInO\arduino-1.8.5\libraries\OLED_Mono_I2C
    Invalid library found in D:\programs\ArDuInO\arduino-1.8.5\libraries\OLED_Mono_I2C: D:\programs\ArDuInO\arduino-1.8.5\libraries\OLED_Mono_I2C

    This report would have more information with
    "Show verbose output during compilation"
    option enabled in File -> Preferences.

title: error while uploading a code

Answers: 0


body: I did a project with the Arduino Due and the libraries for the VS1053 MP3 Shield were not compatable with the Due. Are the libraries that work with the Uno compatable with the Arduino Mega?

title: Do the libraries of the Arduino Uno work with the Arduino Mega?

Answers: 1

body:
> Are the libraries that work with the Uno compatable with the Arduino Mega?

Sometimes.

They have a higher chance of being compatible, due to them both using the same AVR core, but since internal peripherals differ slightly there is a chance that, depending on what the library does, it won't work right.

You just have to try it and see.


body:
I'm new to PID.
My goal: control the motor to get it to run a given RPM by a potmeter (which is setpoint).
Sensor is optical (detects white line, reflections), counts 100 round in x amount of time. Small calculation gives detected RPM.
I'm using an Arduino and the PID library.

Now my question.
Let's say I've implemented the PID lib on the arduino. It all calculates and so on, but it gives a PID_value which I don't understand.

Ex:
setpoint = 5000
detected = 4999
received PID value = 40

It's my guess that this (or rather: all) PID-lib I'm using always gives a value between 0 and 255 and I have to map/scale that value to my AC trigger.
Could someone point me in the right direction? Thanks!

title: SIlly PID question using the PID library

Answers: 1

body:
See [PID Library - SetOutputLimits()](https://playground.arduino.cc/Code/PIDLibrarySetOutputLimits) - you can change the limits.

For a meaningful result you need to make the output do something reasonable to the speed. Since your detected speed is lower than the desired speed, you have found it outputs a positive value, which is good, as far as it goes. But you have to interpret that in the context of what you are currently sending to the motor. If you are using PWM to control the motor you could feed the output (40 in this case) to the motor. If that makes it go even slower hopefully the PID library will compensate.

It's hard to make more suggestions without seeing the code.


body:
I am working on a circuit that can record audio to an SD when a switch is HIGH and stop recording when the switch is LOW. I am using the TMRpcm library. I previously had an issue solved on these two forums[Recording Audio - Film Name Error][1]and [Trying to save .wav files with new name every loop][2]. These solutions solved my problem but have left me with a new one. Currently the audio recorded on the new code (which I have pasted below) results is a very noisy and muffled audio quality; while the audio recorded on the old code (also posted below) is very clear. Could this be a physical issue and if so what should I do about it? Or is it an issue I am missing in the code?

OLD CODE - provides good quality audio

    //////////////////////////////////////// SD CARD
    #include <SD.h>
    #include <SPI.h>
    #include <TMRpcm.h>
    #define SD_ChipSelectPin 10
    TMRpcm audio;
    //////////////////////////////////////// SWITCH CASE
    int audiofile = 0;     // # of recording
    unsigned long i = 0;
    bool recmode = 0;      // recording state
    //////////////////////////////////////// SWITCH
    int inPin = 2;         // input Switch Pin
    int state = HIGH;      // the current state switch
    int reading;           // the current reading from the switch

    void setup() {
      Serial.begin(9600);
      pinMode(A0, INPUT);  // Microphone
      pinMode(inPin, INPUT_PULLUP); // Switch
      //////////////////////////////////////// SD CARD
      SD.begin(SD_ChipSelectPin);
      audio.CSPin = SD_ChipSelectPin;
    }

    void loop() {

      reading = digitalRead(inPin);
      ////////////////////////////////////////
      while (i < 300000) {
        i++;
      }
      i = 0;
      ////////////////////////////////////////
      if (reading == LOW) {
        if (recmode == 0) {
          recmode = 1;

          Serial.println("Recording");

          audiofile++; // To move case
          switch (audiofile) {
            case 1: audio.startRecording("1.wav", 16000, A0); break;
            case 2: audio.startRecording("2.wav", 16000, A0); break;
            case 3: audio.startRecording("3.wav", 16000, A0); break;
            case 4: audio.startRecording("4.wav", 16000, A0); break;
            case 5: audio.startRecording("5.wav", 16000, A0); break;
            case 6: audio.startRecording("6.wav", 16000, A0); break;
            case 7: audio.startRecording("7.wav", 16000, A0); break;
            case 8: audio.startRecording("8.wav", 16000, A0); break;
            case 9: audio.startRecording("9.wav", 16000, A0); break;
            case 10: audio.startRecording("10.wav", 16000, A0); break;
          }
        }
      }
      ////////////////////////////////////////
      else if (reading == HIGH) {
        recmode = 0;

        Serial.println("Hung-Up");
        switch (audiofile) {
          case 1: audio.stopRecording("1.wav"); break;
          case 2: audio.stopRecording("2.wav"); break;
          case 3: audio.stopRecording("3.wav"); break;
          case 4: audio.stopRecording("4.wav"); break;
          case 5: audio.stopRecording("5.wav"); break;
          case 6: audio.stopRecording("6.wav"); break;
          case 7: audio.stopRecording("7.wav"); break;
          case 8: audio.stopRecording("8.wav"); break;
          case 9: audio.stopRecording("9.wav"); break;
          case 10: audio.stopRecording("10.wav"); break;
        }
      }
    }

NEW CODE - poor quality audio

    //////////////////////////////////////// SD CARD
    #include <SD.h>
    #include <SPI.h>
    #include <TMRpcm.h>
    #define SD_ChipSelectPin 10
    TMRpcm audio;
    //////////////////////////////////////// SWITCH CASE
    unsigned int i = 0;     // # of recording
    unsigned long d = 0;
    bool recmode = 0;      // recording state
    //////////////////////////////////////// SWITCH
    int inPin = 2;         // input Switch Pin
    int state = HIGH;      // the current state switch
    int reading;           // the current reading from the switch

    void setup() {
      //Serial.begin(9600);
      pinMode(A0, INPUT);  // Microphone
      pinMode(inPin, INPUT_PULLUP); // Switch
      //////////////////////////////////////// SD CARD
      SD.begin(SD_ChipSelectPin);
      audio.CSPin = SD_ChipSelectPin;
    }

    void loop() {
      char buffer[50];
      sprintf(buffer, "%i.wav", i++);
      reading = digitalRead(inPin);
      ////////////////////////////////////////
      while (d < 300000) {
        d++;
      }
      d = 0;
      ////////////////////////////////////////
      if (reading == LOW) {
        if (recmode == 0) {
          recmode = 1;

          //Serial.println("Recording");

          audio.startRecording(buffer, 1600, A0);
          //Serial.println(buffer);
        }
      }
      ////////////////////////////////////////
      else if (reading == HIGH) {
        recmode = 0;

        //Serial.println("Hung-Up");

        audio.stopRecording(buffer);
      }
    }

  [1]: https://forum.arduino.cc/index.php?topic=587263.0
  [2]: https://arduino.stackexchange.com/questions/60046/trying-to-save-wav-files-with-new-name-every-loop

title: New code results in audio noise

Answers: 1

body:
Old code:

    audio.startRecording("1.wav", 16000, A0);

New code:

    audio.startRecording(buffer, 1600, A0);

Spot the typo?


body:
Where is a comprehensive and authoritative list of commonly used library or built-in methods (functions) that do not work properly in Arduino interrupt service routines?

I am aware of the following:

* do not use delay()
* do not use Serial print methods

which are part of Nick Gammon's advice [linked here][1]. His TLDR summary is:

> TL;DR :
>
> When writing an Interrupt Service Routine (ISR):
>
>
>     Keep it short
>     Don't use delay ()
>     Don't do serial prints
>     Make variables shared with the main code volatile
>     Variables shared with main code may need to be
>                 protected by "critical sections" (see below)
>     Don't try to turn interrupts off or on

however, I am looking for, as I said, a list that is more comprehensive and authoritative.

  [1]: https://gammon.com.au/interrupts

title: comprehensive list of common library methods that do not work in interrupt service routines

Answers: 2

body:
The basic rule is quite simple, but the list is practically impossible to produce.

The rule is:

* You cannot use anything that relies on an interrupt to function from within an interrupt service routine.

AVR chips only have one interrupt priority. Only one interrupt routine can function at a time. If an interrupt fires whilst an ISR is currently executing that interrupt will be delayed until the ISR finishes.  If that ISR relies on a function that itself needs an ISR to fire (such as `millis()`, or serial transmission), then it will never get to finish.

A partial list of things to know:

* You cannot transmit serial more than there is room in the TX buffer for, or it blocks.
* The time generated by `millis()` (which `delay()` relies on) never changes.
* Servo motors cannot be controlled and will *jitter* if an interrupt routine takes too long.
* `tone()` generated sounds will also jitter since the ISR is delayed while another ISR is executing

And basically anything else that uses interrupts.

body:
> ... that do not work properly in Arduino interrupt service routines ...

A much safer approach would be to ask what **does** work properly in an ISR. Considering that my advice was to "keep it short" that would tend to exclude calling *any* functions except ones which are known to be OK. For example, calling `millis()` or `micros()` to find out the current timer values would be OK (bearing in mind that the figures returned by `millis()` will not increment).

Anything complex enough to be placed in a library would tend to be excluded simply based on that, in my opinion, unless *specifically documented otherwise*.

So, I wouldn't try to write files, do serial output, do I2C output, drive motors, etc.

Really, what an ISR should be doing is one or more of:

 * Setting a flag (eg. "key has been pressed")
 * Note the time (eg. "Pulse received at this moment")
 * Retrieve some value (eg. what number is in a timer register)

Then the main code, not in an ISR, does something lengthier with that data.

The other thing to be concerned about is: *Is a function re-entrant?*

Just as an example, if you are doing `strcpy` in an ISR, is the `strcpy` function coded to be re-entered? (I don't know the answer just now). If it is not re-entrant, and you happen to be doing a `strcpy` in the main code, and the ISR also does a `strcpy` then one of them will be corrupted.

---

In terms of getting a comprehensive list, that would be almost impossible. Some libraries are no longer maintained. Others might be maintained but change from one month to the next, and the change might affect how they work inside an ISR. This is like the question people ask about "which libraries use which timers or pins?". These questions are difficult or impossible to adequately answer.


body:
i realise this is probably the most common error that is asked about on this forum, but it is a major issue for me. i have an arduino lilypad main board (with the ATMega328P, boot loader already burned), and a generic FTDI serial to usb adapter plugged into my windows 10 laptop. When i try to upload the Blink program from the Arduino IDE, it fails with the error:

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

i am using a windows 10 laptop, the Arduino IDE from the windows store. this is a new lilypad, and i have never been able to upload to it. take note that when i reset the board, the pin13 light does flash (but  not the way the Blink program specifies, obviously.

i have already tried:

 - Rebooting my computer
 - Restarting the IDE
 - Turning the COM port on and off
 - Taking out the RX/TX wires from the FTDI converter
 - Pressing the reset button right before uploading (or during uploading)
 - Changing which board it is set as in the IDE
 - Unplugging and re-plugging the USB-Serial converter

[![my wiring, the USB end goes in to the laptop of course][1]][1]

if you have any other possible solutions they would be appreciated, thanks

  [1]: https://i.stack.imgur.com/1fZpq.jpg

title: avrdude: stk500_recv(): programmer is not responding: lilypad arduino

Answers: 1

body:
Last time I bought one of the Lilypads, it did not have a bootloader. I had to buy a SMD programmer adapter that presses down over the 328P chip to bootload it as the board did not break out the ICSP pins to any pads.  [![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/RZsRA.jpg

I think I got mine here https://hobbyking.com/en_us/atmel-atmega-socket-firmware-flashing-tool.html but I haven't seen them in stock for a while.  Very handy tool tho. Another option is to tack wires to the appropriate uC pins and, connected to a 2x3 header that your Programmer can connect to. Remove the wires when done.


body:
I need to read acceleration data with ADXL335 using ARDUINO MICRO (or NANO) and send this data with RS485 module to another RS485 module connected to an ARDUINO UNO (300m between RS485 modules). Treated to use the codes below but slave does not receives any data.
Data from AXDL335 are in the form "xxx  yyy  zzz"
Do I need to write in a "string format" before send with RS485 (master)??
Many thanks in advance!!

**master code**

    #include <SoftwareSerial.h>
    #define SSerialRX   10
    #define SSerialTX   11
    #define SSerialTxControl  3
    #define RS485Transmit  HIGH
    #define RS485Receive  LOW
    int x;                                                // channel X  ADXL335
    int y;                                                // channel Y  ADXL335
    int z;                                                // channel Z  ADXL335
    SoftwareSerial RS485Serial(SSerialRX, SSerialTX);
    void setup() {
      Serial.begin(9600);                                 // configure baud rate monitor

      pinMode(SSerialTxControl, OUTPUT);
      digitalWrite(SSerialTxControl, RS485Receive);
      RS485Serial.begin(4800);                            // starts serial(485) and configure baud rate
    }

    void loop() {

     x=analogRead(0);                                     //read X in analog(0)
     y=analogRead(1);                                     //read Y in analog(1)
     z=analogRead(2);                                     //read Z in analog(2)
                                                          // print read values in monitor
     Serial.print(x);Serial.print(" ");Serial.print(y);Serial.print(" ");Serial.print(z);Serial.println(" ");
     RS485Serial.print(x);
     delay (250);

     RS485Serial.flush();
     delay (750);
     }

*SLAVE CODE*

    #include <SoftwareSerial.h>
    #define SSerialRX   10
    #define SSerialTX   11
    #define SSerialTxControl  3
    #define RS485Transmit  HIGH
    #define RS485Receive  LOW
    char x;
    SoftwareSerial RS485Serial(SSerialRX, SSerialTX);

    void setup() {
      Serial.begin(9600);        // configure baud rate monitor
      pinMode(13, OUTPUT);
      pinMode(SSerialTxControl, OUTPUT);
      digitalWrite(SSerialTxControl, RS485Receive);
      RS485Serial.begin(4800);  // start serial(485) and configure baud rate
    }

    void loop()
    {
     if (RS485Serial.available()>0) {
      x = RS485Serial.read();
      if (x!="n")

      Serial.print(x);Serial.println(" ");
      delay(1000);

     }
    }

title: sending data with rs485

Answers: 0


body:
I wrote this code to control my christmas tree. It takes up the majority of the memory on my Arduino Uno:

    Sketch uses 31822 bytes (98%) of program storage space. Maximum is 32256 bytes.
    Global variables use 1882 bytes (91%) of dynamic memory, leaving 166 bytes for local variables. Maximum is 2048 bytes.
    Low memory available, stability problems may occur.

Does anyone know how I can reduce the memory usage?

Code:

    #include <SPI.h>
    #include <SdFat.h>
    #include <SdFatUtil.h>
    #include <SFEMP3Shield.h>

    #define TREEONE 3
    #define TREETWO 4
    #define TREETHREE 5
    #define TREEFOUR 10

    SdFat sd;
    SFEMP3Shield MP3player;

    const uint8_t volume = 10; // MP3 Player volume 0=max, 255=lowest (off)
    //10 for basement 50 for testing

    const uint16_t monoMode = 1;

    int song = 3;
    int num = 0;
    int count = 0;

    //put arrays here
    byte arrayTree[] = {17,16,9,8,3,2,5,4,17,16,9,8,3, ...etc };

    void setup() {
      initSD();
      initMP3Player();

      pinMode(TREEONE, OUTPUT);
      pinMode(TREETWO, OUTPUT);
      pinMode(TREETHREE, OUTPUT);
      pinMode(TREEFOUR, OUTPUT);

      digitalWrite(TREEONE, HIGH);
      digitalWrite(TREETWO, HIGH);
      digitalWrite(TREETHREE, HIGH);
      digitalWrite(TREEFOUR, HIGH);
    }

    void loop() {
      if(!MP3player.isPlaying()){
        MP3player.playTrack(song);
        MetallicaChristmas();
      }
    }

    void initSD() {
      if(!sd.begin(SD_SEL, SPI_HALF_SPEED))
        sd.initErrorHalt();
      if(!sd.chdir("/"))
        sd.errorHalt("sd.chdir");
    }

    void initMP3Player() {
      uint8_t result = MP3player.begin();
      MP3player.setVolume(volume, volume);
      MP3player.setMonoMode(monoMode);
    }

    void treeFunc() {
        //delay(arrayTimes[i]);
        num = arrayTree[count];

        //TREEONE
        if(num>15){
          if((num%2)==0){
            digitalWrite(TREEONE,HIGH);
          }else{
            digitalWrite(TREEONE,LOW);
          }
        }
        //TREETWO
        if((num)>7){
          if((num%2)==0){
            digitalWrite(TREETWO,HIGH);
          }else{
            digitalWrite(TREETWO,LOW);
          }
        }
        //TREETHREE
        if((num%8)>3){
          if((num%2)==0){
            digitalWrite(TREETHREE,HIGH);
          }else{
            digitalWrite(TREETHREE,LOW);
          }
        }
        //TREEFOUR
        if((num%4)>1){
          if((num%2)==0){
            digitalWrite(TREEFOUR,HIGH);
          }else{
            digitalWrite(TREEFOUR,LOW);
          }
        }
      count = count + 1;
    }

    void MetallicaChristmas()
    {
      //event 1
      delay(670);
      treeFunc();
      delay(248);
      treeFunc();
      //event 2
      delay(116);
      treeFunc();
      delay(248);
      treeFunc();
      //event 3
      delay(100);
      treeFunc();
      delay(248);
      treeFunc();
      //event 4
      delay(132);
      treeFunc();
      delay(248);
      treeFunc();
      //event 5
      delay(125);
      treeFunc();
      delay(248);
      treeFunc();
      //event 6

      ...etc.

title: How can I reduce the memory usage on my code?

Answers: 1

body:
As well as `PROGMEM` (as described in the comments), there are a couple of other efficiencies that you can make:

* A function call is expensive (takes a lot of code space), and you are performing a LOT of them!

  * The repetitious calls to `delay()` followed by `treeFunc()` are wasteful. Your commented-out line

            //delay(arrayTimes[i]);

     looks like you were going to do the right thing, so I’d restore that (use `count` instead of `i`) and put the `delay()` numbers in a new `int arrayTimes[]` array.

     `PROGMEM` this array too, of course!

  * Once you’ve done this, you can remove all the calls to `delay()`. You’ll be left with nothing but repeated calls to `treefunc()`, which you can replace with a single loop:

            for (count=0;count<sizeof(arrayTree);++count) {
               treeFunc();
            } // for
      Don’t forget to get rid of the `count = count + 1;` line from `treeFunc()` - it’s now in the `for` loop.

* Also expensive is calling the same function twice except with different parameters in both sides of the `if` in `treeFunc()`. Instead of:

        if (<condition>) {
           Function(1);
        } // if
        else {
           Function(0);
        } // else

 you can instead do:

        Function(<condition>);

 For this to work, you need to know that `HIGH` has the value `1` and `LOW` has the value `0` - and that a `true` condition has the value `1` and a `false` condition has the value `0`.

 So, you need to change the `if ()` slightly:

        digitalWrite(THREEONE, (num%2)>0);

* Finally, the mod `%` operator itself is very expensive, since it is effectively a division, and the Arduino chip doesn’t know how to divide - so the code to do so is large. But the code you’ve written is using binary arithmetic, which the Arduino can do instantly - you just have to write it as such.

 * Instead of `(num%2)>0` use `num & B0001`.
 * Instead of `(num%4)>1` use `num & B0010`.
 * Instead of `(num%8)>3` use `num & B0100`.
 * Instead of `(num)>7` use `num & B1000`.

You’ve probably copied the guts of this code from somewhere else, and while it works it isn’t very efficient. Writing the code as above will greatly reduce your code size, exchanging repeated calls for much smaller `PROGMEM` arrays.


body:
I'm doing a simple calculation with integers (on Arduino with ESP8266 12E), but I can't get the expected result and can't find the error. Can someone guide me?

    #define A      200
    #define B      A * 62
    #define C      500

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

       unsigned long aux = 0;

       aux = (B * 500) / C;    // (12400 * 500) / 500 = 12400
       Serial.printf("aux = %d\n", aux);
       aux = aux * C;          // 12400 * 500 = 6200000
       Serial.printf("aux = %d\n", aux);

       // ERROR: Should result in "500", but is resulting in "1922000"
       aux = aux / B;          // 6200000 / 12400 = 500

       Serial.printf("aux = %d\n", aux); // It's printing "1922000"
    }

title: Arduino: incorrect calculation of long integer

Answers: 3

body:
In your #define of B you missed parenthesis (). Change your definition to:

    #define B      (A * 62)

Without parenthesis you first divide 6200000 by 200 and then multiply result by 62, which is not what you intend.

body:
Fully-parenthesizing macros (as noted in [answer by dmz](https://electronics.stackexchange.com/a/414154/5185)) solves one class of problem.

Another thing you should do is, in any arithmetic expression which involves literal constants, use the `L` suffix on at least one of the constants involved if there's any chance the result will exceed 32767 (the maximum guaranteed-representable value for `int`). The type of an arithmetic operation in C is based on the types of the operands of that operation only; the type of the variable to which the result is assigned is irrelevant.

(edit)
For example:

    long q, r;
    unsigned char v = 231;
    unsigned char w = 197;

    q = v * w * 5;
    r = v * w * 5L;

`q` might contain 30927, since after the Usual Arithmetic Conversions (6.3.1.8) [in this case, the Integer Promotions (6.3.1.1-2)] all operands are of type `int` and it's possible for `INT_MAX` to be 32767 in which case each operation would be performed modulo 32768.

`r` will contain 227535, since the constant `5L` is of type `long` and thus all operations in this expression will be performed on values of type `long`.

body:
As explained in previous answers, fully parenthesizing the macros is the
standard solution to this problem in C. However, on Arduino you are
programming in C++, and in C++ it is considered good practice to replace
this usage of `#define` by explicit constants:

<!-- language: lang-c++ -->

    const int A = 200;
    const int B = A * 62;
    const int C = 500;

Not only this makes the initial problem go away, it also provides some
type safety: you can choose to give these constants other types (e.g.
`long`) if appropriate.


body:
I am using a XMG-996R servo motor. It is controlled by and Arduino Uno board. The problem is when I tell it to go to a certain angle, it will rotate to the desired position but then return to 0. The motor keeps rotating back and forth between the destination and 0 degrees. I tried this with different servos and they all do the same.

I am using 3 AA batteries as an external power supply. I have also tried using 4 AA batteries or a 9V battery. The same thing happens no matter the power supply.

My control wire is connected to the Arduino, positive is connected to the external power source. The negative is connected to the ground of the power source and the ground of the Arduino.

This is my code:

    include <Servo.h>

    Servo servo;

    void setup(){
       servo.attach(9);
       servo.write(90);
    }

    void loop(){

    }

I have also tried putting the write() into loop as well as putting ```servo.write()``` before ```servo.attach()```. neither of these methods made a difference.

What can I do to make the servo rotate to the given degree and stay at that degree? Thanks.

title: Servo motor rotates back to 0 after reaching destination

Answers: 0


body:
I recently bought a new ESP8266 because I'm pretty sure I used 5V instead of 3.3V on my old one.
But it seems the new one behaves the same as the old one.

I'm using the sketch:

https://i.stack.imgur.com/BZRd4.jpg

When I open up the serial monitor and type [b]AT [/b]I get not response (on the 115200 baud).
If I boot up the power supply while the device is connected I get this in the serial monitor:

    load 0x40100000, len 1856, room 16
    tail 0
    chksum 0x63
    load 0x3ffe8000, len 776, room 8
    tail 0
    chksum 0x02
    load 0x3ffe8310, len 552, room 8
    tail 0
    chksum 0x79
    csum 0x79

    2nd boot version : 1.5
      SPI Speed      : 40MHz
      SPI Mode       : DOUT
      SPI Flash Size & Map: 8Mbit(512KB+512KB)
    jump to run user1 @ 1000

    Fatal exception 0(IllegalInstructionCause):
    epc1=0x40215021, epc2=0x00000000, epc3=0x00000000, excvaddr=0x00000000, depc=0x00000000

When I googled the log it seems to be related to the voltage. Could it be the same problem again? If so, what did I do wrong?

title: Problem with ESP8266, wrong voltage?

Answers: 1

body:
The ESP8266 has a relatively high peak current requirement compared to general microcontrollers. This is rarely fully understood. There is a lot of information on the Internet that says the current requirements is about 70mA. But that is a long term operational average. The peak current requirements can be as high as 1/2 an Amp.

When the ESP8266 starts one of the first things it does is an analog calibration. This is where it draws more current. If the power supply can not maintain the minimum required voltage at that current the voltage dip will cause a failure. The duration of this dip can be very short. A digital scope needed to see the fault.

I tend to recommend the use of ESP8266 modules that have an onboard regulator. Modules like the Wemos and Nodemcu type boards.

Using modules like the ESP-01 or the ESP-12 type modules (no regulators) are a lot more touchy. What you need to do is keep the 3.3v regulator as close as possible to those modules, and short solid connections. It also helps to have some additional capacitance across the 3.3v connections at the module.

Breadboards are convenient to use but they also can be the source of poor connections.

Consider what I have wrote here, how it applies to your setup. You may also want to solder an additional capacitor on the module. Vcc to ground. Something like 200-470uF, right onto the top of the module.


body:
I want to use a load cell (Capable of measuring up to 1 ton) connected to a arduino board.
I am a beginner, my questions are as follows :
1. How to calculate the current generated by the load cell ?
2. If current is too high, how will We make the arduino use the current to display weight ?

p.s If you know some helpful articles that might help me learn, please suggest.

title: Weight Measurement System using arduino and load cell

Answers: 4

body:
You need to use a load cell amplifier between the Arduino and the load cell. Load cells are around 350 Ohms. Four wire. And the signal that needs to be measured are very small.

The current will not be too high. The question indicates that you don't understand the application. (and therefore you are looking for help)

Here are some useful links.

https://www.hackster.io/MOHAN_CHANDALURU/hx711-load-cell-amplifier-interface-with-arduino-fa47f3

https://circuits4you.com/2016/11/25/hx711-arduino-load-cell/

A typical load cell has an output of 2 millivolts per volt of excitation voltage at the full rated weight. For example, if 5 volts were used for the excitation voltage, and the output is 2 mV/volt, then the voltage out would be 10mV at full scale. The voltage difference (compared to the unloaded load cell) is what is measure.

If the excitation voltage (just a technical name for applied voltage) were 5 volts, the voltage at the output terminals, measured from the negative terminal, would be 2.5 volts, half of the applied voltage. But this 2.5 volts is not the measured output. What is measured is the difference between the +signal and the -signal wires.

body:
My suggestion would be to make a spreadsheet with some items of known weights. Generally while using scales you’ll have a 5lb calibration weight that has a very tight tolerance. You can find the output voltage changes and map it from 0-1023.

This should mean for every 2.2lbs you will get another increment. Not extremely accurate but fine when measuring at the ton scale

body: That makes sense, most of my experience is with Mettler Toledo but I have never used the voltage for reference. A lot of the time hacking something together on Arduino requires mapping to values it likes. I had a few ultrasonic distance sensors that were just slightly different in the way they responded so I spent a while getting them just right.

body:
Get a multimeter and check the max output. That would be the best way to find it. If you actually have items around that weigh a literal ton that’d be the best way to find out the max current. Once that’s done you can split the current with a few resistors. If I recall correctly twice as much current would flow through a resistor with twice the value of the other. Make a y and pick the end that outputs the value you like. If you need 1/4 you should have a resistor for example with 47k and 3 together would be 141k. Connect to the 3 to get 1/4 the output current

Wikipedia has a pretty good article on <b> Current Dividers </b> if the output current is too high.


body:
I wrote this code to control my Christmas tree. It plays the Holy Night Code perfectly but never transitions to the next song. In addition, it plays random notes after the song is finished. Does anyone know what the error is?

    #include <SPI.h>
    #include <SdFat.h>
    #include <SdFatUtil.h>
    #include <SFEMP3Shield.h>

    #define TREEONE 3
    #define TREETWO 4
    #define TREETHREE 5
    #define TREEFOUR 10

    SdFat sd;
    SFEMP3Shield MP3player;

    const uint8_t volume = 10; // MP3 Player volume 0=max, 255=lowest (off)
    //10 for basement 50 for testing

    const uint16_t monoMode = 1;

    byte song = 1;
    byte totalsongs = 10;
    int num = 0;
    int i;

    //put arrays here
    const PROGMEM uint16_t arrayTimesMC[] = {670, 249, 116, 249, 100, 249, 132, 249, 125, 249, 102, 249, 116, 249, 82, 249, 130, 249, 118, 249, 94, 249, 125, 249, 100, 249, 110, 249, 95, 249, 134, 249, 156, 249, 125, 249, 107, 249, 142, 249, 110, 249, 73, 249, 96, 249, 119, 249, 115, 249, 83, 249, 101, 249, 168, 249, 120, 249, 111, 249, 108, 249, 102, 249, 104, 249, 106, 249, 115, 249, 122, 249, 136, 249, 100, 249, 99, 249, 136, 249, 138, 249, 113, 249, 111, 249, 117, 249, 148, 249, 115, 249, 102, 249, 100, 249, 108, 249, 140, 249, 115, 249, 93, 249, 148, 249, 119, 249, 91, 249, 136, 249, 84, 249, 185, 249, 104, 249, 126, 249, 148, 249, 83, 249, 74, 249, 97, 249, 105, 249, 166, 249, 128, 249, 95, 249, 158, 249, 122, 249, 220, 249, 42, 249, 66, 249, 180, 249, 387, 249, 236, 249, 350, 249, 3571, 249, 622, 249, 744, 249, 711, 249, 707, 249, 727, 249, 691, 249, 682, 249, 570, 198, 0, 249, 333, 249, 67, 249, 401, 249, 103, 249, 355, 249, 107, 249, 712, 249, 687, 249, 749, 249, 688, 249, 424, 249, 53, 249, 371, 249, 92, 249, 330, 249, 112, 249, 387, 249, 98, 249, 709, 249, 704, 249, 702, 249, 693, 249, 785, 249, 33, 147, 0, 171, 0, 249, 93, 249, 64, 124, 0, 165, 0, 249, 100, 249, 82, 149, 0, 137, 0, 249, 56, 249, 66, 148, 0, 142, 0, 249, 124, 249, 59, 216, 0, 190, 0, 249, 87, 249, 14, 171, 0, 105, 0, 74, 0, 249, 46, 249, 38, 150, 0, 183, 0, 249, 67, 249, 46, 152, 0, 192, 0, 249, 55, 249, 30, 182, 0, 136, 0, 172, 0, 166, 0, 249, 73, 162, 0, 160, 0, 175, 0, 141, 0, 249, 56, 179, 0, 158, 0, 155, 0, 160, 0, 249, 54, 249, 58, 249, 91, 119, 0, 112, 0, 162, 0, 200, 0, 136, 0, 152, 0, 181, 0, 199, 0, 249, 59, 249, 64, 122, 0, 142, 0, 156, 0, 216, 0, 154, 0, 130, 0, 160, 0, 209, 0, 249, 49, 249, 102, 125, 0, 132, 0, 205, 0, 224, 0, 158, 0, 164, 0, 162, 0, 172, 0, 174, 0, 139, 0, 173, 0, 148, 0, 169, 0, 170, 0, 113, 0, 178, 0, 170, 0, 108, 0, 124, 0, 249, 10, 144, 0, 100, 0, 208, 0, 138, 0, 249, 225, 215, 0, 249, 59, 249, 4, 249, 77, 249, 84, 249, 32, 249, 90, 249, 54, 249, 89, 249, 20, 89, 0, 249, 43, 249, 50, 249, 69, 249, 58, 249, 89, 249, 67, 249, 48, 249, 50, 249, 88, 249, 58, 249, 59, 249, 108, 249, 157, 239, 0, 249, 78, 249, 74, 249, 25, 249, 104, 249, 111, 249, 32, 249, 56, 249, 76, 249, 42, 249, 104, 249, 36, 249, 58, 249, 88, 249, 48, 249, 73, 249, 73, 249, 78, 249, 39, 249, 94, 249, 124, 249, 67, 249, 92, 249, 60, 249, 47, 150, 0, 169, 0, 249, 101, 249, 5, 166, 0, 144, 0, 249, 102, 249, 22, 196, 0, 173, 0, 249, 81, 249, 12, 136, 0, 209, 0, 249, 69, 249, 325, 249, 77, 249, 303, 249, 142, 249, 373, 249, 124, 249, 365, 249, 122, 249, 354, 249, 34, 249, 367, 249, 104, 249, 402, 249, 86, 249, 404, 249, 110, 249, 332, 249, 51, 249, 381, 249, 92, 249, 402, 249, 76, 249, 406, 249, 38, 249, 404, 249, 48, 249, 420, 249, 64, 249, 418, 249, 82, 249, 369, 249, 63, 249, 442, 249, 11, 249, 362, 249, 92, 249, 423, 249, 70, 249, 380, 249, 57, 249, 369, 249, 104, 249, 354, 249, 98, 249, 410, 249, 72, 249, 424, 249, 50, 249, 768, 249, 61, 170, 0, 131, 0, 153, 0, 206, 0, 249, 40, 129, 0, 162, 0, 146, 0, 184, 0, 249, 103, 129, 0, 156, 0, 131, 0, 186, 0, 249, 79, 176, 0, 131, 0, 141, 0, 194, 0, 249, 60, 146, 0, 154, 0, 135, 0, 201, 0, 249, 67, 147, 0, 155, 0, 143, 0, 194, 0, 249, 220, 102, 0, 104, 0, 249, 55, 249, 56, 249, 374, 249, 725, 249, 723, 249, 673, 249, 689, 249, 711, 249, 744, 249, 751, 249, 617, 249, 753, 249, 698, 249, 760, 249, 74, 161, 0, 212, 0, 249, 17, 249, 50, 132, 0, 172, 0, 249, 64, 249, 34, 149, 0, 191, 0, 249, 94, 249, 96, 124, 0, 151, 0, 249, 66, 249, 18, 203, 0, 146, 0, 228, 0, 132, 0, 249, 62, 162, 0, 170, 0, 175, 0, 162, 0, 249, 79, 164, 0, 218, 0, 166, 0, 148, 0, 249, 38, 249, 37, 249, 66, 123, 0, 138, 0, 166, 0, 194, 0, 166, 0, 155, 0, 165, 0, 165, 0, 249, 23, 249, 100, 142, 0, 162, 0, 150, 0, 172, 0, 142, 0, 136, 0, 168, 0, 249, 10, 249, 14, 249, 114, 151, 0, 249, 41, 162, 0, 249, 118, 249, 16, 163, 0, 152, 0, 249, 90, 249, 30, 167, 0, 167, 0, 249, 121, 249, 16, 192, 0, 168, 0, 249, 71, 249, 74, 123, 0, 163, 0, 249, 115, 249, 32, 155, 0, 166, 0, 249, 90, 249, 45, 139, 0, 149, 0, 249, 117, 249, 62, 182, 0, 189, 0, 249, 42, 249, 39, 142, 0, 173, 0, 145, 0, 156, 0, 249, 60, 183, 0, 141, 0, 155, 0, 182, 0, 249, 39, 175, 0, 170, 0, 155, 0, 149, 0, 249, 103, 249, 42, 249, 118, 118, 0, 132, 0, 136, 0, 222, 0, 134, 0, 136, 0, 162, 0, 184, 0, 249, 36, 249, 106, 142, 0, 120, 0, 140, 0, 232, 0, 184, 0, 139, 0, 158, 0, 214, 0, 239, 0, 249, 156, 110, 0, 112, 0, 228, 0, 192, 0, 168, 0, 146, 0, 176, 0, 172, 0, 163, 0, 112, 0, 173, 0, 239, 0, 120, 0, 172, 0, 146, 0, 173, 0, 140, 0, 136, 0, 191, 0, 92, 0, 125, 0, 165, 0, 162, 0, 216, 0, 249, 55, 158, 0, 128, 0, 249, 95, 249, 60, 221, 0, 127, 0, 249, 102, 249, 24, 148, 0, 155, 0, 249, 74, 249, 62, 153, 0, 138, 0, 249, 115, 249, 64, 165, 0, 147, 0, 249, 77, 249, 56, 143, 0, 163, 0, 249, 100, 249, 58, 168, 0, 146, 0, 249, 80, 249, 45, 158, 0, 168, 0, 249, 110, 249, 31, 168, 0, 134, 0, 249, 38, 104, 0, 187, 0, 134, 0, 160, 0, 132, 0, 135, 0, 142, 0, 249, 108, 145, 0, 157, 0, 154, 0, 152, 0, 249, 82, 136, 0, 163, 0, 165, 0, 146, 0, 249, 459, 117, 0, 146, 0, 249, 90, 130, 0, 166, 0, 154, 0, 194, 0, 249, 68, 154, 0, 140, 0, 158, 0, 168, 0, 249, 97, 155, 0, 146, 0, 134, 0, 184, 0, 249, 708, 249, 710, 249, 741, 249, 708, 249, 419, 126, 0, 119, 0, 82, 0, 112, 0, 84, 0, 98, 0, 86, 0, 109, 0, 98, 0, 113, 0, 249, 63, 55, 0, 158, 0, 135, 0, 210, 0, 161, 0, 138, 0, 249, 61, 141, 0, 195, 0, 139, 0, 155, 0, 223, 0, 248};
    const PROGMEM byte arrayTreeMC[] = {17, 16, 9, 8, 3, 2, 5, 4, 17, 16, 9, 8, 3, 2, 5, 4, 17, 16, 9, 8, 3, 2, 5, 4, 17, 16, 9, 8, 3, 2, 5, 4, 17, 16, 9, 8, 3, 2, 5, 4, 17, 16, 9, 8, 3, 2, 5, 4, 17, 16, 9, 8, 3, 2, 5, 4, 17, 16, 9, 8, 3, 2, 5, 4, 17, 16, 9, 8, 3, 2, 5, 4, 17, 16, 9, 8, 3, 2, 5, 4, 17, 16, 9, 8, 3, 2, 5, 4, 17, 16, 9, 8, 3, 2, 3, 2, 5, 4, 9, 8, 17, 16, 9, 8, 17, 16, 9, 8, 3, 2, 3, 2, 5, 4, 9, 8, 17, 16, 9, 8, 17, 16, 9, 8, 3, 2, 3, 2, 5, 4, 9, 8, 17, 16, 9, 8, 17, 16, 9, 8, 3, 2, 3, 2, 5, 4, 9, 8, 17, 16, 5, 4, 9, 8, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 3, 2, 3, 2, 5, 4, 5, 4, 9, 8, 17, 16, 17, 16, 17, 16, 31, 30, 31, 30, 31, 30, 31, 30, 5, 4, 5, 4, 3, 2, 3, 2, 5, 4, 9, 8, 17, 16, 9, 8, 31, 30, 31, 30, 31, 30, 31, 30, 3, 2, 5, 4, 3, 2, 17, 16, 3, 2, 5, 4, 3, 2, 17, 16, 3, 2, 5, 4, 3, 2, 17, 16, 3, 2, 5, 4, 3, 2, 17, 16, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 5, 4, 11, 10, 17, 16, 15, 14, 3, 2, 5, 4, 17, 16, 3, 2, 5, 4, 3, 2, 9, 8, 3, 2, 3, 2, 3, 2, 5, 4, 9, 8, 17, 16, 17, 16, 17, 16, 9, 8, 5, 4, 3, 2, 3, 2, 3, 2, 5, 4, 9, 8, 17, 16, 17, 16, 17, 16, 17, 16, 9, 8, 5, 4, 3, 2, 17, 16, 9, 8, 5, 4, 3, 2, 5, 4, 9, 8, 17, 16, 9, 8, 5, 4, 3, 2, 17, 16, 9, 8, 5, 4, 3, 2, 5, 4, 9, 8, 17, 16, 9, 8, 5, 4, 3, 2, 17, 16, 9, 8, 5, 4, 3, 2, 17, 16, 9, 8, 5, 4, 3, 2, 17, 16, 9, 8, 5, 4, 3, 2, 17, 16, 9, 8, 5, 4, 3, 2, 5, 4, 9, 8, 17, 16, 5, 4, 3, 2, 5, 4, 5, 4, 5, 4, 9, 8, 17, 16, 5, 4, 9, 8, 9, 8, 9, 8, 17, 16, 13, 12, 3, 2, 3, 2, 5, 4, 9, 8, 9, 8, 17, 16, 9, 8, 3, 2, 5, 4, 9, 8, 9, 8, 9, 8, 17, 16, 3, 2, 5, 4, 5, 4, 5, 4, 9, 8, 9, 8, 9, 8, 17, 16, 17, 16, 17, 16, 5, 4, 3, 2, 3, 2, 5, 4, 5, 4, 5, 4, 9, 8, 17, 16, 3, 2, 5, 4, 5, 4, 9, 8, 17, 16, 9, 8, 3, 2, 5, 4, 3, 2, 9, 8, 3, 2, 5, 4, 3, 2, 17, 16, 3, 2, 5, 4, 3, 2, 17, 16, 3, 2, 5, 4, 3, 2, 17, 16, 17, 16, 3, 2, 3, 2, 5, 4, 9, 8, 17, 16, 9, 8, 17, 16, 9, 8, 3, 2, 3, 2, 5, 4, 9, 8, 17, 16, 9, 8, 17, 16, 9, 8, 3, 2, 3, 2, 5, 4, 9, 8, 17, 16, 9, 8, 17, 16, 9, 8, 3, 2, 3, 2, 5, 4, 9, 8, 17, 16, 9, 8, 17, 16, 9, 8, 3, 2, 3, 2, 5, 4, 9, 8, 17, 16, 9, 8, 17, 16, 9, 8, 3, 2, 3, 2, 5, 4, 9, 8, 17, 16, 9, 8, 17, 16, 31, 30, 31, 30, 17, 16, 9, 8, 17, 16, 9, 8, 31, 30, 17, 16, 9, 8, 17, 16, 9, 8, 31, 30, 17, 16, 9, 8, 17, 16, 9, 8, 31, 30, 17, 16, 9, 8, 17, 16, 9, 8, 31, 30, 17, 16, 9, 8, 17, 16, 9, 8, 31, 30, 17, 16, 9, 8, 17, 16, 9, 8, 31, 30, 17, 16, 9, 8, 17, 16, 17, 16, 3, 2, 5, 4, 9, 8, 17, 16, 31, 30, 5, 4, 9, 8, 17, 16, 3, 2, 5, 4, 9, 8, 17, 16, 3, 2, 5, 4, 3, 2, 9, 8, 3, 2, 5, 4, 3, 2, 17, 16, 3, 2, 5, 4, 3, 2, 9, 8, 3, 2, 5, 4, 3, 2, 17, 16, 3, 2, 3, 2, 3, 2, 5, 4, 9, 8, 17, 16, 17, 16, 17, 16, 9, 8, 5, 4, 3, 2, 3, 2, 3, 2, 5, 4, 9, 8, 17, 16, 17, 16, 17, 16, 17, 16, 9, 8, 5, 4, 3, 2, 17, 16, 9, 8, 5, 4, 3, 2, 5, 4, 9, 8, 17, 16, 9, 8, 5, 4, 3, 2, 17, 16, 9, 8, 5, 4, 3, 2, 5, 4, 9, 8, 17, 16, 9, 8, 9, 8, 17, 16, 3, 2, 5, 4, 3, 2, 5, 4, 9, 8, 17, 16, 9, 8, 17, 16, 3, 2, 5, 4, 3, 2, 5, 4, 11, 10, 21, 20, 11, 10, 21, 20, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 3, 2, 3, 2, 3, 2, 5, 4, 9, 8, 17, 16, 17, 16, 17, 16, 9, 8, 5, 4, 3, 2, 3, 2, 3, 2, 5, 4, 9, 8, 17, 16, 17, 16, 17, 16, 17, 16, 9, 8, 5, 4, 3, 2, 17, 16, 9, 8, 5, 4, 3, 2, 5, 4, 9, 8, 17, 16, 9, 8, 5, 4, 3, 2, 17, 16, 9, 8, 5, 4, 3, 2, 5, 4, 9, 8, 17, 16, 9, 8, 5, 4, 3, 2, 17, 16, 9, 8, 5, 4, 3, 2, 17, 16, 9, 8, 5, 4, 3, 2, 3, 2, 5, 4, 9, 8, 17, 16, 9, 8, 5, 4, 3, 2, 5, 4, 9, 8, 17, 16, 13, 12, 11, 10, 21, 20, 11, 10, 21, 20, 3, 2, 11, 10, 29, 28, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 21, 20, 11, 10, 21, 20, 11, 10, 31, 30, 11, 10, 21, 20, 11, 10, 31, 30, 11, 10, 21, 20, 11, 10, 31, 30, 11, 10, 21, 20, 11, 10, 31, 30, 11, 10, 21, 20, 11, 10, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 21, 20, 11, 10, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 5, 4, 9, 8, 3, 2, 17, 16, 5, 4, 9, 8, 3, 2, 17, 16, 5, 4, 9, 8, 3, 2, 5, 4, 17, 16, 3, 2, 9, 8, 5, 4, 17, 16, 3, 2, 5, 4, 9, 8, 3, 2, 17, 16, 5, 4, 31, 30};
    const PROGMEM uint16_t arrayTimesHN[] = {28, 246, 1542, 246, 646, 246, 390, 246, 38, 246, 1222, 246, 70, 246, 358, 246, 70, 246, 326, 246, 70, 246, 1542, 246, 326, 246, 70, 246, 358, 246, 70, 246, 650, 246, 290, 246, 70, 246, 680, 246, 320, 246, 70, 246, 1550, 246, 1540, 246, 640, 246, 330, 246, 70, 246, 1250, 246, 70, 246, 360, 246, 70, 246, 330, 246, 0, 246, 1550, 246, 390, 246, 0, 246, 360, 246, 70, 246, 650, 246, 320, 246, 100, 246, 620, 246, 360, 246, 70, 246, 1540, 246, 1250, 246, 40, 246, 650, 246, 670, 246, 650, 246, 650, 246, 350, 246, 40, 246, 360, 246, 40, 246, 640, 246, 360, 246, 40, 246, 610, 246, 680, 246, 620, 246, 710, 246, 350, 246, 40, 246, 330, 246, 70, 246, 1540, 246, 680, 246, 640, 246, 650, 246, 360, 246, 40, 246, 630, 246, 660, 246, 640, 246, 360, 246, 70, 246, 650, 246, 640, 246, 330, 246, 70, 246, 330, 246, 70, 246, 640, 246, 650, 246, 640, 246, 360, 246, 70, 246, 620, 246, 640, 246, 650, 246, 360, 246, 70, 246, 610, 246, 680, 246, 640, 246, 330, 246, 100, 246, 650, 246, 610, 246, 360, 246, 70, 246, 360, 246, 40, 246, 640, 246, 650, 246, 640, 246, 650, 246, 680, 246, 610, 246, 650, 246, 680, 246, 610, 246, 650, 246, 670, 246, 650, 246, 680, 246, 640, 246, 650, 246, 360, 246, 40, 246, 640, 246, 650, 246, 250, 246, 250, 246, 246};
    const PROGMEM byte arrayTreeHN[] = {31, 30, 17, 16, 17, 16, 17, 16, 9, 8, 9, 8, 5, 4, 5, 4, 9, 8, 5, 4, 3, 2, 5, 4, 5, 4, 9, 8, 17, 16, 5, 4, 17, 16, 9, 8, 5, 4, 3, 2, 5, 4, 31, 30, 31, 30, 31, 30, 17, 16, 17, 16, 9, 8, 9, 8, 5, 4, 5, 4, 9, 8, 5, 4, 3, 2, 31, 30, 5, 4, 9, 8, 17, 16, 7, 6, 17, 16, 9, 8, 5, 4, 3, 2, 5, 4, 31, 30, 31, 30, 9, 8, 9, 8, 5, 4, 17, 16, 9, 8, 5, 4, 9, 8, 3, 2, 9, 8, 5, 4, 9, 8, 9, 8, 9, 8, 5, 4, 17, 16, 9, 8, 5, 4, 9, 8, 3, 2, 9, 8, 5, 4, 3, 2, 21, 20, 21, 20, 5, 4, 9, 8, 5, 4, 21, 20, 21, 20, 21, 20, 9, 8, 3, 2, 11, 10, 11, 10, 17, 16, 17, 16, 17, 16, 9, 8, 21, 20, 29, 28, 21, 20, 9, 8, 3, 2, 19, 18, 19, 18, 23, 22, 9, 8, 5, 4, 19, 18, 19, 18, 5, 4, 9, 8, 17, 16, 11, 10, 11, 10, 17, 16, 5, 4, 17, 16, 17, 16, 11, 10, 11, 10, 5, 4, 3, 2, 21, 20, 21, 20, 17, 16, 3, 2, 19, 18, 13, 12, 15, 14, 29, 28, 21, 20, 9, 8, 5, 4, 3, 2, 5, 4, 19, 18, 31, 30, 31, 30, 31, 30, 30};

    //put arrays here

    void setup() {
      initSD();
      initMP3Player();

      pinMode(TREEONE, OUTPUT);
      pinMode(TREETWO, OUTPUT);
      pinMode(TREETHREE, OUTPUT);
      pinMode(TREEFOUR, OUTPUT);

      digitalWrite(TREEONE, HIGH);
      digitalWrite(TREETWO, HIGH);
      digitalWrite(TREETHREE, HIGH);
      digitalWrite(TREEFOUR, HIGH);
    }

    void loop() {
      MP3player.playTrack(2);
      OHolyNight();
      delay(92000);
      MP3player.stopTrack();

      MP3player.playTrack(3);
      MetallicaChristmas();
      delay(192000);
      MP3player.stopTrack();
    }

    void initSD() {
      if (!sd.begin(SD_SEL, SPI_HALF_SPEED))
        sd.initErrorHalt();
      if (!sd.chdir("/"))
        sd.errorHalt("sd.chdir");
    }

    void initMP3Player() {
      uint8_t result = MP3player.begin();
      MP3player.setVolume(volume, volume);
      MP3player.setMonoMode(monoMode);
    }

    void AllLights() {
      digitalWrite(TREEONE, LOW);
      digitalWrite(TREETWO, LOW);
      digitalWrite(TREETHREE, LOW);
      digitalWrite(TREEFOUR, LOW);
    }

    void MetallicaChristmas() {
      for (i = 0; i < sizeof(arrayTimesMC); i++) {
        delay(pgm_read_word_near(arrayTimesMC + i));
        num = pgm_read_byte_near(arrayTreeMC + i);

        if (num > 15) {
          if ((num % 2) == 0) {
            digitalWrite(TREEONE, HIGH);
          } else {
            digitalWrite(TREEONE, LOW);
          }
        }
        if ((num % 16) > 7) {
          if ((num % 2) == 0) {
            digitalWrite(TREETWO, HIGH);
          } else {
            digitalWrite(TREETWO, LOW);
          }
        }
        if ((num % 8) > 3) {
          if ((num % 2) == 0) {
            digitalWrite(TREETHREE, HIGH);
          } else {
            digitalWrite(TREETHREE, LOW);
          }
        }
        if ((num % 4) > 1) {
          if ((num % 2) == 0) {
            digitalWrite(TREEFOUR, HIGH);
          } else {
            digitalWrite(TREEFOUR, LOW);
          }
        }
        if (i == sizeof(arrayTimesMC)) {
          break;
        }
      }
    }

    void OHolyNight() {
      for (i = 0; i < sizeof(arrayTimesHN); i++) {
        delay(pgm_read_word_near(arrayTimesHN + i));
        num = pgm_read_byte_near(arrayTreeHN + i);

        if (num > 15) {
          if ((num % 2) == 0) {
            digitalWrite(TREEONE, HIGH);
          } else {
            digitalWrite(TREEONE, LOW);
          }
        }
        if ((num % 16) > 7) {
          if ((num % 2) == 0) {
            digitalWrite(TREETWO, HIGH);
          } else {
            digitalWrite(TREETWO, LOW);
          }
        }
        if ((num % 8) > 3) {
          if ((num % 2) == 0) {
            digitalWrite(TREETHREE, HIGH);
          } else {
            digitalWrite(TREETHREE, LOW);
          }
        }
        if ((num % 4) > 1) {
          if ((num % 2) == 0) {
            digitalWrite(TREEFOUR, HIGH);
          } else {
            digitalWrite(TREEFOUR, LOW);
          }
        }
        if (i == sizeof(arrayTimesHN)) {
          break;
        }
      }
    }

title: Problem with MP3 Shield and function calling combination

Answers: 1

body:
Since KIIV didn't write an answer to this question, I will do it.

You are using this for loop:

    for (i = 0; i < sizeof(arrayTimesHN); i++)

The `sizeof()` function will return the size of the array in bytes. Since the array is of type `uint16_t`, each element has a size of 2 bytes (16 bit). Concluding: The `sizeof()` function will return a number twice as high, as the actual element count of the array. The delays and state number, that you use for the LEDs, will be read from memory, that lies after the array. We don't know, what is saved there (or if there is actually some valid data or only random data), so this will seem random. That random notes are played by the MP3 Player must be a problem with the library (I'm not sure about that). What does the library do, if a song is finished, but you didn't call the `stopTrack()` method yet?

---

In the LED functions (for example `OHolyNight()`) you are using delays, but you also set a big delay after the execution of the function. I guess, the big delay is the duration of the song. So you delay twice. The first comes with the accumulated delays in the LED function (while the LED lights are changing). The second delay will kick in after that (when the LED function is finished). Maybe you thought, that it doesn't proceed to the next song, because you didn't wait for 92 seconds (your first big delay).

---

Lastly, in your LED functions you have this if statement:

    if (i == sizeof(arrayTimesHN)) {
      break;
    }

This is unnecessary, you used a for loop with the condition `i < sizeof(arrayTimesHN)`, so that `i` cannot ever be equal to `sizeof(arrayTimesHN)` inside of the loop.


body:
In my limited testing it appears that the EEPROM in the Wemos D1 is not initialized to 255 like the specs say is the case for AtMega based Arduinos. In fact, the values look to be more-or-less random. Presumably this is because the ESP8266 doesn't actually contain EEPROM, but instead emulates it using flash. Is there a way to initialize the EEPROM region when flashing?

(This is pretty much the same question as [here][1], which has not been answered.) Since I need only a few bytes of data, I'd prefer not to have to use the SPIFS.

Update:

Use case: I'm using the WiFiManager library to select the network to connect a Wemos D1 mini to the web to upload data to Thingspeak. I'd like to use WiFiManager to request the api-key and channel id from the user. However, once the user has entered these, I'd prefer not to make them enter the values again. (The api key is 16 random looking chars and difficult to enter correctly.) This means that the device has to store the values persistently between boots - the main use case for EEPROM. But how do you tell that the values in EEPROM (actually flash on an ESP device) are uninitialized crap, not the previous value? As suggested in the comments, setting flag values in a number of vars make it statistically unlikely to the random values from uninitialized memory. On an AtMega device, unless previously used, the values will be 255 in each byte.

  [1]: https://arduino.stackexchange.com/questions/46519/set-eeprom-to-initial-values-when-flashing-esp8266

title: Value of uninitialized EEPROM in ESP8266?

Answers: 3

body:
I've done this in the past by simply checking for a string (array of characters if you prefer) at a specific memory location. I used "INITIALIZED". It would be very unlikely for the ROM to have this sequence of characters by accident. If I find the string I read the variables from ROM. If I don't, I write the string and set default values for the variables.

I found a slightly different example that uses the same technique:

    // EEPROM library.
    #include <EEPROM.h>
    // Persistent Shoe State.
    byte shoeState = 0;
    // Number of Shoe States.
    #define SHOE_STATE_MAX 3

    // setup() runs once at reset.
    void setup() {
      // EEPROM Init Code Base Address
      #define EEPROM_INIT_CODE_ADDR 0x00
      // Check EEPROM Init Code
      byte shoeStateInit[] = {0xde, 0xad, 0xbe, 0xaf, 0xaa};
      for(int b = EEPROM_INIT_CODE_ADDR; b < EEPROM_INIT_CODE_ADDR + sizeof(shoeStateInit); b++) {
        // EEPROM = Init Code?
        if(EEPROM.read(b) != shoeStateInit[b]) {
          // No, Write Init Code to EEPROM.
          EEPROM.write(b, shoeStateInit[b]);
          // Set Not Initialized Flag.
          shoeState = -1;
        }
      }
      // EEPROM Init Code?
      if(shoeState == 0) {
        // Yes, Read Shoe State from EEPROM.
        shoeState = EEPROM.read(sizeof(shoeStateInit));
      }
    }

The only variable being saved to ROM is shoeState.

body:
Calculate a checksum for the data and store as part of the data. Recalculate the checksum when you read the (questionable) data back again. If the checksum fails, it's invalid. If it passes, the data is valid to some statistical level of confidence.

A 16-bit checksum would make false acceptance highly unlikely, but  make it long enough for your own comfort level. What would be the worst consequence of a false acceptance: inconvenience (user has to re-enter a number)? Loss of money or property? Loss of life? Choose the complexity of your solution accordingly.

body:
Rather than use EEPROM, which is a real pain considering that it's shared between all stored data and you need to remember offsets and lengths, use SPIFFS.

By including `FS.h` in your program (or the include file that needs to store the data, if you are trying to be modular), you can store several megabytes of data as strings in a named file (much like fprintf() or open() would let you do in C++).

Call  `SPIFFS.begin();`  in setup(), and then use the following sections of code to read or write data to the file:

(assuming you want to store `start` and `end` in SPIFFS, but this works for any datatype known to Arduino, and probably anything with the printable attribute)

Read saved config:

    Serial.println(F("Loading config"));
    File f = SPIFFS.open("/ACTIVE_TIMES.cnf", "r");
    if (!f) {
      //File does not exist -- first run or someone called format()
      //Will not create file; run save code to actually do so (no need here since
      //it's not changed)
      Serial.println(F("Failed to open config file"));
      start = 8;
      end = 20; // defaults
      return;
    }
    while (f.available()) {
      String key = f.readStringUntil('=');
      String value = f.readStringUntil('\r');
      f.read();
      Serial.println(key + F(" = [") + value + ']');
      Serial.println(key.length());
      if (key == F("START_TIME")) {
        start = value.toInt();
      }
      if (key == F("END_TIME")) {
        end = value.toInt();
      }
    }
    f.close();
Save configuration:

    Serial.println(F("Saving config"));
    File f = SPIFFS.open("/ACTIVE_TIMES.cnf", "w+");
    if (!f) {
      //It's cases like this when calling SPIFFS.format() might be a good idea,
      //but you would not want to do so here, since if it's an error for a
      //different reason it would delete all your data. Make it manual or a prompt
      //instead.
      Serial.println(F("Failed to open config file"));
      return;
    }
    f.print(F("START_TIME="));
    f.println(start);
    f.print(F("END_TIME="));
    f.println(end);
    f.flush();
    f.close();
    Serial.println(F("Saved values"));

You may also call `SPIFFS.format()` to reset the filesystem (say, for a factory reset), but this will cause issues on attempting to read any stored data, since the file *will not exist*. Thus, have a section that sets reasonable defaults (or just prompts the user to set the values).

Note: Since this is for storing an API key and such, just have it fail, since the API key not working is a good notice the user needs to configure it, and you do NOT want to ship a product with a *working* API key that belongs to you rather than the user.

Final warning: Note carefully the use of `F()` around certain items in that code. This macro, specific to Arduino, allows one to store data in Flash ONLY, where strings normally consume RAM as well (once the system boots, it loads to RAM, since most code expects it there). The *benefit* of `F()`, rather than a progmem directive, is that many functions native to Arduino can read it directly thanks to overloads, or you can wrap `String()` around the `F()` to convert it to a string at runtime if the function does not allow that overload. The end result is that, as I've written it, this code should consume RAM only when it is actually running, as good code should (otherwise, it's really easy to use up all your RAM on such embedded devices if you add enough strings).

I have not bothered to do the latter with the filename passed to `open()` since it is used only once per load or save operation, does not support F() (thus I'd need to use the `String()` trick), and I'm fairly sure the compiler then shares the memory location, reducing the RAM used to only one edition of that filename.


body:
I try to detect commands given by user in Serial Monitor, but `strcmp` fails to flag as identical.

What do I do wrong ?

Is there a better way not reading as `String` and convert to `char` for comparison ?

Guy

    char* additional_callbacks [] = {"command_1", "command_2", "command_3"};

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

    void loop() {
      if (Serial.available() > 0) {
        char tmpchar[50];

        Serial.print("entered_text:");
        String str = Serial.readString();
        str.toCharArray(tmpchar, 50);
        Serial.println(tmpchar);

        for (int i = 0; i < sizeof(additional_callbacks) / sizeof(char*); i++) {
          if (strcmp(tmpchar, additional_callbacks[i]) == 0) {
            Serial.println("match");
          }
        }
        Serial.flush();
      }
      delay(50);
    }

title: String compare when using Serial

Answers: 2

body:
In your for() loop, use Serial.println() to display both strings before the compare. You'll be able to see why the compare is failing.

Update:

> it seemed identical.

Something has to be different for the test to fail. If the strings look identical then there must be some non-printing characters that differ: \r, \n, <space>, <tab>, missing \0 <end-of-string>), etc.

Try printing your buffers byte-by-byte in hex for a few more bytes than the string length, to be sure there is an <end-of-string> where it should be.

Or print the buffers with this hexdump function which lists a specified memory range in both ASCII and hex:

    /***

    Name:  hexdump

    Function:   Dump memory contents to terminal

    Description:Dump a specified range of memory in hex and ASCII

    Parameters: byte *mem       - starting address
                uint16_t len    - # of bytes

    Returns: void

    Notes:      Based on: http://grapsus.net/blog/post/Hexadecimal-dump-in-C
                Formats with sprintf(); outputs with Serial.print().
                Modified to print ...0 - ...F of each hex-block containing
                any of the requested memory range. Data not in the range are
                not shown.

    ***/

    void hexdump(byte *mem, uint16_t len)
    {
       byte *p, *pfirst, *plast;    // -> curr byte, first & last hex-blocks to print from
       char buf[10+1];              // sprintf o/p buffer

       // Print entire hex-blocks that contain the requested mem range,
       // except only show data within the range.
       pfirst = (byte *)((uint16_t)mem & 0xFFF0);           // beg of 1st  hex-block
       plast = (byte *)((uint16_t)(mem + len) | 0xF);       // end of last hex-block

       for( p = pfirst;  p <= plast;  ++p ){

          /* Print block addr */
          if( ((byte *)((uint16_t)p & 0xF)) == 0 ){
             sprintf_P(buf, PSTR("X: "), (unsigned int)p);
             Serial.print(buf);
          }

          // Print hex data, or if outside mem range, print spaces
          if( mem <= p && p < (mem + len) ){
             sprintf_P(buf, PSTR("hhX "), *p);
             Serial.print(buf);
          }
          else
             Serial.print("   ");                   // outside requested range - just spaces

          // Maybe print gutters and/or ASCII data
          if( ((uint16_t)p & 0xF) == 0x7 )
             Serial.print(" ");                     // narrow gutter after 8 bytes
          // If at end of hex block, print a gutter & re-print the block as ASCII
          if( ((uint16_t)p & 0xF) == 0xF ){
             Serial.print("  ");                    // wide gutter after 16 bytes

             // Print as ASCII.
             // Note: In this loop, we re-use the outer loop's index, 'p', to rescan
             // the hex block. We must leave 'p' as we found it!
             for( p = (byte *)((uint16_t)p & 0xFFF0);  ; ++p ){
                if( !(mem <= p && p < mem+len) )
                   Serial.print(' ');               // not in requested mem range
                else if( !isprint(*p) )
                   Serial.print('.');               // not printable
                else
                   Serial.print(*(char *)p);        // print as ASCII

                if( ((uint16_t)p & 0xF) == 0xF ){
                   break;                           // end of hex-block
                }
             }
             Serial.print('\n');
          }
       }
    }

body:
You try to compare Serial input

> command_1\r\n

with

> command_1

and these two are **not** equal.


body:
I am completely new to Arduino. I have been given a side project to display a image from SD card to display. LCD used is ILI9486 which has a SD card slot at the back of the display module. I have inserted an 1 GB micro SD card. I am using below example code to try to open the SD card and display the image on display module. I am getting error on serial monitor "Initializing sd card - failed". Can anyone let me know how to display image from SD card to screen.

    #include <SD.h>
    #include <SPI.h>
    #include <TFT.h>  // Arduino LCD library

    // pin definition for the Uno
    #define sd_cs  4
    #define lcd_cs 10
    #define dc     9
    #define rst    8

    TFT TFTscreen = TFT(lcd_cs, dc, rst);

    // this variable represents the image to be drawn on screen
    PImage logo;

    void setup() {
        // initialize the GLCD and show a message
        // asking the user to open the serial line
        TFTscreen.begin();
        TFTscreen.background(255, 255, 255);

        TFTscreen.stroke(0, 0, 255);
        TFTscreen.println();
        TFTscreen.println(F("Arduino TFT Bitmap Example"));
        TFTscreen.stroke(0, 0, 0);
        TFTscreen.println(F("Open serial monitor"));
        TFTscreen.println(F("to run the sketch"));

        // initialize the serial port: it will be used to
        // print some diagnostic info
        Serial.begin(9600);

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

        // clear the GLCD screen before starting
        TFTscreen.background(255, 255, 255);

        // try to access the SD card. If that fails (e.g.
        // no card present), the setup process will stop.
        Serial.print(F("Initializing SD card..."));
        if (!SD.begin(sd_cs)) {
            Serial.println(F("failed!"));
            return;
        }
        Serial.println(F("OK!"));

        // initialize and clear the GLCD screen
        TFTscreen.begin();
        TFTscreen.background(255, 255, 255);

        // now that the SD card can be access, try to load the
        // image file.
        logo = TFTscreen.loadImage("arduino.bmp");
        if (!logo.isValid()) {
            Serial.println(F("error while loading arduino.bmp"));
        }
    }

    void loop() {
        // don't do anything if the image wasn't loaded correctly.
        if (logo.isValid() == false) {
            return;
        }

        Serial.println(F("drawing image"));

        // get a random location where to draw the image.
        // To avoid the image to be draw outside the screen,
        // take into account the image size.
        int x = random(TFTscreen.width() - logo.width());
        int y = random(TFTscreen.height() - logo.height());

        // draw the image to the screen
        TFTscreen.image(logo, x, y);

        // wait a little bit before drawing again
        delay(1500);
    }

title: Want to display an image from SD card to ILI9486 LCD display

Answers: 1

body: Make sure your SD card is Fat16 format.  At least that was a requirement of the test code I had on the same sort of display.


body:
I have an Arduino NANO clone and a 2.4" ILI9341 TFT display.  The VCC and LCD pins of the display are connected to the 5V pin of the board.  The GND to the GND.  All the logic pins are connected to voltage dividers (2k2 and 4k3 resistors), their connections checked and delivering 3.3V when 5V is supplied to them.

If I understand the source correctly, [if I specify all the pins to the constructor, then I use software SPI](https://github.com/adafruit/Adafruit_ILI9341/blob/master/Adafruit_ILI9341.cpp#L82), but [if I don't, then I use hardware SPI](https://github.com/adafruit/Adafruit_ILI9341/blob/master/Adafruit_ILI9341.cpp#L97).

Now, if I use the software SPI, everything is working fine, I can get the info, I can draw, etc.  However if I use the hardware SPI then it is not giving me anything.

<!-- language: c -->

    #include <Adafruit_GFX.h>
    #include <Adafruit_ILI9341.h>

    // Adafruit_ILI9341 tft = Adafruit_ILI9341(10, 9);              // NOT WORKING!
    Adafruit_ILI9341 tft = Adafruit_ILI9341(10, 9, 11, 13, 8, 12);  // WORKING!

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

        Serial.println("ILI9341 Test!");

        tft.begin();

        // read diagnostics (optional but can help debug problems)
        uint8_t x = tft.readcommand8(ILI9341_RDMODE);
        Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
        x = tft.readcommand8(ILI9341_RDMADCTL);
        Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
        x = tft.readcommand8(ILI9341_RDPIXFMT);
        Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
        x = tft.readcommand8(ILI9341_RDIMGFMT);
        Serial.print("Image Format: 0x"); Serial.println(x, HEX);
        x = tft.readcommand8(ILI9341_RDSELFDIAG);
        Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX);
    }

    void
    loop()
    {
        // pass
    }

However, what really makes me totally confused is when I use the SD card reader with the `SD Library` alone (the SD card reader is on the ILI9341 board), then that is working fine as well (as if the hardware SPI would be working, unless the SD Library is switching to software SPI magically).  Anyway, the following is the working code:

<!-- language: c -->

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

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

        Serial.println("ILI9341 Test!");

        if (!SD.begin(7))
        {
            Serial.println("Cannot initialise SD card");
            while (true);
        }

        File file;

        if ((file = SD.open("file.txt", FILE_WRITE)))
        {
            Serial.print("Writing to file...");
            file.println("Hello, World!");
            file.close();
            Serial.println(" DONE");
        }
        else
            Serial.println("Cannot open file for writing");

        if ((file = SD.open("file.txt")))
        {
            Serial.println("Opening file...");
            while (file.available())
                Serial.write(file.read());
            file.close();
            Serial.println("DONE");
        }
        else
            Serial.println("Cannot open file for reading");
    }

    void
    loop()
    {
        // pass
    }

---

**So what exactly is going on here?  Am I doing something obviously wrong?  Or is the board's hardware SPI not working?  Or is there a problem with the Adafruit library?**

---

**Extra info:**

I'm using the `arduino-cli` to upload sketches the following ways:

<!-- language: bash -->

    # To compile:
    arduino-cli                                     \
        compile                                     \
        --fqbn arduino:avr:nano:cpu=atmega328old    \
        --warnings all                              \
        MyArduinoSketch;

    # To upload
    sudo arduino-cli                                \
         upload                                     \
         --verify                                   \
         --verbose                                  \
         --port /dev/ttyUSB0                        \
         --fqbn arduino:avr:nano:cpu=atmega328old   \
         MyArduinoSketch;

I installed the mentioned libraries via `arduino-cli`.

title: Arduino NANO hardware SPI not working

Answers: 2

body:
Use constructor `Adafruit_ILI9341(10, 9, 8);` to make the reset that works with software SPI.

To SD card as second device on the bus:

Every SPI device on SPI bus must be controlled by slave select pin. If a device is connected to the bus and the SS pin is left floating the device disturbs the bus.

The empty SD card adapter is not a device on the bus, only the inserted card is a device. If it is on the bus the corresponding SS pin must be set HIGH. If you use the SD libray SD.begin(SD_SS_PIN), the library initializes the pin. If you don't use the library in the sketch (because it takes much memory), remove the SD card or set the SS pin to OUTPUT and HIGH.

body:
Hi Peter First Adafruit spends a lot of time creating their libraries and i do appreciate that but my luck is that I never get anything working with their libraries it is just me

I use this library:

https://github.com/Bodmer/TFT_ILI9341

and it works wonders if I want to add other SPI devices like your SD card I edit the User_Setup File that is included in your sketch right at the bottom of the file you can find the following line:

// #define SUPPORT_TRANSACTIONS

uncomment that line and your Touch part as well as SD card will functional normally I have had a setup working with the screen, touch controller, RFID board and a SD card all working on SPI each with their own SS or Chip select pin

NB! if you are going to try the library it is best you remove the ADAfruit one first because there are some files with the same names and the IDE tends to include the first one it finds AKA Adafruit


body:
The LEDs namely L, TX and RX on the board.
Furthermore, whenever the board is connected, the L LED blinks to the frequency of the delay that I set. [Eg: delay(1000);]
If I miss any other LED, do mention their purposes as well!
Thank you

title: What are the purposes of the different LED lights on a Arduino UNO board?

Answers: 1

body:
'L' shows the state of pin13 which is programmable by you for any purpose, whether to read or write to an external device, or just for turn the LED on and off as you have done.

'RX' and 'TX' show the states of the Receive and Transmit pins, respectively, and allow you see when serial communication is taking place.


body:
I am learning Arduino interruptions and I am unable to explain the behavior of a minimalistic interrupt driven project. The project is the following: an Arduino UNO is connected to two LEDs, on ports 9 and 10, and a button on port 2. The button is listened to for RISING interruptions, which are expected to trigger the following 3 seconds sequence: LED1 `HIGH` (one second); both LEDs `HIGH` (one second); LED2 `HIGH` (one second); during which pressing the button should have no effect.

    #define led1Pin 10
    #define led2Pin 9
    #define buttonPin 2

    void setup() {

      cli();//stop interrupts

      pinMode(led1Pin, OUTPUT);
      pinMode(led2Pin, OUTPUT);
      pinMode(buttonPin, INPUT);
      digitalWrite(led1Pin, LOW);
      digitalWrite(led2Pin, LOW);
      attachInterrupt(digitalPinToInterrupt(buttonPin), f, RISING);

      TCCR0A = 0;// set TCCR2A register to 0
      TCCR0B = 0;// set TCCR2B register to 0 (sets timer0 prescaler values to "disable timer")
      TCCR2A = 0;// set TCCR2A register to 0
      TCCR2B = 0;// set TCCR2B register to 0 (sets timer2 prescaler values to "disable timer")

      //set timer1 interrupt at 1Hz
      TCCR1A = 0;// set TCCR1A register to 0
      TCCR1B = 0;// set TCCR1B register to 0

      // set compare match register for 1hz increments
      OCR1A = 15624;// = (16*10^6) / (1*1024) - 1
      TCCR1B |= (1 << WGM12);   // turn on CTC mode 1 (compare to OCR1A)
      TCCR1B |= (1 << CS12) | (1 << CS10);// CS12|CS10 => Prescaler 1024
      TIMSK1 = 0;// disable timer compare interrupt

      sei();
    }

    volatile int index=0;

    volatile byte previousState=LOW;
    volatile byte state = LOW;

    void loop() {
      if (state && !previousState) {
        digitalWrite(led1Pin, HIGH); index=1;
        TCNT1H = 0;
        TCNT1L = 0; //initialize counter value to 0
        TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
        previousState = HIGH;
      }
    }

    void f() {
      state = HIGH;
    }

    ISR(TIMER1_COMPA_vect){ //timer1 interrupt 1Hz
      switch(index) {
      case 1:
        digitalWrite(led2Pin, HIGH); index=2;
        break;
      case 2:
        digitalWrite(led1Pin, LOW); index=3;
        break;
      case 3:
        digitalWrite(led2Pin, LOW); index=0;
        state=LOW; previousState=LOW;
        TIMSK1 = 0;// disable timer compare interrupt
        break;
      default:
        break;
      }

    }

Code adapted from https://www.instructables.com/id/Arduino-Timer-Interrupts/

Upon pressing the button, `state` is set to `HIGH`, which assuming `previousState` and `state` were `LOW`, should get the loop to perform a set of action once as it will set `previousState` `HIGH`.

These actions are the following: set `led1Pin` to `HIGH`, set `TCNT1H` and `TCNT1L` to 0, which should put the Timer1 counter to 0, and then set `TIMSK1` to `0b00000010`, that is, `1 << OCIE1A`, to accept the interrupt when it will be triggered, supposedly one second from the instruction that set the counter to 0, as the timer fires interrupts at 1Hz.

But while the expected behaviour is LED 1 on for one second, both LEDs on for one second, then LED 2 on for one second, the observed behaviour is the following, from my tests:

- First time pressing the button since Arduino reset : LED 1 and LED 2 on for one second, LED 2 on for one second.

- Button presses properly ignored until LED 2 turns off.

- Subsequent button presses : either proper behaviour (LED1 on, both LEDs on, LED2 on); or "first press" behaviour (both LEDs on, LED2 on). In both cases, the cycle sometimes instantly restart ([optional : LED1 on;] both LEDs on; LED2 on; LED1 on; both LEDs on; LED2 on), with each state taking one second.

The non-deterministic nature of the problem lets me think I'm mishandling interruptions. The project behaves as if enabling timer compare interrupts instantly triggered one, despite setting the relevant registers to 0 before that. I was unsuccessful in finding information regarding this that would explain the problem.

Is there asynchronous behaviour when setting the `TCNT1H` and `TCNT1L` registers to 0 ? Can a compare match interruption somehow be buffered ? And how comes the cycle sometimes execute twice ?

title: Does enabling the Timer1 CompareA interrupt instantly triggers an interrupt?

Answers: 1

body:
> The project behaves as if enabling timer compare interrupts instantly
> triggered one

This can indeed happen, and it's likely what you are experiencing.

Explanation: an interrupt fires when three bits are simultaneously set:

- the “interrupt flag” that signals the detection of some specific event
- the “interrupt enable” bit associated with that particular interrupt
- the “global interrupt enable” bit that is set by the `sei()`
  instruction

In your case, the relevant interrupt flag is `OCF1A` (Timer/Counter1,
Output Compare A Match Flag), in register `TIFR1` (Timer/Counter1
Interrupt Flag Register). This flag is raised by a “timer compare”
event, i.e. when the timer value hits the value stored in `OCR1A`. If
the interrupt fires, the flag is automatically cleared when the CPU
starts executing the corresponding ISR. Alternatively, the flag can be
cleared manually by overwriting it with a logic 1 (yes, that's kind of
backwards). It is worth noting that the flag records the compare events
whether or not the interrupt is enabled.

You normally expect the interrupt flag to be the last of these three
bits to be set, so that the interrupt is triggered by the compare event.
But this need not be the case. In your program, it is likely that the
interrupt flag is raised one second after startup. The global interrupt
enable is set by your `sei()` at the end of `setup()`. Thus, at this
point, as soon as you set the interrupt enable bit the interrupt fires
immediately.

The standard solution to this problem is to clear the interrupt flag
right before setting the interrupt enable bit:

    TIFR1  |= _BV(OCF1A);   // clear timer compare flag
    TIMSK1 |= _BV(OCIE1A);  // enable timer compare interrupt


body:
I've got to do a project which uses a servo to drive a turntable.
How much I adjusted the angle, the servo seemed to shift every time it spinned. For instance, the 0 degree angle was getting a bit bigger. I think it is caused by the imprecise PWM control of the Arduino or the bad translation using, I think, the `map()` function.

 [![How a servo works][1]][1]

Could you fix this issue in code, or the servo doesn't work properly. I observed that every servo (that I've tried) creates a buzzing noice for angles bigger than 170 degrees.

By the way, my code is:

<pre>
#include <Servo.h>

Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 0;    // variable to store the servo position

#define pos0 0
#define pos1 23
#define pos2 48
#define pos3 164

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  Serial.begin(9600);
}

void loop() {
  for (pos = pos0; pos < pos1; pos += 1) {
    myservo.write(pos);
    delay(30);
  }
  Serial.print("pos: ");
  Serial.println(pos);
  delay(5000);
  for (pos = pos1; pos < pos2; pos += 1) {
    myservo.write(pos);
    delay(30);
  }
  Serial.print("pos: ");
  Serial.println(pos);
  delay(5000);
  for (pos = pos2; pos < pos3; pos += 1) {
    myservo.write(pos);
    delay(30);
  }
  Serial.print("pos: ");
  Serial.println(pos);
  delay(5000);
  for (pos = pos3; pos > pos0; pos -= 1) {
    myservo.write(pos);
    delay(30);
  }
  Serial.print("pos: ");
  Serial.println(pos);
  delay(5000);
}
</pre>

Edit: Should I try with a more powerful Arduino, like the Mega, which I think will be the perfect option having more GPIO than the UNO.

  [1]: https://i.stack.imgur.com/jhdl0.jpg

title: Why a servo doesn`t move to angles properly

Answers: 4

body:
Not all Servos are perfectly built. One can get rid of the library itself; there is a way to make a servo turn by manually writing out the code.

    for(x=0; x<150; x=x+1)
    {
      digitalWrite(Servomotor, HIGH);
      delayMicroseconds(1500);          //Edit this delay to adjust the position
      digitalWrite(Servomotor, LOW);
      delayMicroseconds(18550);         //Don't touch this delay
    }

By trying out different delays for the first `delayMicroseconds()`, you can test out which delay you need for what position.

To make your code more clean, you could safe different angles in another void function, and when you need them just type out the name

Have a nice day ;)

body: Try to use `myservo.writeMicroseconds(x)` function. For standard servos the value of parameter x is between 1000 to 2000 for 0 degree to 180 degree rotation. But you know all servos are not manufactured perfectly. Thats why servos can response to 700 to 2300. At first you have to verify the minimum and maximum responding values then use it. You can use `map()` for easy coding.

body:
Every servo is different, they can have varying specifications:

 - Angular speed
 - Rotation range
 - Stall Torque
 - Size
 - Gear material/quality

Servos will vary based on brand; in addition each servo is going to have some individual variance.  So one has to characterize the servo, and discover what the proper control values are. Once the control values are established these are used to initialize the library so angular control will be accurate.

> For instance, the 0 degree angle was getting a bit bigger

I have found that errors in repeatability, like this, are usually found in the mechanism the servo is driving, especially the connection between the servo and the driven mechanisms. Check the connection for slop, see if everything is tightened properly.

>  I observed that every servo (that I've tried) creates a buzzing noice for angles bigger than 170 degrees.

The typical maximum range of a servo is 160-190 degrees of rotation. The noise you are hearing is the servo trying to drive the motor to set the angle, but it is stalled as it can't turn that far.

> Should I try with a more powerful Arduino, like the Mega, which I think will be the perfect option having more GPIO than the UNO.

IIRC the servo library can control 12 servos with a basic Arduino, and 48 with the MEGA. This difference is more than just pin count, the MEGA has 4x the hardware timers of the 328p; 12 x 4 = 48

If you need more features you can move to the MEGA, i.e. you need more PWM channels, and the servo library reduces PWM pins from 6 to 4 on the 328p. Another example could needing more timers.

Read the [Arduino Servo examples][1] for more information on usage of the servo library and control of servos, etc.

  [1]: https://www.arduino.cc/en/reference/servo

body:
An inexpensive servo tester, e.g....

https://www.amazon.com/DIYmall-Digital-Consistency-Controler-Checker/dp/B012LZKTDO/ref=sr_1_12?crid=3BLBBVDUPTN53&keywords=servo+tester&qid=1644245707&sprefix=servo+tester,aps,93&sr=8-12

...is useful for determining the exact mechanical limits of a specific servo quickly and easily.  If the servo will only physically move 170 degrees and the connected mechanism requires 180 degrees, a different servo is needed.

It should be possible to use an oscilloscope connected to the servo control lead to determine a) what the tester output duty cycle is at specific angular positions, and b) what the actual Arduino output duty cycle is when running a program.

Use the servo tester to assure that the range of motion of your servo is adequate to correctly operate the mechanism.

Note the tester output at desired positions.

Adjust your program to produce the duty cycle(s) necessary to replicate the tester output at the desired positions.


body:
I'm trying to switch a ATX PSU on and off by serial command. My code is as follows:

    #include <Arduino.h>
    #define PIN_LOW_FOR_POWER PIN_F0

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

    void loop() {
      String sCode = Serial.readStringUntil('\n');
      if (sCode == "M80"){
        digitalWrite(PIN_LOW_FOR_POWER, LOW);
      }
      else if (sCode == "M81"){
        digitalWrite(PIN_LOW_FOR_POWER, HIGH);
      }
      else{
        Serial.println("Unknown command");
        return;
      }
      Serial.println("OK");
    }

I'm getting "OK" back, and the power switches. After sending M81 I read 5V across the pin and ground, but after sending M80 for some reason I read 2.37V and not 0V. If I switch to "F1" (keep the wire connected to F0) I do read 0V.

The ATX PSU needs F0 to be pulled down in order to turn on. I soldered the ground of the ATX PSU to the Teensy ground, and the wire to be pulled down (green) to F0. I supply the 5V to the Teensy through USB, so the VCC pin is left unconnected.

The PSU does turn on if I manually create a short between F0 and ground.

Why doesn't the Teensy pull F0 down, and how do I resolve this? (All I could come up with is something of internal resistance within the Teensy being too high, which seems unlikely to me. (If the resistance within the PSU and wires between "green" and ground is equal to the resistance within the Teensy this would happen, right?))

PS: It turns out I bought a fake Teensy from China, if it's related. Ordered a new one for a different project, but still had this one laying around.

title: Teensy not pulling down despite digitalWrite(x,LOW)

Answers: 1

body:
You forgot to set the IO pin to OUTPUT. Unless you do so all you are doing (if the Teensy core follows the Arduino API to the letter) is controlling the internal pullup.

    pinMode(PIN_LOW_FOR_POWER, OUTPUT);