# Question
Title: SPI - Apparently Random pulses on CS/SS line
I'm trying to figure out why my SPI device isn't responding as expected. So I hooked up my logic analyzer and am a bit confused by the results.

I'm seeing what appears to be random pulses on the chip select/slave select line (CS in the images below). The pulses happen in random locations with random counts. Always matching either a falling edge or rising edge in the CLK line.

The code I'm running is part of a library, but I've pulled it all out for a minimum functional example:

```
#include <SPI.h>

#define DC_PIN          9
#define CS_PIN          10
#define BUSY_PIN        7

int IfInit(void) {
    pinMode(CS_PIN, OUTPUT);
    SPI.begin();
    SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
    return 0;
}

void SpiTransfer(unsigned char data) {
    digitalWrite(CS_PIN, LOW);
    SPI.transfer(data);
    digitalWrite(CS_PIN, HIGH);
}

int Init() {

    if (IfInit() != 0) {
        return -1;
    }

    SendCommand(0x01); //POWER_SETTING
    SendData(0x03);                  // VDS_EN, VDG_EN
    SendData(0x00);                  // VCOM_HV, VGHL_LV[1], VGHL_LV[0]
    SendData(0x2b);                  // VDH
    SendData(0x2b);                  // VDL
    SendData(0xff);                  // VDHR
    SendCommand(0x06); //BOOSTER_SOFT_START
    SendData(0x17);
    SendData(0x17);
    SendData(0x17);                  //07 0f 17 1f 27 2F 37 2f
    SendCommand(0x04); //POWER_ON
    WaitUntilIdle();
    SendCommand(0x00); //PANEL_SETTING
    SendData(0xbf);    // KW-BF   KWR-AF  BWROTP 0f
    SendData(0x0b);
    SendCommand(0x30); //PLL_CONTROL
    SendData(0x3c);        // 3A 100HZ   29 150Hz 39 200HZ  31 171HZ

    return 0;
}

void SendCommand(unsigned char command) {
//    digitalWrite(DC_PIN, LOW);
    SpiTransfer(command);
}

void SendData(unsigned char data) {
//    digitalWrite(DC_PIN, HIGH);
    SpiTransfer(data);
}

void WaitUntilIdle(void) {
    while(digitalRead(BUSY_PIN) == 0) {      //0: busy, 1: idle
        delay(100);
    }
}

void setup() {

  pinMode(CS_PIN, OUTPUT);
  digitalWrite(CS_PIN, HIGH);

  Serial.begin(9600);
  Serial.println("Start");

  if (Init() != 0) {
    Serial.println("init failed");
    return;
  }

  Serial.print("init success");

}

void loop() {

}

```

I've tried on two different ATMEGA chips (same Arduino Uno board), same results. I've also tried with the device disconnected. Again same results. I've also tried changing the pin used for the CS, still didn't change anything.

Anyone have some insight as to what might be causing this, and/or what can be done to stop it?

# Answer
I shortened the leads between my arduino board and the device from 15 inches down to ~5 inches and the issue disappeared.

I would have to guess that it was some RF interference.
> 1 votes

# Answer
See my page about SPI.

> Pin 10 of the Arduino is the SS line - so does this mean you have to use it for the peripheral SS line? Or should it be kept high? The answer (from the Atmega documentation) is that the SS line (pin 10) must be configured as an **output** (regardless of what value is on it). If configured as an output the Arduino ignores the value on that line, and thus the SPI hardware will not be put into slave mode.
>
> Since the value on pin 10 is ignored, providing it is set as an output, then it can also be used as the SS line for your first, or only, slave. You could then use other pins (eg. 5, 6, 7, 8, 9) to control other slaves.

For you to successfully make an SPI master then pin 10 on your Uno must be configured as an output, regardless of whether or not you actually use pin 10 for SS. Under the circumstances, you may as well use pin 10 for SS if you are going to make it an output anyway.

---

> This issue persists when using pin 10 as the SS.

I tried your code with my Uno (no device connected) and had no such problems. Sounds like an electrical issue to me.
> 0 votes

---
Tags: arduino-uno, spi
---


# Question
Title: Synching local clock usign NTP to milliseconds
I am interested in getting a local clock on an ESP32 module synch to a network clock using NTP. I am able to read data and time here. But I am interested in synching to the milli second level.

```
    #include <WiFi.h>
    #include <WiFiUdp.h>

    char ssid[] = "*************"; //  your network SSID (name)
    char pass[] = "********"; // your network password

    unsigned int localPort = 2390; // local port to listen for UDP packets

    IPAddress timeServerIP; // time.nist.gov NTP server address
    const char* ntpServerName = "time.nist.gov";

    const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes
    byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing
    // A UDP instance to let us send and receive packets over UDP
    WiFiUDP udp;

    void setup() {
      Serial.begin(115200);
      Serial.println();
      Serial.println();
      // We start by connecting to a WiFi network
      Serial.print("Connecting to ");
      Serial.println(ssid);
      WiFi.begin(ssid, pass);
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      Serial.println("");
      Serial.println("WiFi connected");
      Serial.println("IP address: ");
      Serial.println(WiFi.localIP());
      Serial.println("Starting UDP");
      udp.begin(localPort);
      Serial.print("Local port: ");
    }

    void loop() {
      //get a random server from the pool
      WiFi.hostByName(ntpServerName, timeServerIP);
      sendNTPpacket(timeServerIP);
      // send an NTP packet to a time server
      // wait to see if a reply is available
      delay(1000);
      int cb = udp.parsePacket();
      if (!cb) {
        Serial.println("no packet yet");
      } else {
        Serial.print("packet received, length=");
        Serial.println(cb);
        // We've received a packet, read the data from it
        udp.read(packetBuffer, NTP_PACKET_SIZE);
        // read the packet into the buf
        unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
        unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
        // combine the four bytes (two words) into a long integer
        // this is NTP time (seconds since Jan 1 1900):
        unsigned long secsSince1900 = highWord << 16 | lowWord;
        Serial.print("Seconds since Jan 1 1900 = " );
        Serial.println(secsSince1900);
        unsigned long mshighWord = word(packetBuffer[44], packetBuffer[45]);
        unsigned long mslowWord = word(packetBuffer[46], packetBuffer[47]);
        unsigned long mssecs = mshighWord << 16 | mslowWord;
        Serial.print("Frac Seconds = " );
        Serial.println(mssecs);
        // now convert NTP time into everyday time:
        Serial.print("Unix time = ");
        // Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
        const unsigned long seventyYears = 2208988800UL;
        // subtract seventy years:
        unsigned long epoch = secsSince1900 - seventyYears;
        // print Unix time:
        Serial.println(epoch);
        // print the hour, minute and second:
        Serial.print("The UTC time is "); // UTC is the time at GMT
        Serial.print((epoch  % 86400L) / 3600);
        // print the hour (86400 equals secs per day)
        Serial.print(':');
        if (((epoch % 3600) / 60) < 10) {
          // In the first 10 minutes of each hour, we'll want a leading '0'
          Serial.print('0');
        }
        Serial.print((epoch  % 3600) / 60); // print the minute
        Serial.print(':');
        if ((epoch % 60) < 10) {
          // In the first 10 seconds of each minute, we'll want a leading '0'
          Serial.print('0');
        }
        Serial.println(epoch % 60); // print the second
      }
      // wait ten seconds before asking for the time again
      delay(10000);
    }

    // send an NTP request to the time server at the given address
    unsigned long sendNTPpacket(IPAddress& address) {
      Serial.println("sending NTP packet...");
      // set all bytes in the buffer to 0
      memset(packetBuffer, 0, NTP_PACKET_SIZE);
      // Initialize values needed to form NTP request
      // (see URL above for details on the packets)
      packetBuffer[0] = 0b11100011; // LI, Version, Mode
      packetBuffer[1] = 0; // Stratum, or type of clock
      packetBuffer[2] = 6; // Polling Interval
      packetBuffer[3] = 0xEC; // Peer Clock Precision
      // 8 bytes of zero for Root Delay & Root Dispersion
      packetBuffer[12]  = 49;
      packetBuffer[13]  = 0x4E;
      packetBuffer[14]  = 49;
      packetBuffer[15]  = 52;
      // all NTP fields have been given values, now
      // you can send a packet requesting a timestamp:
      udp.beginPacket(address, 123); //NTP requests are to port 123
      udp.write(packetBuffer, NTP_PACKET_SIZE);
      udp.endPacket();

```

# Answer
The NTP timestamp format doesn't use milliseconds. All timestamps are in **seconds**, in a 32.32 fixed point format. This means that the fraction field is in units of 2−32 s, or about 233 picoseconds. You can convert that to milliseconds by multiplying by 1000 and dividing by 232. For example:

```
uint32_t frac  = (uint32_t) packetBuffer[44] << 24
               | (uint32_t) packetBuffer[45] << 16
               | (uint32_t) packetBuffer[46] <<  8
               | (uint32_t) packetBuffer[47] <<  0;
uint16_t mssec = ((uint64_t) frac * 1000) >> 32;

```

If you want to avoid 64-bit arithmetic, you can instead divide by 128, then multiply by 125, then divide by 222:

```
uint16_t mssec = ((frac >> 7) * 125) >> 22;

```

That should give the same result except for a potentially larger rounding error. Note that, if you care about rounding, you would try to round to nearest rather than towards zero:

```
uint16_t mssec = ((frac >> 7) * 125 + (1UL << 21)) >> 22;

```
> 3 votes

---
Tags: esp8266, esp32
---


# Question
Title: How to control an 12V 2A Car lamp using relay or MOSFET in Arduino
I am working with the project controlling an 25W 12V Car lamp. I have a 12V car battery. I want to control it with the Arduino using a relay or MOSFET.

Any suggestion for my project would be appreciated.

# Answer
You can use a RFP30N06LE mosfet. It can support up to 60V 30A

Here is a wiring schema
> 3 votes

---
Tags: relay, mosfet
---


# Question
Title: Why connect a diode between the reset pin of Arduino and 555 timer?
I am trying to create a watchdog timer using 555 IC and I am following this.

I do not understand why a 1N4148 diode is connected between the reset pin of Arduino and the output of the 555 timer.

As far as I understand, the reset pin of the Arduino should be high, and when it is pulled low, the Arduino resets. But why should we add a diode over here? What purpose does it serve?

# Answer
It's called a "Wired Or" arrangement.

The Arduino's RESET pin has a pullup resistor in it (10KΩ). That keeps the RESET pin normally HIGH. To invoke a reset that pin needs pulling low, and that is done from a number of sources:

* The RESET button
* The DTR pin (through a 100nF capacitor) of the USB interface chip
* The 555 watchdog circuit above

The critical one there is the DTR pin. That, because it's a brief pulse with quite a high output impedance, needs the reset pin to be easy to pull down. If you connected the output of the 555 directly to RESET it would be constantly trying to pull the RESET pin up to 5V with quite a low output impedance. The DTR circuit would have no chance of overcoming it.

So by adding a diode in there you get Wired Or, using an arrangement direct from the 1950s - DRL - Diode-Resistor Logic. When the output of the 555 is HIGH the diode is reverse biased (or neutrally biased) and doesn't conduct, so the RESET pin's own resistor pulls the RESET pin up. However, when the output of the 555 is LOW the diode can then conduct (it's forward biased) and that pulls the RESET pin LOW.
> 15 votes

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


# Question
Title: How to make timed loops after switch / case?
I am working on a code, which is running a function once a second:

```
switch (gearbox1) {
  case 1:
    //manually close
    Serial.println("Closing1");
    digitalWrite(gear1OpenPin, OFF);
    t.setTimer(1000, Close1, 1);

    break;

  case 2:
    //manually open
    Serial.println("Opening1");
    digitalWrite(gear1ClosePin, OFF);
    t.setTimer(1000, Open1, 1);

    break;

```

This part is working fine. But then i want at case 10: call function `autoClose()` which would work in 10 second cycles.

Struggle is, as my first function is called once a second, it is starting function `autoClose()` once a second as well. How can I overcome this please?

At the moment I have current, non working code:

```
  case 10:
    //automatic close
    Serial.println("A Close1");
    digitalWrite(gear1ClosePin, OFF);
    digitalWrite(gear1OpenPin, OFF);

    t.enable(autoClose);
    autoClose();
    break;

```

Edit: Added minimal possible code. I want `autoOpen()` and `autoClose()` to loop in 10 sec. intervals.

```
#include <SimpleTimer.h>
SimpleTimer t;
int gearbox1;

#define gear1OpenPin 44
#define gear1ClosePin 46

int OFF = HIGH;  // states for relays
int ON = LOW;

byte gear1Open = 0;
byte gear1Close = 0;

void setup() {

  t.setInterval(1000, Control1);
  int autoOpen = t.setInterval(10000, autoOpen);
  int autoClose = t.setInterval(10000, autoClose);
}

void loop() {

  t.run();
}

void Control1() {
  //*****************************************
  switch (gearbox1) {
    case 1:
      //manually close
      Serial.println("Closing");
      digitalWrite(gear1OpenPin, OFF);
      t.setTimer(1000, Close1, 1);

      break;

    case 2:
      //manually open
      //   Serial.println("Opening");
      digitalWrite(gear1ClosePin, OFF);
      t.setTimer(1000, Open1, 1);

      break;

    case 5:
      //stop
      Serial.println("Stopping");
      digitalWrite(gear1ClosePin, OFF);
      digitalWrite(gear1OpenPin, OFF);

      break;

    case 10:
      //automatic close

      digitalWrite(gear1ClosePin, OFF);
      digitalWrite(gear1OpenPin, OFF);
      if (t.isEnabled(autoClose)) {
        autoClose();
      } else {
        t.restartTimer(autoClose) ; t.enable(autoClose);
        autoClose();
      }
      break;

    case 20:
      //automatic open

      digitalWrite(gear1ClosePin, OFF);
      digitalWrite(gear1OpenPin, OFF);
      t.restartTimer(autoOpen); t.enable(autoOpen);
      autoOpen();
      break;
 }
}

void Open1() {
  digitalWrite(gear1OpenPin, ON);
}
//**********************************************
void Close1() {
  digitalWrite(gear1ClosePin, ON);
}
//**********************************************
void autoOpen() {

  if (gear1Open == ON) {
    gear1Open = OFF;
  } else {
    gear1Open = ON;
  }
  digitalWrite(gear1OpenPin, gear1Open);
}
//**********************************************
void autoClose() {
  if (gear1Close == ON) {
    gear1Close = OFF;
  } else {
    gear1Close = ON;
  }
  digitalWrite(gear1ClosePin, gear1Close);
}

```

# Answer
Create a new variable to hold the state of whether or not you are in autoClose mode:

```
uint8_t inAutoClose=0;

```

Then, add a line in your switch statement to set that flag when you enter that state, but not call the function if you were already in that state:

```
case 10:
  //automatic close
  Serial.println("A Close1");
  digitalWrite(gear1ClosePin, OFF);
  digitalWrite(gear1OpenPin, OFF);
  if (!inAutoClose) {
    inAutoClose = 1;
    t.enable(autoClose);
    autoClose();
  }
  break;

```

Add a line in your other switch branches to clear that flag:

```
case 1:
  //manually close
  inAutoClose = 0;
  [...]

```

If you want `autoClose()` to be called every 10 seconds repeatedly as the "idle" state, then you need to clear `inAutoClose` (set it to zero) at the end of every 10 second period. How and where you do that depends on other factors you haven't shown, like what `autoClose()` does, or what the timer you enable does.

Side note: avoid naming your timer name (`autoClose`) and your function name `autoClose()` the same! Does your code compile that way? It ought to throw an error.

**ANSWER 2** (based on comments)

Your auto-close state is described as

> Turns on for 10 seconds, after that off for 10 seconds.

This can be accomplished with a similar structure to what you have now, with a few changes. (These are my suggestions, but by no means the best or worst way.)

Edit your open and close functions:

```
void Open1() {
  digitalWrite(gear1OpenPin, ON);
  if (isAutoOpen) {
    t.setTimeout(10000UL, Close1); // Sets a timer to call closer in 10s
   }
}

void close1() {
  digitalWrite(gearClosePin, ON);
  if (isAutoOpen) {
    t.setTimeout(10000UL, Open1); // Sets a timer to call opener in 10s
  }
}

```

When you call either `Open1()` or `Close1()`, if your auto-open flag is set, then 10s later, the opposite function is called, and this keeps chaining together, every 10s.

Whenever it's time to stop this, you clear the `isAutoOpen` flag and disable the timers. You may wish to keep track of the timer ID that is created with the `setTimeout()` function, so you can disable it at any time to avoid the system going through the cycle one more time after you clear the flag.
> 0 votes

---
Tags: timers, switch
---


title: Structure Array Initialization

text:
# Question
Title: Structure Array Initialization
I'm trying to initialize a char array which is part of a structure as follows:

```
#define TRUE 1
#define FALSE 0

struct s_field_def { // structure for managing display field
  char f_txt[16]; // option text
  bool f_inhibit; // set this to inhibit updating of the field on the display
};

enum field_name {F_STATE, F_PULSE};

void setup() {

  // initialize display fields structure
  struct s_field_def fields[2]; // initialize the display fields
  fields[F_STATE] =  {"HALTED", FALSE}; // displays the current run state
  fields[F_PULSE] =  {"@", TRUE}; // displays indicator of system running
}

void loop() {

}

```

The initialization of the structure is producing an error at these lines:

```
  fields[F_STATE] =  {"HALTED", FALSE}; // displays the current run state
  fields[F_PULSE] =  {"@", TRUE}; // displays indicator of system running

no match for 'operator=' (operand types are 's_field_def' and '<brace-enclosed initializer list>')

```

What am I doing wrong here?

# Answer
> 4 votes
As explained in Michel Keijzers' answer, you cannot use the `=` operator to *assign* something to a string (a character array). However, you can *initialize* a string using `=`. There is an important distinction between *assignment*, which you can do anywhere in a program, an *initialization*, which can only be done at the time you *define* a variable.

For example:

```
int i = 2;  // initialization

void setup() {
    i = 4;  // assignment
}

```

In your specific case, you can initialize `fields` as follows:

```
struct s_field_def fields[2] = {
    {"HALTED", FALSE},  // displays the current run state
    {"@", TRUE}         // displays indicator of system running
};

```

# Answer
> 0 votes
You can use this (but look at the accepted answer, it shows a much neater way).

```
  strcpy(fields[F_STATE].f_txt, "HALTED");
  fields[F_STATE].f_inhibit = FALSE;

  strcpy(fields[F_PULSE].f_txt, "@");
  fields[F_PULSE].f_inhibit = TRUE;

```

I don't have a compiler so I hope it's correct.

When using C++ you can use a constructor or assignment operator, but C does not have these object oriented features.

---
Tags: software
---


# Question
Title: How can I make an AC analog voltage with Arduino?
I am trying to create an AC voltage in Arduino. Until now I have only managed to get a square wave. How can this be achieved with Arduino?

If I try:

```
int up;
int down;
int out = 11;

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

void loop() {
  for (up = 0; up <= 255; up++) {
    analogWrite(out, up);
    delay(1);
  }
  for (down = 255; down >= 0; down--) {
    analogWrite(out, down);
    delay(1);
  }
}

```

is it still pulsed DC?

# Answer
You have a few options:

* Use a low-pass filter to round the square wave's edges some so they look more AC-ish.
* Use a low-pass filter and have your code create steps of voltage that look AC-ish by varying the PWM widths.
* Use an external SPI DAC chip that you can control with more discrete levels to make smoother looking AC.
* Look into Direct Digital Synthesis (DDC) to learn more. Google "analog via ddS", lots of hits.
> 3 votes

---
Tags: arduino-uno, analogwrite, voltage
---


# Question
Title: Arduino UNO + Ethernet Shield + LCD + RFID but RFID doesn't work
I've been working to a project that uses arduino for RFID but when connected to ethernet shield, the RFID seems to not read any card tapped to sensor but the LCD seems to do fine. Here's the code I use from this page: http://www.instructables.com/id/RFID-CARD-READER-WITH-ARDUINORFID-RC522-and-LCD-16/

```
#include <EEPROM.h> //Library To read and write PICC's UIDs from/to EEPROM
#include <SPI.h> //Library  RC522 Module uses SPI protocol
#include <MFRC522.h> //Library  RC522 Module
#include <LiquidCrystal.h> //Library  for LCD Display
#include <Ethernet.h>

EthernetServer server(80);
boolean match = false; // initialize card match to false
boolean programMode = false; // initialize programming mode to false
int successRead; // Variable integer to keep if we have Successful Read from Reader
byte storedCard[4]; // Stores an ID read from EEPROM
byte readCard[4]; // Stores scanned ID read from RFID Module
byte masterCard[4]; // Stores master card's ID read from EEPROM
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); //Initializing LCD PINS as (RS, EN, D4, D5, D6, D7)

void setup() {
  Serial.begin(9600); // Initialize serial communications with PC
  lcd.begin(16, 2); //Initializing LCD 16x2
  pinMode(8, OUTPUT); //LED and Buzzer PIN OUT
  SPI.begin(); // MFRC522 Hardware uses SPI protocol
  mfrc522.PCD_Init(); // Initialize MFRC522 Hardware
  mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max);
  if (EEPROM.read(1) != 1) {
    // Look EEPROM if Master Card defined, EEPROM address 1 holds if defined
    Serial.println("No Admin Card Defined");
    //When no Master Card in Your EEROM (Serial Display)
    Serial.println("Scan A card to Define as Admin Card");
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.println("SET ADMIN CARD   ");
    //When no Master Card in Your EEROM (LCD Display)
    lcd.setCursor(0, 1);
    lcd.println("SCAN A CARD.....");
    //Scan any RFID CARD to set Your Master Card in Your EEROM (LCD Display)
    delay(1500);
    do {
      successRead = getID();
      // sets successRead to 1 when we get read from reader otherwise 0
    }
    while (!successRead);
    //the program will not go further while you not get a successful read
    for (int j = 0; j < 4; j++) {
      // Loop 4 times
      EEPROM.write(2 + j, readCard[j]);
      // Write scanned PICC's UID to EEPROM, start from address 3
    }
    EEPROM.write(1, 1); //Write to EEPROM we defined Master Card.
    Serial.println("Admin Card Defined");
  }
  Serial.println("Administrator Card's UID");
  for (int i = 0; i < 4; i++) { // Read Master Card's UID from EEPROM
    masterCard[i] = EEPROM.read(2 + i); // Write it to masterCard
    Serial.print(masterCard[i], HEX); //Master Card only view in serial
    Serial.println("Waiting PICCs to bo scanned :)");
  }
 //WAITING TO SCAN THE RFID CARDS:
  Serial.println("");
  Serial.println("Waiting cards to bo scanned :)");
  lcd.clear();
  lcd.setCursor(4, 0);
  lcd.println("WAITING     ");
  lcd.setCursor(3, 1);
  lcd.println("FOR CARD...  ");
  delay(1500);
}

int getID() {
 // Getting ready for Reading PICCs
  if (! mfrc522.PICC_IsNewCardPresent()) {
    //If a new PICC placed to RFID reader continue
    return 0;
  }
  if (! mfrc522.PICC_ReadCardSerial()) {
    //Since a PICC placed get Serial and continue
    return 0;
  }
 // There are Mifare PICCs which have 4 byte or 7 byte UID care if you use 7 byte PICC
 // I think we should assume every PICC as they have 4 byte UID
 // Until we support 7 byte PICCs
  Serial.println("Scanning card's UID....");
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("SCANNING");
  lcd.setCursor(0, 1);
  lcd.print("Card's UID.....");
  delay(2000);
  for (int i = 0; i < 4; i++) {
    readCard[i] = mfrc522.uid.uidByte[i];
    Serial.print(readCard[i], HEX);
  }
  Serial.println("");
  mfrc522.PICC_HaltA(); // Stop reading
  return 1;
}
boolean isMaster(byte test[]) {
  if (checkTwo(test, masterCard))
    return true;
  else
    return false;
}

boolean checkTwo (byte a[], byte b[]) {
  if (a[0] != NULL)
    // Make sure there is something in the array first
    match = true;
    // Assume they match at first
  for (int k = 0; k < 4; k++) {
    // Loop 4 times
    if (a[k] != b[k])
      // IF a != b then set match = false, one fails, all fail
      match = false;
  }
  if (match) {
    // Check to see if if match is still true
    return true;
  } else  {
    return false;
  }
}
boolean findID(byte find[]) {
  int count = EEPROM.read(0);
  // Read the first Byte of EEPROM that
  for (int i = 1; i <= count; i++) {
    // Loop once for each EEPROM entry
    readID(i);
    // Read an ID from EEPROM, it is stored in storedCard[4]
    if (checkTwo(find, storedCard)) {
      // Check to see if the storedCard read from EEPROM
      return true;
      break; // Stop looking we found it
    } else {
      // If not, return false
    }
  }
  return false;
}
void readID(int number) {
  int start = (number * 4) + 2;
  // Figure out starting position
  for (int i = 0; i < 4; i++) {
    // Loop 4 times to get the 4 Bytes
    storedCard[i] = EEPROM.read(start + i);
    // Assign values read from EEPROM to array
  }
}
void deleteID(byte a[]) {
  if (!findID(a)) {
    // Before we delete from the EEPROM, check to see if we have this card!
    failedWrite(); // If not
  } else {
    int num = EEPROM.read(0);
    // Get the numer of used spaces, position 0 stores the number of ID cards
    int slot;
    // Figure out the slot number of the card
    int start;
    // = (num * 4) + 6; // Figure out where the next slot starts
    int looping;
    // The number of times the loop repeats
    int j;
    int count = EEPROM.read(0);
    // Read the first Byte of EEPROM that stores number of cards
    slot = findIDSLOT(a);
    //Figure out the slot number of the card to delete
    start = (slot * 4) + 2;
    looping = ((num - slot) * 4);
    num--; // Decrement the counter by one
    EEPROM.write(0, num); // Write the new count to the counter
    for (j = 0; j < looping; j++) {
      // Loop the card shift times
      EEPROM.write(start + j, EEPROM.read(start + 4 + j));
      // Shift the array values to 4 places earlier in the EEPROM
    }
    for (int k = 0; k < 4; k++) {
      //Shifting loop
      EEPROM.write(start + j + k, 0);
    }
    successDelete();
  }
}
//For Failed to add the card:
void failedWrite() {
  Serial.println("something wrong with Card");
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("SOMETHING WRONG");
  lcd.setCursor(0, 1);
  lcd.print("WITH CARD");
  delay(2000);
}

//For Sucessfully Deleted:
void successDelete() {
  Serial.println("Succesfully removed");
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("SUCCESFULLY");
  lcd.setCursor(0, 1);
  lcd.print("REMOVED CARD");
  delay(2000);
}

int findIDSLOT(byte find[]) {
  int count = EEPROM.read(0);
  // Read the first Byte of EEPROM that
  for (int i = 1; i <= count; i++) {
    // Loop once for each EEPROM entry
    readID(i);
    // Read an ID from EEPROM, it is stored in storedCard[4]
    if (checkTwo(find, storedCard)) {
      // Check to see if the storedCard read from EEPROM
      // is the same as the find[] ID card passed
      return i;
      // The slot number of the card
      break;
      // Stop looking we found it
    }
  }
}
//For Sucessfully Added:
void successWrite() {
  Serial.println("Succesfully added");
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("SUCCESFULLY");
  lcd.setCursor(0, 1);
  lcd.print("ADDED");
  delay(2000);
}

//For Adding card to EEPROM:
void writeID(byte a[]) {
  if (!findID(a)) {
    // Before we write to the EEPROM, check to see if we have seen this card before!
    int num = EEPROM.read(0);
    // Get the numer of used spaces, position 0 stores the number of ID cards
    int start = (num * 4) + 6;
    // Figure out where the next slot starts
    num++;
    // Increment the counter by one
    EEPROM.write(0, num);
    // Write the new count to the counter
    for (int j = 0; j < 4; j++) {
      // Loop 4 times
      EEPROM.write(start + j, a[j]);
      // Write the array values to EEPROM in the right position
    }
    successWrite();
  } else {
    failedWrite();
  }
}
void loop() {
  lcd.clear();
  lcd.setCursor(4, 0);
  lcd.print("TAP YOUR");
  lcd.setCursor(4, 1);
  lcd.print("CARD HERE");
  do {
    successRead = getID(); // sets successRead to 1 when we get read from     reader otherwise 0
    if (programMode) {
      // Program Mode cycles through RGB waiting to read a new card
    } else {
    }
  }
  while (!successRead);
  //the program will not go further while you not get a successful read
  if (programMode) {
    if (isMaster(readCard)) {
      //If master card scanned again exit program mode
      Serial.println("This is ADMIN Card");
      Serial.println("Exiting ADMIN Mode");
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("EXITING FROM");
      lcd.setCursor(0, 1);
      lcd.print("ADMINISTRATOR MODE");
      delay(2000);
      programMode = false;
      return;
    } else {
      if (findID(readCard)) {
        //If scanned card is known delete it
        Serial.println("I know this CARD, so removing");
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("AVAILABLE!");
        lcd.setCursor(0, 1);
        lcd.print("SO DELETING.....");
        delay(5000);
        deleteID(readCard);
        Serial.println("-----------------------------");
      } else {
        // If scanned card is not known add it
        Serial.println("Adding this card...");
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Card no:");
        lcd.setCursor(0, 1);
        lcd.print(readCard[0], HEX);
        lcd.print(readCard[1], HEX);
        lcd.print(readCard[2], HEX);
        lcd.print(readCard[3], HEX);
        lcd.print(readCard[4], HEX);
        delay(4000);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("NOT AVAILABLE");
        lcd.setCursor(0, 1);
        lcd.print("SO ADDING...");
        delay(5000);
        writeID(readCard);
        Serial.println("-----------------------------");
      }
    }
  } else {
    if (isMaster(readCard)) {
      // If scanned card's ID matches Master Card's ID enter program mode
      programMode = true;
      Serial.println("Welcome to Administrator Mode");
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("WELCOME TO");
      lcd.setCursor(0, 1);
      lcd.print("ADMIN MODE");
      delay(3000);
      int count = EEPROM.read(0);
      // Read the first Byte of EEPROM that
      Serial.print("I have ");
      // stores the number of ID's in EEPROM
      Serial.print(count);
      Serial.print(" record(s) on EEPROM");
      Serial.println("");
      Serial.println("Scan a card to ADD or REMOVE");
      Serial.println("-----------------------------");
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("SCAN CARD TO");
      lcd.setCursor(0, 1);
      lcd.print("ADD OR REMOVE...");
      delay(2500);
    } else {
      if (findID(readCard)) {
        // If not, see if the card is in the EEPROM
        Serial.println("Acces Granted");
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("ACCESS GRANTED");
        lcd.setCursor(0, 1);
        lcd.print("YOU MAY ENTER NOW");
        digitalWrite(8, HIGH);
        delay(1500);
        digitalWrite(8, LOW);
        lcd.clear();
      } else {
        // If not, show that the ID was not valid
        Serial.println("Access Denied");
        for (int abcd = 0; abcd < 3; abcd++) {
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("     SORRY");
          lcd.setCursor(0, 1);
          lcd.print("  ACCESS DENIED");
          digitalWrite(8, HIGH);
          delay(1000);
          digitalWrite(8, LOW);
          lcd.clear();
          lcd.print("   YOU'RE NOT  ");
          lcd.setCursor(0, 1);
          lcd.print("   AUTHORIZED   ");
          delay(1000);
        }
        lcd.clear();
      }
    }
  }
}

```

Any help would be appreciated!

# Answer
I recently made a similar project with a RFID reader and an SD card shield, and I had the same problem.

The explanation why it doesn't work is that some shields that use SPI communication don't really care about your slave select pin being pulled low, and interfere when Arduino is talking to another SPI device via the MISO pin.

The only way I got it to work is by using a tri-state buffer on the MISO pins of my SPI devices. You can find plenty of info about it on the internet, as well as how to use them in your project.

The idea is simple, it works kind of like a transistor. When you pull the enable pin of the buffer to ground using SS pin, you allow the MISO pin of that device to be connected to the corresponding Arduino input. Otherwise, the MISO pin will be on a state of high impedance and would not interfere on the communication anymore.

Good luck with your project.
> 2 votes

# Answer
It may not be possible to use every optional Arduino feature with every other optional Arduino feature. Some features use the same Arduino resources. If there is actually a hardware contention problem, you need to dive deep into the software drivers and hardware to figure out if there is a possible work around. But this is hardly the type of effort new developers would take on. It might be easier for a new developer to use 2 different Arduino's to host the features desired and set up a communication link between them.
> 1 votes

---
Tags: arduino-uno, c++, c, spi, rfid
---


# Question
Title: What is the most Inputs on An analog Pin with a specified Accuracy on the Resistors Used?
I am asking about the technique were switches and resistors in series are used on the analog pin, so it creates a voltage divider when one of the switches is pressed, it a well known technique it is described here with 5 buttons on one analog pin

http://www.instructables.com/id/How-to-access-5-buttons-through-1-Arduino-input/

Obviously we assume the circuit is set up correctly e.g. the voltage reference is stable-but such things aren't the main point of this question. My question is about an obvious generalisation of that circuit for more inputs - and where the resistors are all replaced by, a single type of resistor, a fixed resistance value (e.g. 4k ohm) with a known error on the resistance (e.g. 5%). We use the 4k resistors to make up larger values 4k,8k,12k,16k,20k Ohms and make the 100k Ohm resistor out of twenty five 4k ohm resistors. My question using only 4k ohm resistors (connected in series in the voltage divider) within a 5% error of their value -what is the most switches we can theoretically connect for reliable working on one analog pin?-I'll have a guess at 20 switches.

The second question is given X ohm resistors (connected in series in the voltage divider) within a E% error of their value -what is the most switches, M, we can theoretically connect for reliable working on one analog pin? So there will be a formula for this-so what is it?

# Answer
> My question using only 4k ohm resistors (connected in series in the voltage divider)

The circuit you are describing (a collection of identical resistors connected in series) is quite different from the one discussed in the link you provide. I assume you have in mind something analogous to a digital pot, i.e. a chain of N resistors between GND and Vcc, with N switches connecting the Arduino analog input to N taps along the chain: N−1 taps in between consecutive resistors and one extra tap at GND¹.

simulate this circuit – Schematic created using CircuitLab

The push buttons could actually be the multiple contacts of a rotary switch. If using real push buttons, it would be tricky to know whether a button is being pushed or if you are just reading noise, though it can be known by toggling the pin between output and input and using its stray capacitance.

In this case, the worst case error happens when all the resistors on one side of the tap are 5% too high, while all those at the other side are 5% too low. It can be easily shown that the minimum possible voltage at tap k is

V(k) = k(1−e)/(k(1−e) + (N−k)(1+e))×Vcc

where e = 0.05 is the 5% tolerance of the resistors. The maximum possible voltage, V+(k), is given by the same formula after replacing e by −e.

The graph below shows the expected voltage at each tap for a chain of 20 resistors, with the error bars showing the possible voltage ranges. The blue curves are the analytical expressions of V(k) and V+(k).

As can be seen on the graph, the largest error bars are the ones closer to the central tap. Thus, the buttons can be discriminated accurately if the two taps closest to the center have non overlapping error bars. This criterion could be translated into an exact formula, but the formula would be quite complex and depend on the parity of N. I propose to do instead some approximations, starting with a first order Taylor expansion on the error. This expansion gives the length of the error bars as

V+(k) − V(k) ≈ 4/N2 k (N−k) e × Vcc

This error is maximal when k = N/2 (we will forget the parity issue):

V+(N/2) − V(N/2k) ≈ e × Vcc

Then we say that the taps can be discriminated if this error is smaller than the expected voltage difference between consecutive taps, namely Vcc/N. Then the criterion is now simply

N ≤ 1/e

which is exactly what your intuition told you.

---

¹ The extra tap could be at Vcc rather than GND. It would be unwise, however, to tap *both* GND and Vcc, as a user pressing both buttons simultaneously would then short the power supply.

---

**Edit** to answer the questions in comments.

Yes, you could use the expressions of V+ and V to set the thresholds for discriminating the buttons. For example, you could set the threshold between k and k+1 halfway between V+(k) and V(k+1), i.e.

threshold(k, k+1) = (V+(k) + V(k+1)) / 2

However, if you try to compute that, you will see that it is extremely close the average between the expected voltages. Then, you could use that average as your threshold, which is given by a very simple formula:

threshold(k, k+1) = (k+½)/N×Vcc

Then, the pin number is just the integer closest to Vin/Vcc×N. Assuming N = 20, this can be written as:

```
const float VCC = 5.0
float voltage = analogRead(PIN) * VCC / 1024;
int button_number = round(voltage / VCC * 20);

```

This can be optimized to use only integer arithmetics:

```
int button_number = (analogRead(PIN) * 5 + 128) >> 8;

```

Note that 20 buttons is kind of borderline. Your system could fail if the errors due to resistor inaccuracies and those intrinsic to the ADC (offset, gain error...) add up the wrong way. If you are building only one device, then the safest fix would be to take note of the value `analogRead()` returns for each button, and set the thresholds halfway between consecutive values.

You could also measure the resistances of all your resistors, and arrange them in a way that minimizes the errors. For example, if you number the resistors from 0 to 19 in order of increasing resistance, I would build the chain by arranging them in the following order:

0 19 2 17 4 15 6 13 8 11 9 10 7 12 5 14 3 16 1 18

Then you could most likely use the simple formula above to get the button number at a minimal computing cost.
> 1 votes

# Answer
The same the same technique is used routinely for 4x4 keypads. You don't really need very precise resistor as long as the final divider produce final voltage that are differente enough.

For each button/key you need to reserve some voltage range for it. You can expected some random fluctuation every time you read the analog input, so you need some safety margin.

I think you can use up to 32 button/key using this technique. That's give you 150 mV of distance between each button (or +/- 32 for the corresponding analog value.
> 0 votes

# Answer
You're just making a voltage resistor divider, with Vin at the top of the string of resistors, Vout at the selected resistor junction, and Gnd at the bottom. Using 5V as Vin, then

Vout = Vin x (sum of resistance below the junction)/(sum of the entire string).

For example, 10 1K resistors, and the junction is between resistors 5 and 6 (resistor 1, R1, connected to Vin, resistor 10, R10, to Gnd).

Vout = 5V * 5,000/(10,000) = 2.5V

Arduino will return a reading of ~ 2.5V/5V * 1024 = 512 (~4.88mV per step)

Connect between R7 and R8

Vout = 5V * 3,000/(10,000) = 1.5V

analogRead = ~1.5/5 * 1024 = 307
> 0 votes

---
Tags: electronics, resistor
---


# Question
Title: Issue programming breadboarded Arduino via FTDI chip
I am trying to upload the Blink sketch to my ATmega chip which is now on a breadboard connected via an FTDI chip.

My clock is running, power is OK. I connected the reset pin via a 100 kohm to the vcc and have a 0.1 uF capacitor between the reset pin and the DTR pin of my FTDI chip.

Connections to the PCB with the FTDI chip:

Does anybody know what I am doing incorrectly?

On a side note, I am running Ubuntu 16.04

All this seems correct to me, yet when I try to program the controller I get this exact:

```
/home/yalishanda/Downloads/arduino-1.8.5/arduino-builder -dump-prefs -logger=machine -hardware /home/yalishanda        /Downloads/arduino-1.8.5/hardware -tools /home/yalishanda/Downloads/arduino-1.8.5/tools-builder -tools /home/yalishanda    /Downloads/arduino-1.8.5/hardware/tools/avr -built-in-libraries /home/yalishanda/Downloads/arduino-1.8.5/libraries -libraries     /root/Arduino/libraries -fqbn=arduino:avr:uno -ide-version=10805 -build-path /tmp/arduino_build_476404 -warnings=none -build-        cache /tmp/arduino_cache_889393 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arduinoOTA.path=/home/yalishanda/Downloads/arduino-1.8.5/hardware/tools/avr -prefs=runtime.tools.avrdude.path=/home/yalishanda/Downloads/arduino-1.8.5/hardware/tools/avr -prefs=runtime.tools.avr-gcc.path=/home/yalishanda/Downloads/arduino-1.8.5/hardware/tools/avr -verbose /home/yalishanda/Downloads/arduino-1.8.5/examples/01.Basics/Blink/Blink.ino
/home/yalishanda/Downloads/arduino-1.8.5/arduino-builder -compile -logger=machine -hardware /home/yalishanda/Downloads/arduino-1.8.5/hardware -tools /home/yalishanda/Downloads/arduino-1.8.5/tools-builder -tools /home/yalishanda    /Downloads/arduino-1.8.5/hardware/tools/avr -built-in-libraries /home/yalishanda/Downloads/arduino-1.8.5/libraries -libraries /root/Arduino/libraries -fqbn=arduino:avr:uno -ide-version=10805 -build-path /tmp/arduino_build_476404 -warnings=none -build-cache /tmp/arduino_cache_889393 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arduinoOTA.path=/home/yalishanda/Downloads/arduino-1.8.5/hardware/tools/avr -prefs=runtime.tools.avrdude.path=/home/yalishanda/Downloads/arduino-1.8.5/hardware/tools/avr -prefs=runtime.tools.avr-gcc.path=/home/yalishanda/Downloads/arduino-1.8.5/hardware    /tools/avr -verbose /home/yalishanda/Downloads/arduino-1.8.5/examples/01.Basics/Blink/Blink.ino
Using board 'uno' from platform in folder: /home/yalishanda/Downloads/arduino-1.8.5/hardware/arduino/avr
Using core 'arduino' from platform in folder: /home/yalishanda/Downloads/arduino-1.8.5/hardware/arduino/avr
Detecting libraries used...
"/home/yalishanda/Downloads/arduino-1.8.5/hardware/tools/avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10805 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-I/home/yalishanda/Downloads/arduino-1.8.5/hardware/arduino/avr/cores/arduino" "-I/home/yalishanda/Downloads/arduino-1.8.5/hardware/arduino/avr/variants/standard" "/tmp/arduino_build_476404/sketch/Blink.ino.cpp" -o "/dev/null"
Generating function prototypes...
"/home/yalishanda/Downloads/arduino-1.8.5/hardware/tools/avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10805 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-I/home/yalishanda/Downloads/arduino-1.8.5/hardware/arduino/avr/cores/arduino" "-I/home/yalishanda/Downloads/arduino-1.8.5/hardware/arduino/avr/variants/standard" "/tmp/arduino_build_476404/sketch/Blink.ino.cpp" -o "/tmp/arduino_build_476404/preproc/ctags_target_for_gcc_minus_e.cpp"
"/home/yalishanda/Downloads/arduino-1.8.5/tools-builder/ctags/5.8-arduino11/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "/tmp/arduino_build_476404/preproc/ctags_target_for_gcc_minus_e.cpp"
Compiling sketch...
"/home/yalishanda/Downloads/arduino-1.8.5/hardware/tools/avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10805 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-I/home/yalishanda/Downloads/arduino-1.8.5/hardware/arduino/avr/cores/arduino" "-I/home/yalishanda/Downloads/arduino-1.8.5/hardware/arduino/avr/variants/standard" "/tmp/arduino_build_476404/sketch/Blink.ino.cpp" -o "/tmp/arduino_build_476404/sketch/Blink.ino.cpp.o"
Compiling libraries...
Compiling core...
Using previously compiled file: /tmp/arduino_build_476404/core/wiring_pulse.S.o
Using previously compiled file: /tmp/arduino_build_476404/core/WInterrupts.c.o
Using previously compiled file: /tmp/arduino_build_476404/core/hooks.c.o
Using previously compiled file: /tmp/arduino_build_476404/core/wiring.c.o
Using previously compiled file: /tmp/arduino_build_476404/core/wiring_analog.c.o
Using previously compiled file: /tmp/arduino_build_476404/core/wiring_digital.c.o
Using previously compiled file: /tmp/arduino_build_476404/core/wiring_pulse.c.o
Using previously compiled file: /tmp/arduino_build_476404/core/wiring_shift.c.o
Using previously compiled file: /tmp/arduino_build_476404/core/CDC.cpp.o
Using previously compiled file: /tmp/arduino_build_476404/core/HardwareSerial.cpp.o
Using previously compiled file: /tmp/arduino_build_476404/core/HardwareSerial0.cpp.o
Using previously compiled file: /tmp/arduino_build_476404/core/HardwareSerial1.cpp.o
Using previously compiled file: /tmp/arduino_build_476404/core/HardwareSerial2.cpp.o
Using previously compiled file: /tmp/arduino_build_476404/core/HardwareSerial3.cpp.o
Using previously compiled file: /tmp/arduino_build_476404/core/IPAddress.cpp.o
Using previously compiled file: /tmp/arduino_build_476404/core/PluggableUSB.cpp.o
Using previously compiled file: /tmp/arduino_build_476404/core/Print.cpp.o
Using previously compiled file: /tmp/arduino_build_476404/core/Stream.cpp.o
Using previously compiled file: /tmp/arduino_build_476404/core/Tone.cpp.o
Using previously compiled file: /tmp/arduino_build_476404/core/USBCore.cpp.o
Using previously compiled file: /tmp/arduino_build_476404/core/WMath.cpp.o
Using previously compiled file: /tmp/arduino_build_476404/core/WString.cpp.o
Using previously compiled file: /tmp/arduino_build_476404/core/abi.cpp.o
Using previously compiled file: /tmp/arduino_build_476404/core/main.cpp.o
Using previously compiled file: /tmp/arduino_build_476404/core/new.cpp.o
Using previously compiled file: /tmp/arduino_build_476404/core/core.a
Archiving built core (caching) in: /tmp/arduino_cache_889393    /core/core_arduino_avr_uno_fbfa3aa7d5698fed1dc5326dc32eae8f.a
Linking everything together...
"/home/yalishanda/Downloads/arduino-1.8.5/hardware/tools/avr/bin/avr-gcc" -w -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -mmcu=atmega328p  -o "/tmp/arduino_build_476404/Blink.ino.elf" "/tmp/arduino_build_476404/sketch/Blink.ino.cpp.o"     "/tmp/arduino_build_476404/core/core.a" "-L/tmp/arduino_build_476404" -lm
"/home/yalishanda/Downloads/arduino-1.8.5/hardware/tools/avr/bin/avr-objcopy" -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0  "/tmp/arduino_build_476404/Blink.ino.elf"     "/tmp/arduino_build_476404/Blink.ino.eep"
"/home/yalishanda/Downloads/arduino-1.8.5/hardware/tools/avr/bin/avr-objcopy" -O ihex -R .eeprom      "/tmp/arduino_build_476404/Blink.ino.elf" "/tmp/arduino_build_476404/Blink.ino.hex"
Sketch uses 928 bytes (2%) of program storage space. Maximum is 32256 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.

/home/yalishanda/Downloads/arduino-1.8.5/hardware/tools/avr/bin/avrdude -C/home/yalishanda/Downloads/arduino-1.8.5/hardware/tools/avr/etc/avrdude.conf -v -patmega328p -cstk500v1 -P/dev/ttyUSB0 -Uflash:w:/tmp/arduino_build_476404/Blink.ino.hex:i

avrdude: Version 6.3, compiled on Jan 17 2017 at 11:00:16
     Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
     Copyright (c) 2007-2014 Joerg Wunsch

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

     Using Port                    : /dev/ttyUSB0
     Using Programmer              : stk500v1
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x00
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x00
...

```

# Answer
> 2 votes
Right now you don't have a bootloader on your chip that's the reason why it wouldn't be programmed via UART so to flash the bootloader you need an ISCP programmer and an arduino bootloader.hex file.

# Answer
> -1 votes
10K reset pullup. Check your crystal caps, they should be 22pF.

The response does look like the chip does not have a bootloader tho. Or Rx & Tx lines are swapped.

---
Tags: uploading, breadboard
---


title: Extending EEPROM life

text:
# Question
Title: Extending EEPROM life
I'm working on some software using an Uno (ATmega328P). I have a stage byte that can be 1 of 5 values (0-4) in my code and it will increase by 1 every 2.5 hours. If I lose power I need to ensure that on wake up the stage is the same as it was at the time of power loss, so each time the stage is updated I save it to EEPROM.

To ensure the EEPROM lasts as long as possible I want to write some code that uses more than a single byte which I continually erase and write to. I was wondering if there is any library to do this or if my idea below would work?

I currently don't need to use the EEPROM for anything else so to extend the EEPROM life I was going to section of 1 quarter of it (0-255 bytes) for saving this value. Each time I change the stage I will write 3 bytes to EEPROM which will be:

* An index byte (used to shift addresses I write to).
* A stage byte (the stage I need to store).
* A count byte (the amount of times I have wrote the stage at the current index).

To begin with the index will be written to byte 0 in the EEPROM, the stage to byte 1 and the count to byte 2.

My plan is to allow the stage to be written to byte 1 250 times, then clear the count and shift the index to 3. This will in turn move the bytes that the stage and count are being written to to 4 and 5. I will do this until the index reaches the end of the 255 bytes and then return the index to 0. So in total I should be able to shift 85 times.

Each byte has 100,000 erase/write cycles so this means I can pass through bytes 0-255 400 times, writing the stage 250 times each pass. So instead of having 100K writes I would have about 8.5 million writes.

This is my first idea and I realize there is also some waste in the way I do it. I haven't worked with EEPROM much and I was just hoping for some advice as I'm sure I could be going at this completely wrong.

# Answer
You can load spread by saving the current value ORred 0x80 or 0x00.

When writing you write to the next memory location and when it wraps you take the other value to OR with.

The values in the eeprom will be

```
[{0x00|value},{0x00|value},{0x00|value},...,{0x00|value},{0x00|value},{0x00|value},{0x80|value},{0x80|value},{0x80|value},...,{0x80|value},{0x80|value}]

```

or

```
[{0x80|value},{0x80|value},{0x80|value},...,{0x80|value},{0x80|value},{0x80|value},{0x00|value},{0x00|value},{0x00|value},...,{0x00|value},{0x00|value}]

```

Then you read the first and last byte and if the upper bit is equal you take the last value.

If they are not equal you binary search until to the position changes, the most recent value will be the one right before the change.
> 1 votes

# Answer
There are many ways of achieving what you want. The method I would use would be to use pairs of bytes, but split up differently.

For each 16 bits I would have 13 for a counter, and 3 for a value. The counter, being 13 bits, can count from 0 - 2^13-1, or 0 - 8191. The 3 value bits can store 0 - 2^3-1, or 0 - 7, which is fine for your 0-4 value.

The size of the counter is important, since it is more than double the number of 16-bit pairs in the EEPROM. Assuming a 1kB EEPROM that's 512 16-bit values, so you want more than 1024 values available in your counter (if you wanted to change the split to store a larger number...).

The algorithm is simple:

1. Read through the EEPROM looking at the next counter value. If the count increases by more than 1 the last value read is the current one.
2. If the count goes from 8191 to 0 then keep going, you have just looped is all.
3. Increase the counter by 1 and write to the EEPROM addresses where the count jumped by more than 1.

For example, if you have:

```
78 1
79 2
80 3
8191 7
8191 7
8191 7

```

you know that the space after 80 hasn't been used (0xFFFF is split as 0x1FFF and 0x7) so you write "81 4" to it.

Another:

```
8190 2
8191 3
0 4
1 0
2 1
7283 3
7284 4
7285 0

```

The jump from 8191 to 0 is just a wrap around and can be considered sequential. However the jump from 2 to 7283 isn't sequential, so you can overwrite entry 7283 with "3 2".

When you write, if you are going past the end of the EEPROM's memory space, you just loop back round to the start again.

This gives you 512 * 100,000 writes, or 51.2m writes.
> 0 votes

# Answer
Also, check that the values you want to write are actually changing. No point in erasing and writing a value that is already there. And you save 3.3 ms by not having to do the write.
> 0 votes

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


# Question
Title: ATmega 2560 with Arduino bootloader running issue
I have designed a board based on an ATmega2560 chip and I burned the bootloader by following this tutorial.

Now I am able to load Blinky and other programs using an FTDI cable. But the issue I am facing right now is the controller runs Blinky fine if I leave the FTDI connected there. If I disconnect the FTDI cable and power-cycle the board it is not running Blinky. If I connect the FTDI, right away it starts blinking.

It looks like something is wrong with my RESET pin connection? Here is what my RESET circuitry looks like:

* I also have tried by removing D1 diode but no luck !

# Answer
The issue was there was some noise on RX Pin of the chip and because of that when it is powered on in bootloader it was stuck at that place. And it was working good with FTDI because RX gets proper connection with my FTDI.

Solution:- Connect 10K pull-down on RX pin resolved this problem.
> 0 votes

# Answer
Or get rid of C6, I have never used that in a design.
> -1 votes

---
Tags: arduino-mega, reset, atmega2560
---


title: Set a pin HIGH when crash occurs

text:
# Question
Title: Set a pin HIGH when crash occurs
I'm using an ESP8266 (NodeMCU v3). I want to set a PIN high if a `soft wdt reset` occurs (not expecting one). Is there a way I can do that?

Can I attach something on TX pin of the board and watch for crash dump? Maybe another Arduino?

# Answer
> 1 votes
The ESP provides a reset reason API, which lets you differentiate between a crash and a normal reset:

```
extern "C" {
  #include "user_interface.h"
}

const char * const RST_REASONS[] =
{
  "REASON_DEFAULT_RST",
  "REASON_WDT_RST",
  "REASON_EXCEPTION_RST",
  "REASON_SOFT_WDT_RST",
  "REASON_SOFT_RESTART",
  "REASON_DEEP_SLEEP_AWAKE",
  "REASON_EXT_SYS_RST"
};

// .. in setup():

const rst_info * resetInfo = system_get_rst_info(); //populate reset info
String diag = String(RST_REASONS[resetInfo->reason]); // turn enum index to string

if(diag == "REASON_SOFT_WDT_RST") digitalWrite(TX, HIGH);// check string, take action

```

# Answer
> 0 votes
The ESP8266 should hold the pin LOW when it is active, letting it go high then signals that the program has crashed.

---
Tags: esp8266
---


# Question
Title: Combining code for multiple sensors (Current and Voltage Sensors) in one program
I need to operate 2 different sensors (Current and Voltage) simultaneously. I have managed to run each one of them separately and I don't know how to manipulate the code so they could work together. My background in coding is basic and I'm not the one who wrote these codes.

Here are the sketches:

**1. Current Sensor Code**

```
void setup() {

  Serial.begin(9600);
}

void loop() {

  float average = 0;
  for(int i = 0; i < 1000; i++) {
    average = average + (.0264 * analogRead(A0) -13.385) / 1000;//this is
    //for the 5A mode, if 20A or 30A mode, need to modify this formula to
    //(.19 * analogRead(A0) -25) for 20A mode and
    //(.044 * analogRead(A0) -3.78) for 30A mode
    delay(3);
  }
  Serial.println(average);
}

```

**2. Voltage Sensor Code**

```
/*
DC Voltmeter Using a Voltage Divider
Based on Code Created By
T.K.Hareendran
*/

int analogInput = A1;
float vout = 0.0;
float vin = 0.0;
float R1 = 30000.0; //
float R2 = 7500.0; //
int value = 0;
void setup(){
   pinMode(analogInput, INPUT);
   Serial.begin(9600);
   Serial.print("DC VOLTMETER");
}
void loop(){
   // read the value at analog input
   value = analogRead(analogInput);
   vout = (value * 5.0) / 1024.0; // see text
   vin = vout / (R2/(R1+R2));

Serial.print("INPUT V= ");
Serial.println(vin,2);
delay(500);
}

```

# Answer
> 2 votes
**How to combine two sketches.**

First, make sure every global variable and function name is unique (except setup and loop). Choose the smallest sketch and rename its. variables, function names and any other named items (like DEFINE).

Is convenient to refactor things. I extract the code for reading Voltage and Current to separate functions, to reduce the count of global variable and length of each function, making things easier by reducing the side of setup() and loop().

Now, combine the code inside the setup and loop:

```
const int analogInput = A1;

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

void loop(){
  Serial.print(getCurrent());
  Serial.print(" ");
  Serial.println(getVoltage(),2);
  delay(500);
}

float getCurrent() {
  float average = 0;
  for(int i = 0; i < 1000; i++) {
    average = average + (.0264 * analogRead(A0) -13.385) / 1000;//this is
    //for the 5A mode, if 20A or 30A mode, need to modify this formula to
    //(.19 * analogRead(A0) -25) for 20A mode and
    //(.044 * analogRead(A0) -3.78) for 30A mode
    delay(3);
  }
return average;
}

float getVoltage() {
   const float R1 = 30000.0; //
   const float R2 = 7500.0; //
   float value = analogRead(analogInput);
   float vout = (value * 5.0) / 1024.0; // see text
   float vin = vout / (R2/(R1+R2));
  return vin;
}

```

# Answer
> 1 votes
The bigger problem regarding combining the code is timing. You can't use `delay()` because the other code can't run.

You need to do let `loop()` run through as fast as possible and only do things when you need to i.e. when certain time elapses. And you do that with `millis()`, like in the Blink Without Delay example.

In your case, current reading code also needs to keep track of number of samples read and react when the sample count is reached.

```
const byte current_pin = A0;
const byte voltage_pin = A1;

const int max_current_sample_count = 1000;
const int current_sample_interval = 3;
const int voltage_sample_interval = 500;

// voltage divider parameters
const float R1 = 30000;
const float R2 = 7500;

// 5A current sensor parameters
const float current_sensor_scale = 0.0264;
const float current_sensor_offset = -13.385;

float current_sum = 0; // for accumulated measurements
int current_count = 0; // counter for measurements

unsigned long last_current_measure = 0; // for timing the current measurement
unsigned long last_voltage_measure = 0; // for timing the voltagemeasurement

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

void loop() {
    unsigned long time = millis();

    if (time - last_current_measure > current_sample_interval) { // if enough time elapsed to make another measurement
        last_current_measure = time; // save the time this action ran

        current_sum += current_sensor_scale * analogRead(current_pin) + current_sensor_offset;
        current_count++; // increase the counter
        if (current_count >= max_current_sample_count) { // when we reached number of samples
            // output the average and reset the sum and counter
            Serial.print("A = ");
            Serial.println(current_sum/current_count);
            current_sum = 0;
            current_count = 0;
        }
    }
    if (time - last_voltage_measure > voltage_sample_interval) { // if enough time elapsed to make another measurement
        last_voltage_measure = time; // save the time this action ran

        int value = analogRead(voltage_pin);
        float vout = (value * 5) / 1024.0;
        float vin = vout / (R2/(R1+R2));
        Serial.print("V = ");
        Serial.println(vin, 2);
    }
}

```

It is also a good practice that some values, that might need to be changed, are defined as constants. So you don't need to search for them inside the code which can become a problem, when you write more code. And it can prevent bugs, if you have those values in multiple places and forgot to change one.

# Answer
> 0 votes
**WARNING** The following advice does not generally produce compiling or working code, but is one way to start merging two separate sketches.

Without getting into the details of the code (we are not here to write code for free) I can give you the general guidelines:

* put all the declarations (anything not contained in the `setup` or `loop` functions) at the top, first all from one sketch, then all from the other
* copy the `setup` function from the first sketch and paste it after all the declarations
* copy the content (anything inside the curly braces) of the `setup` function from the second sketch and put it inside the same function, but after all the first sketch code
* rinse and repeat the last two steps for the `loop` functions

At this point the you might have variable name collisions and plenty of other issues, but looking at the type of code you are trying to mesh, it should work

---
Tags: sensors, current, voltage
---


# Question
Title: Problem "Didn't find PN53x board" in Arduino Uno E-Card Reader
This is component to make E-Card reader, using arduino uno pn532

**Code**

```
  if (success) {
    // Display some basic information about the card
    Serial.println("Found an ISO14443A card");
    Serial.print("  UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
    Serial.print("  UID Value: ");
    nfc.PrintHex(uid, uidLength);
    Serial.println("");

    if (uidLength == 4)
    {
      // We probably have a Mifare Classic card ...
      Serial.println("Seems to be a Mifare Classic card (4 byte UID)");

      // Now we need to try to authenticate it for read/write access
      // Try with the factory default KeyA: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
      Serial.println("Trying to authenticate block 4 with default KEYA value");
      uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

      // Start with block 4 (the first block of sector 1) since sector 0
      // contains the manufacturer data and it's probably better just
      // to leave it alone unless you know what you're doing
      success = nfc.mifareclassic_AuthenticateBlock(uid, uidLength, 4, 0, keya);

      if (success)
      {
        Serial.println("Sector 1 (Blocks 4..7) has been authenticated");
        uint8_t data[16];

        // If you want to write something to block 4 to test with, uncomment
        // the following line and this text should be read back in a minute
        //memcpy(data, (const uint8_t[]){ 'a', 'd', 'a', 'f', 'r', 'u', 'i', 't', '.', 'c', 'o', 'm', 0, 0, 0, 0 }, sizeof data);
        //success = nfc.mifareclassic_WriteDataBlock (4, data);

        // Try to read the contents of block 4
        success = nfc.mifareclassic_ReadDataBlock(4, data);

        if (success)
        {
          // Data seems to have been read ... spit it out
          Serial.println("Reading Block 4:");
          nfc.PrintHexChar(data, 16);
          Serial.println("");

          // Wait a bit before reading the card again
          delay(1000);
        }
        else
        {
          Serial.println("Ooops ... unable to read the requested block.  Try another key?");
        }
      }
      else
      {
        Serial.println("Ooops ... authentication failed: Try another key?");
      }
    }

    if (uidLength == 7)
    {
      // We probably have a Mifare Ultralight card ...
      Serial.println("Seems to be a Mifare Ultralight tag (7 byte UID)");

      // Try to read the first general-purpose user page (#4)
      Serial.println("Reading page 4");
      uint8_t data[32];
      success = nfc.mifareultralight_ReadPage (4, data);
      if (success)
      {
        // Data seems to have been read ... spit it out
        nfc.PrintHexChar(data, 4);
        Serial.println("");

        // Wait a bit before reading the card again
        delay(1000);
      }
      else
      {
        Serial.println("Ooops ... unable to read the requested page!?");
      }
    }
  }
}

```

And i find problem, like this :

**EDIT:** Now has ben change to I2C mode and detected RFID. But not detected E-Card:

How solve this is problem?

# Answer
> 0 votes
if (success) { // Display some basic information about the card Serial.println("Found an ISO14443A card"); Serial.print(" UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes"); Serial.print(" UID Value: "); nfc.PrintHex(uid, uidLength); Serial.println("");

```
if (uidLength == 4)
{
  // We probably have a Mifare Classic card ...
  Serial.println("Seems to be a Mifare Classic card (4 byte UID)");

  // Now we need to try to authenticate it for read/write access
  // Try with the factory default KeyA: 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
  Serial.println("Trying to authenticate block 4 with default KEYA value");
  uint8_t keya[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

  // Start with block 4 (the first block of sector 1) since sector 0
  // contains the manufacturer data and it's probably better just
  // to leave it alone unless you know what you're doing
  success = nfc.mifareclassic_AuthenticateBlock(uid, uidLength, 4, 0, keya);

  if (success)
  {
    Serial.println("Sector 1 (Blocks 4..7) has been authenticated");
    uint8_t data[16];

    // If you want to write something to block 4 to test with, uncomment
    // the following line and this text should be read back in a minute
    //memcpy(data, (const uint8_t[]){ 'a', 'd', 'a', 'f', 'r', 'u', 'i', 't', '.', 'c', 'o', 'm', 0, 0, 0, 0 }, sizeof data);
    //success = nfc.mifareclassic_WriteDataBlock (4, data);

    // Try to read the contents of block 4
    success = nfc.mifareclassic_ReadDataBlock(4, data);

    if (success)
    {
      // Data seems to have been read ... spit it out
      Serial.println("Reading Block 4:");
      nfc.PrintHexChar(data, 16);
      Serial.println("");

      // Wait a bit before reading the card again
      delay(1000);
    }
    else
    {
      Serial.println("Ooops ... unable to read the requested block.  Try another key?");
    }
  }
  else
  {
    Serial.println("Ooops ... authentication failed: Try another key?");
  }
}

if (uidLength == 7)
{
  // We probably have a Mifare Ultralight card ...
  Serial.println("Seems to be a Mifare Ultralight tag (7 byte UID)");

  // Try to read the first general-purpose user page (#4)
  Serial.println("Reading page 4");
  uint8_t data[32];
  success = nfc.mifareultralight_ReadPage (4, data);
  if (success)
  {
    // Data seems to have been read ... spit it out
    nfc.PrintHexChar(data, 4);
    Serial.println("");

    // Wait a bit before reading the card again
    delay(1000);
  }
  else
  {
    Serial.println("Ooops ... unable to read the requested page!?");
  }
}

```

} }

# Answer
> 0 votes
This is sir, i check using white card

---
Tags: arduino-uno, arduino-ide, code-review, rfid
---


# Question
Title: Problem with SPI comms using NodeMCU v 3, Nano and SD
Recently I bought a NodeMCU 8266 v 3 (Lolin) and it works fine. I set up a Catalex SD card module (with a built-in 5-3.3V regulator) and all was good. Then I set the Lolin with an Arduino Uno and or a Nano working for SPI communications and all worked properly. So when I tried to put the Lolin as master, and two slaves (a Nano and an SD Card), all working with SPI, it did not work.

If I set up the SD card Vcc to 5 volts, the Lolin can "see" it and initializes it, but the communication between the Lolin and the Nano crashes (the Lolin can send the data but receives only trash; the Nano can receive and consequentely responds). When I disconnect the SD Vcc cable the communications works.

So I tried to remedy this situation using a bidirectional level shifter and the Lolin seems frozen.

Any help is welcome.

Code of Lolin (as Master).

```
/*Master - ESP12e create a variable string to be sent to slave - Nano_ChipSelect
    and receive a variable answer.

    Master ESP12e use:    COM5
          * SPI communications with a NANO as slave in GPIO 0 = D3
          * WiFi communication
          * a DS3231 for RTC
          * a catalex SD memory
*/

/*---------------( Import needed libraries )-------------------------------------*/
#include <ESP8266WiFi.h>                            // WiFi
#include <WiFiClientSecure.h>                       // SSL Client
#include <SPI.h>                                    // SPI comms
#include <SD.h>                                     // SD mem card
#include <Wire.h>                                   // RTC comms
#include "RtcDS3231.h"                              // RTC by maluma

/*---------------( Define Constants )--------------------------------------------*/
#define Nano_ChipSelect             D3              // Slave select signal for NANO
#define SD_ChipSelect               D8              // Slave select signal for SD

/*---------------( Declare objects )---------------------------------------------*/
RtcDS3231<TwoWire>    Rtc(Wire);
File                  myFile;
WiFiClientSecure      client;

/*---------------( Declare Special settings--------------------------------------*/
SPISettings           Set_SPI_NANO( 1000000, MSBFIRST, SPI_MODE0 );

/*---------------( Declare Constants )--------------------*/
String        defaultChatId         = "5";
char          ssid[]                = "scouts";     // network SSID (name)
char          password[]            = "R";   // network key

/*---------------( Declare Variables )-------------------------------------------*/
bool          switch_Red            = false;
bool          switch_Yell           = false;
bool          switch_Green          = false;
unsigned int  temp_ESP12e            = 0;
unsigned int  temp_nano             = 0;
unsigned int  hum_nano              = 0;
char          datestring[20];
char          Nano_S_to_send[]      = "0000000000000000000000000|";
//                                    "RRYYGcGYYYYcMMDDHcHMMSScc|"
//                                     01234567890123456789012345
//                                     0         1         2
char          Nano_S_to_receive []  = "0000000000000000000000000|";
//                                    "TTTTTcHHHHHcIIIIIcDDDDDcc|
//                                     01234567890123456789012345
//                                     0         1         2
byte          Leds                  = 0;

#define countof( a ) ( sizeof( a ) / sizeof( a[ 0 ] ) )

void _printDateTime( const RtcDateTime& dt ) {  //---------------------------------
    snprintf_P(datestring,
            countof(datestring),
            PSTR("%04u/%02u/%02u %02u:%02u:%02u"),
            dt.Year(),
            dt.Month(),
            dt.Day(),
            dt.Hour(),
            dt.Minute(),
            dt.Second() );
}

void _create_data_for_nano() {  //-------------------------------------------------
  RtcDateTime now = Rtc.GetDateTime();
  _printDateTime( now );
  //;
  //             RRYYGcGYYYYcMMDDHcHMMSScc|
  //             0000000000000000000000000|
  Nano_S_to_send[ 0 ] = _getbit( Leds, 0 );  // red status
  Nano_S_to_send[ 1 ] = _getbit( Leds, 1 );  // red status
  Nano_S_to_send[ 2 ] = _getbit( Leds, 2 );  // yellow status
  Nano_S_to_send[ 3 ] = _getbit( Leds, 3 );  // yellow status
  Nano_S_to_send[ 4 ] = _getbit( Leds, 4 );  // green status
  Nano_S_to_send[ 5 ] = _Nano_CRC( 0, 5 );
  Nano_S_to_send[ 6 ] = _getbit( Leds, 5 );  //green status
  Nano_S_to_send[ 7 ] = datestring[ 0 ];  //y
  Nano_S_to_send[ 8 ] = datestring[ 1 ];  //y
  Nano_S_to_send[ 9 ] = datestring[ 2 ];  //y
  Nano_S_to_send[ 10 ] = datestring[ 3 ];  //y
  Nano_S_to_send[ 11 ] = _Nano_CRC( 6, 5 );
  Nano_S_to_send[ 12 ] = datestring[ 5 ];  //m
  Nano_S_to_send[ 13 ] = datestring[ 6 ];  //m
  Nano_S_to_send[ 14 ] = datestring[ 8 ];  //d
  Nano_S_to_send[ 15 ] = datestring[ 9 ];  //d
  Nano_S_to_send[ 16 ] = datestring[ 11 ];  //h
  Nano_S_to_send[ 17 ] = _Nano_CRC( 12, 5 );
  Nano_S_to_send[ 18 ] = datestring[ 12 ];  //h
  Nano_S_to_send[ 19 ] = datestring[ 14 ];  //m
  Nano_S_to_send[ 20 ] = datestring[ 15 ];  //m
  Nano_S_to_send[ 21 ] = datestring[ 17 ];  //s
  Nano_S_to_send[ 22 ] = datestring[ 18 ];  //s
  Nano_S_to_send[ 23 ] = _Nano_CRC( 18, 5 );
  Nano_S_to_send[ 24 ] = _Nano_CRC( 0, 24 );
}

char _getbit( byte data, byte pos ){
  byte b = data >> pos;
  b = b & 1;
  char b1[] = { '0' };
  if( b ) b1[ 0 ] = '1';
  return b1[ 0 ];
}

char _Nano_CRC( byte pos, byte lon ) {  //---------------------------------------------
  int  suma = 0;
  bool par  = false;
  for( int i = 0 ; i < lon ; i++ ) {
    suma += char( Nano_S_to_send[ i + pos ] );
    if( par )  {
      suma += 2 * char( Nano_S_to_send[ i + pos ] );
    }
    par = !par;
  }
  int  b = suma/10;
  if( suma != b*10 )  b++;
  b *= 10;
  char resultado[ 2 ];
  itoa( b - suma, resultado, 10 );
  return resultado[ 0 ];
}

void _transfer_data_to_NANO_by_spi() {  //----------------------------------------
  char c[2];
  digitalWrite( SD_ChipSelect, HIGH );
  cli();
  byte index2 = 0;
  SPI.beginTransaction( Set_SPI_NANO );
  digitalWrite( Nano_ChipSelect, LOW );
  byte num_char_to_transfer = sizeof( Nano_S_to_send ) ;
  for( byte index = 0 ; index <= num_char_to_transfer ; index++ ) {
    c[ 1 ] = ( Nano_S_to_send[ index ] );
    c[ 0 ] = SPI.transfer( c[ 1 ] );
    if( index != num_char_to_transfer ) Nano_S_to_receive [ index2 ] = 'E';
    if( c[ 0 ] != '\0' ) {
      Nano_S_to_receive [ index2 ] = c[ 0 ];
    }
    if( index != 0 ) index2++;
    delayMicroseconds( 2 );
  }
  digitalWrite(Nano_ChipSelect, HIGH);
  //Serial.print("-->");Serial.print(Nano_S_to_receive);Serial.println("<--");
  sei();
  SPI.endTransaction ();
}

String _txt2str( int valor ){  //-------------------------------------------------
  char v_txt[]= "000";
  itoa( valor, v_txt, 10 );
  String v_text = "";
  for( int i = 0 ; i < 4 ; i++ ){
    if( v_txt[ 3-i ] != '\0' ) {
      v_text = v_txt[ 3-i ]+ v_text;
    }
  }
  return v_text;
}

int _convierte( byte pos ){  //---------------------------------------------------
    char temporal [] = "     ";
    for( int i = 0 ; i < 4 ; i++ )  {
      temporal [ i ] = Nano_S_to_receive [ i + 1 + pos ];
    }
    int temp = atoi( temporal);
    return temp;
}

void setup() {   /*-----------( SETUP: RUNS ONCE )------------------------------*/
  pinMode( SD_ChipSelect,   OUTPUT );          // configure the line as output
  pinMode( Nano_ChipSelect, OUTPUT );          // configure the line as output

  Serial.begin( 115200 );              // start the serial monitor
  digitalWrite( SD_ChipSelect,   HIGH );       // turn to HIGH to disable
  digitalWrite( Nano_ChipSelect, HIGH );       // turn to HIGH to disable slave

  Serial.println();
  Serial.print( "compiled: " );Serial.print( __DATE__ );
  Serial.print( " at " );Serial.println( __TIME__ );
  Serial.print( "Connecting Wifi: " );
  Serial.println( ssid );

  Rtc.Begin();

  RtcDateTime compiled = RtcDateTime( __DATE__, __TIME__ );
  RtcDateTime now = Rtc.GetDateTime();
  _printDateTime( now );
  Serial.print(" --- Initialized WiFi at ");
  Serial.println( datestring );

  if ( !Rtc.IsDateTimeValid() )   {
        Serial.println( "RTC lost confidence in the DateTime!" );
        Rtc.SetDateTime( compiled );
        RtcDateTime now = Rtc.GetDateTime();
        _printDateTime( now );
  }

  if( !Rtc.GetIsRunning() )  {
    Serial.println( "RTC was not actively running, starting now" );
    Rtc.SetIsRunning( true );
  }

   if ( now < compiled )     {
    Serial.println( "RTC is older than compile time!  (Updating DateTime)");
    Rtc.SetDateTime( compiled );
  } else if( now > compiled )    {
      Serial.println( "RTC is newer than compile time. (this is expected)" );
    } else if ( now == compiled )     {
        Serial.println( "RTC is the same as compile time!");
      }
  Rtc.Enable32kHzPin( false );
  Rtc.SetSquareWavePin( DS3231SquareWavePin_ModeNone );

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

  SPI.begin();
  /* begin SPI at 1 Mbit rate most significat bit first & mode 0 */
  SPI.beginTransaction( SPISettings( 1000000, MSBFIRST, SPI_MODE0 ) );
  digitalWrite( SD_ChipSelect, LOW );

  if ( !SD.begin( SD_ChipSelect ) ) {
    Serial.println( "initialization failed!" );
    return;
  }
  myFile = SD.open( "Log_1.txt", FILE_WRITE );
  if (myFile) {                           // if the file opened okay, write to it:
    myFile.println( "YYYY:MM:DD:HH:MM:SS:TNANO:HNANO:TESP12e" );
    // close the file:
    myFile.close();
  } else {                             // if the file didn't open, print an error:
    Serial.println( "error opening file Log_1.txt" );
  }

  digitalWrite( SD_ChipSelect, HIGH );
  SPI.endTransaction();

  Serial.println( "*****  initialization done. ******" );
}

void loop() {  //-----------------------------------------------------------------

  Serial.println("*********** E S P 1 2 ***********");
  RtcTemperature temp = Rtc.GetTemperature();
  temp_ESP12e = temp.AsFloat() * 100;                         // System Temperature

  _create_data_for_nano();
  _transfer_data_to_NANO_by_spi();       // transfer routine to send and receive data
  //_check_received_data();

  Serial.print( "->NANO:" );Serial.print(    Nano_S_to_send );Serial.println(":");
  Serial.print( "NANO<-:" );Serial.print( Nano_S_to_receive );Serial.println(":");

  Leds++;
  if( Leds > 64 ) Leds = 0;
  delay(5000);
}

```

Code of nano ( as slave )

```
/* Slave - Nano receive a variable string, byte by byte from
 *  master - ESP12e and create a variable answer

      Slave NANO use:    COM3
           * SPI communications
           * an AM2302 sensor for temperature and humidity
           * timers
*/

/*---------------( Import needed libraries )-------------------------------------*/
#include <SPI.h>
#include <DHT.h>
#include "DHT_U.h"
#include "SimpleTimer.h"
#include "Adafruit_Sensor.h"

/*---------------( Define Constants )--------------------------------------------*/
#define switch_Yell       2
#define switch_Green      4
#define switch_Red        6
#define DHTPIN            9         // Pin connected to the DHT sensor.

#define DHTTYPE           DHT22     // DHT 22 (AM2302)

/*---------------( Declare objects )---------------------------------------------*/
SimpleTimer timer;
DHT_Unified dht(DHTPIN, DHTTYPE);

/*---------------( Declare Special settings--------------------------------------*/

/*---------------( Declare Constants )--------------------*/

/*---------------( Declare Variables )-------------------------------------------*/
uint32_t       waiting_for_AM2302;
char           string_to_receive[] = "0000000000000000000000000|";
//                                   "RRYYGcGYYYYcMMDDHcHMMSScc|"
//                                    01234567890123456789012345
//                                    0         1         2
char           string_to_answer[]  = "0000000000000000000000000|";
//                                   "TTTTTcHHHHHcIIIIIcDDDDDcc|
//                                    01234567890123456789012345
//                                    0         1         2
volatile byte  index;
volatile bool  receivedone;  /* used as reception complete flag */
byte           Dummy               = 0;

// function to be called repeatedly by timer function
void Read_AM2302() {  //-----------------------------------------------------------

  int tempera    = -1;
  int humidit    = -1;
  int illumin    = -1;
  int dummy       = -1;
  sensors_event_t event;
  // Get temperature event and print its value.
  dht.temperature().getEvent(&event);
  if (isnan(event.temperature)) {
    Serial.println("Error reading temperature!");
  }
  else {
    tempera = event.temperature * 10;
  }
  // Get humidity event and print its value.
  dht.humidity().getEvent(&event);
  if (isnan(event.relative_humidity)) {
    Serial.println("Error reading humidity!");
  }
  else {
    humidit = event.relative_humidity * 10;
  }

//  tempera = 9;
//  humidit = 72;
  illumin = 143;

  _create_answer( tempera,   0 );
  string_to_answer[  5 ] = _CRC(  0,  5 );
  _create_answer( humidit,      6 );
  string_to_answer[ 11 ] = _CRC(  6,  5 );
  _create_answer( illumin, 12 );
  string_to_answer[ 17 ] = _CRC( 12,  5 );
  //_create_answer( Dummy,       18 );
  string_to_answer[ 18 ] = _getbit( Dummy, 4 );
  string_to_answer[ 19 ] = _getbit( Dummy, 3 );
  string_to_answer[ 20 ] = _getbit( Dummy, 2 );
  string_to_answer[ 21 ] = _getbit( Dummy, 1 );
  string_to_answer[ 22 ] = _getbit( Dummy, 0 );
  string_to_answer[ 23 ] = _CRC( 18,  5 );
  string_to_answer[ 24 ] = _CRC(  0, 24 );
  /*
  Serial.print(" Temperature =");Serial.println( tempera );
  Serial.print(" Humidity     =");Serial.println( humidit );
  Serial.print(" Illumination =");Serial.println( illumin );
  Serial.print(" Dummy       =");Serial.println( Dummy   );
  Serial.print("Answer-->"); Serial.println( string_to_answer );
  */
}

char _getbit( byte data, byte pos ){
  byte b = data >> pos;
  b = b & 1;
  char b1[] = { '0' };
  if( b ) b1[ 0 ] = '1';
  return b1[ 0 ];
}

char _CRC( byte pos, byte lon ) {  //----------------------------------------------
  int  suma = 0;
  bool par  = false;
  for( int i = 0 ; i < lon ; i++ ) {
    suma += char( string_to_answer[ i + pos ] );
    if( par )  {
      suma += 2 * char( string_to_answer[ i + pos ] );
    }
    /*
    Serial.print(" i=");Serial.print(i);
    Serial.print(" d=");Serial.print(string_to_answer[ i + pos ] );
    Serial.print(" s=");Serial.println( suma);
    */
    par = !par;
  }
  int  b = suma/10;
  if( suma != b*10 ) b++;
  b *= 10;
  char result[ 2 ];
  itoa( b - suma, result, 10 );
  /*
  Serial.print( "-S-" );Serial.print( sum );      Serial.println("---");
  Serial.print( "-B-" );Serial.print( b );        Serial.println("---");
  Serial.print( "-R-" );Serial.print( result[ 0 ] );Serial.println("---");
  */
  return result[ 0 ];
}
                   //      9         0
void _create_answer( int data, byte pos) {  //-------------------------------------
  char temporal[] = {'\0','\0','\0','\0','\0'};  // masc
  byte longitud = 5;          // posicion desde 0 hasta n
  byte puntero = pos + longitud; //5
  itoa( data, temporal, 10 );//9
  //Serial.print("-t-");Serial.println( temporal );
  //Serial.print("-s-");Serial.println( sizeof temporal );
  for( int i = longitud ; i >= 0 ; i-- ) {
    //Serial.print("-val-");Serial.println( (temporal[i]) );
    if( temporal[i] != '\0' ) {
    string_to_answer[ puntero-- ] = temporal [ i ];
    }
  }
}

// SPI interrupt routine
ISR (SPI_STC_vect) {  //-----------------------------------------------------------
  uint8_t oldsrg = SREG;
  cli();
  string_to_receive[ index ] = SPDR;
  SPDR = string_to_answer[ index ];
  if( string_to_receive [index] == '\0' ) receivedone = true;
  if( index < sizeof( string_to_receive ) ) index++;
  sei();
  SREG = oldsrg;
}

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

  pinMode(MISO, OUTPUT);
  SPCR |= _BV(SPE);    // turn on SPI in slave mode
  SPCR |= _BV(SPIE);   // turn on interrupts

  index = 0;
  receivedone = false;
  SPI.attachInterrupt();    /* Attach SPI interrupt */
  dht.begin();
  sensor_t sensor;
  dht.temperature().getSensor(&sensor);
  dht.humidity().getSensor(&sensor);
  waiting_for_AM2302 = sensor.min_delay / 1000;
  Serial.println("------------------------------------");
  Serial.println("Temperature");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value);
  Serial.println(" *C");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value);
  Serial.println(" *C");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution);
  Serial.println(" *C");
  Serial.println("------------------------------------");
  Serial.println("Humidity");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value);
  Serial.println("%");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value);
  Serial.println("%");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution);
  Serial.println("%");
  Serial.println("------------------------------------");
  timer.setInterval( waiting_for_AM2302, Read_AM2302 );
  pinMode( switch_Red,   OUTPUT );
  pinMode( switch_Yell,  OUTPUT );
  pinMode( switch_Green, OUTPUT );
  digitalWrite( switch_Red,   LOW );
  digitalWrite( switch_Yell,  LOW );
  digitalWrite( switch_Green, LOW );

}

void loop () {  //-----------------------------------------------------------------
    timer.run();
  if (receivedone) {         /* Check and print received buffer if any */
    Serial.println( "************ N A N O ************" );
    Serial.print( "ESP12e<-:" );Serial.print( string_to_receive );Serial.println( ":" );
    Serial.print( "->ESP12e:" );Serial.print( string_to_answer );Serial.println( ":" );
    //_check_received_data();
    digitalWrite( switch_Red,   string_to_receive[ 1 ] - 48 );
    digitalWrite( switch_Yell,  string_to_receive[ 3 ] - 48 );
    digitalWrite( switch_Green, string_to_receive[ 6 ] - 48 );
    string_to_receive[index] = 0;
    index = 0;
    receivedone = false;

    Dummy++;
    if( Dummy > 32 ) Dummy = 0;
  }
}

```

here is the Serial monitor view

```
Master
    ******* L O L I N *******
    ->NANO:1111191201800204282452676|:
    NANO<-:000EEEEEEEE :                     --- connected at 5V
    ******* L O L I N *******
    ->NANO:0000080201810204282453192|:
    NANO<-:00<:
    ******* L O L I N *******
    ->NANO:0000080201810204282453642|:
    NANO<-:EEEEEEEEEEEEEEEEEEEEEE:          ---- connected at 3.3 V
    ******* L O L I N *******
    ->NANO:1000070201810204282454160|:
    NANO<-:0000990007250014320806510|:      ---- disconnected

Slave
    ************ N A N O ************
    LOLIN<-:1111191201800204282452676|
    ->LOLIN:0000990007250014320806510|
    ************ N A N O ************
    LOLIN<-:0000080201810204282453192|
    ->LOLIN:0000990007250014320806510|
    ************ N A N O ************
    LOLIN<-:0000080201810204282453642|
    ->LOLIN:0000990007250014320806510|
    ************ N A N O ************
    LOLIN<-:1000070201810204282454160|
    ->LOLIN:0000990007250014320806510|

```

# Answer
> 0 votes
Use a tri-state buffer on the MISO pins of the SPI devices using the slave select as enable. It's the only way I could make it work.

---
Tags: arduino-nano, spi, sd
---


# Question
Title: Connecting arduino ground with battery powered remote control ground
I soldered a cable to the button of a remote control and I want to simulate that button press by setting the pin to input mode and back to output (LOW) again.

For this to work I connected the ground of the battery (black wire) to the GND of the arduino.

Is this 100% safe if I hook the arduino up to the power grid or to my pc?

I also disconnected the ground pins and had my arduino connected to my pc and suddenly it worked too. I got a BSoD shortly after.

# Answer
All grounds should be connected to provide a common reference point.
> 0 votes

# Answer
Unless you use *galvanic isolation* (see below) then yes, you *must* connect the grounds together. That is vital (see here).

The main concern though is the voltage you are switching. The Arduino cannot connect any of its IO pins directly to any voltage over 5V. Doing so will most likely damage your Arduino.

Instead, you need to use the Arduino to switch a device that will switch the button for you. The simplest is a BJT or MOSFET:

simulate this circuit – Schematic created using CircuitLab

But there are a couple of other caveats you should consider. The most important one is to do with how far away the remote device is, and how it is powered. Connecting the grounds of two devices that are very distant can get quite messy, since "ground" at different points may be at completely different potentials, and the voltage drop across the "ground" wire (wires don't have zero resistance) coupled with the existing ground connection through the power supplies creates a *ground loop* and introduces massive amounts of interference. For this kind of arrangement, it is good to introduce ...

## Galvanic Isolation

This electrically separates the two circuits completely. There is absolutely no electrical connection between your Arduino and the device you are switching.

The most common way of achieving this in low powered digital circuits is to use an opto-isolator (also called an opto-coupler). This is basically an LED and photo-transistor together in a single package. Turn the LED on and the phototransistor turns on. The basic arrangement is exactly the same as the circuit above, but the wire going in from the Arduino is connected to an LED:

simulate this circuit

Now you really don't care what ground potential is at the other end, nor how it is powered. As long as the opto-isolator can cope with the voltage it has to switch all will be good. Nothing in the remote circuit can do any damage at all to the Arduino since there is no way for current to flow back from that circuit to the Arduino.
> 0 votes

---
Tags: power, battery, wires
---


# Question
Title: Using TFT touchscreen with Arduino Uno R3 via I2C
I've recently gotten into Arduino, due to a friend asking to be part of a project. The project requires a few 24V LED strips to be controllable via PWM, probably over MOSFETs (we have someone else in the team that will look after the electronics, I will be mostly responsible for the code) and also various sensors to measure the environment. However, the project should also include a touchscreen that will be used for programming these LEDs based on time and date, and displaying the data from these sensors, or program further events based on their input.

As far as I understand it should be possible to drive a TFT touchscreen via I2C? I've done some googling over the past two hours or so and could barely find any information about what screens to use for such projects, no tutorials, nor if there are any libraries available.

Is it doable to do a project of this magnitude with a Uno R3, or should I consider a Due or Mega?

I have a touchscreen shield right here, but it leaves me with only one PWM and one analogue pin if I don't plan on using the SD card that is on its back.

Maybe I'll find the answer myself, but I have literally only joined the Arduino/microcontroller fun a few days ago and am reading up on the whole topic in a 'for dummies' book which is very interesting, but it only touches on I2C at the very end and I don't want to confuse myself too much by jumping ahead and reading about stuff that doesn't directly answer my questions. So I turn to you guys for at least pointing me in the right direction on what I should read up on or linking me to tutorials.

Also, if you guys have any books to recommend on the topic I'll be glad to take recommendations.

Thanks in advance

# Answer
A TFT touchscreen actually normally consists of two completely separate items:

* TFT Display
* Touchscreen and optional interface chip

While you can get both of those together on a board with both using I2C it is quite rare. It is far more common to find boards with either SPI or 8- (or 16-) bit parallel interfaces for the TFT screen, and SPI (or sometimes 4 channel analog - a direct connection to the touch screen itself) for the touch screen.

I2C is really only used for very small screens. The slow speed of the I2C protocol means that updating the display is very slow, which results in very poor performance for anything bigger than, say 128x128 pixels. It's usually used for things like small OLED displays rather than larger TFT displays.

Touchscreens with I2C are normally capacitative rather than the cheap resistive, so tend to be a little more expensive and harder to work with. The most common touch screen chip, the XPT2046, is SPI.

Fitting everything you want to do into an Uno is going to be tight, and not just because of the number of IO pins a display usually demands. Working with displays usually means lots of graphics (icons, symbols, fonts, etc), and that means a lot of flash memory. A Mega2560 would be a better choice for that if you want to remain with 8-bit.

However better graphical results would be obtained using a more powerful board. The Arduino Due, with its 32-bit ARM chip, would allow you to do much more graphical manipulation, such as drawing nice graphs etc.

My personal preference, though, is to use a PIC32 based board and the chipKIT core, coupled with my own powerful DisplayCore library. But then I'm biased.
> 1 votes

---
Tags: arduino-uno, i2c
---


title: Looking for SPI documentation

text:
# Question
Title: Looking for SPI documentation
I'm trying to use an Arduino as a slave and was searching for examples which I found many. But apart from the examples, I haven't found any documentation explaining many thing that show up in those examples.

For example, I'd like a document that would state what things like the following are:
-SPCR
-SPE
-SPDR
-ISR
-SPI\_STC\_vect

I'm asking this, because I don't and can't just copy an example and hope that it'll work, I really need to know what I'm doing.

Thank you,
João

# Answer
> 2 votes
You are confusing SPI, a de facto standard, with the Arduino/Atmel hardware support for SPI.

SPCR, SPE and SPDR are registers of the Atmel MCU, part of the hardware support.

ISR is Interrupt Service Routine and SPI\_STC\_vect is the vector that point to that code. That is where the data received from the cable is read finally.

# Answer
> 1 votes
Take a look at Nick Gammon's SPI explanations also. Very good, with timing explained as well.

http://www.gammon.com.au/spi

---
Tags: spi
---


# Question
Title: How to get data from a device using ethernet connection with arduino
I have a question, I know how to flush the result of a device(using PIN mode) / control a device with help of an Ethernet shield of arduino.

Now, the thing I want is I need to read a device which communicates only via Ethernet. so i have now connected the device with a router and I have the IP address of the device. I need to read the data from the device using arduino + Ethernet shield.

In fine: How to read data from a device connected to a arduino + Ethernet Sheild via lan cable and flash the result in web server or serial portal. Doesn't matter.

Please suggest a solution or help me with code.

regards, J

# Answer
You are out of luck: The device talks SMP (Static Managment Program), which is a close-source product of the same vendor.

The protocol used by SMP is not documented. The only way to access it is via the vendor own Windows software management.

Decoding the protocol is out of question.
> 0 votes

---
Tags: arduino-uno
---