# Question
Title: FreeRTOS is not solving my problem to run tasks parallelly
I'm pretty new to esp32 and I'm trying to combine two codes in one, they are simple codes from projects that I found online, the first one uses PIR sensor to send message to telegram each time motion is detected, second code uses RFID to open door lock. When I tried directly merging the two codes together the esp32 went crazy on serial monitor and nothing worked even the WIFI failed to connect.

Then I tried creating task for each one using freeRTOS and I did it like this:

***task1***: *for* Wifi connection **running on CORE 0** //wifi function is taken from sketch 1

***task2***: *for* RFID and door lock **running on CORE 1** //taken from sketch 2

***task3***: *for* motion detection and sending telegram message **running on CORE 0** //taken from sketch 1

Again esp32 went crazy when I opened serial monitor and it gave me this error:`" Guru Meditation Error: Core 1 panic'ed (IllegalInstruction). Exception was unhandled. "`

I have no clue why is this happening, does it really require RTOS to combine the two sketches and run them at the same time, or a simple delays and if statements would solve the problem? I need some help please.

**Sketch 1: Motion detection** from enter link description here

```
/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/telegram-esp32-motion-detection-arduino/

  Project created using Brian Lough's Universal Telegram Bot Library: https://github.com/witnessmenow/Universal-Arduino-Telegram-Bot
*/

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <UniversalTelegramBot.h>
#include <ArduinoJson.h>

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// Initialize Telegram BOT
#define BOTtoken "XXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"  // your Bot Token (Get from Botfather)

// Use @myidbot to find out the chat ID of an individual or a group
// Also note that you need to click "start" on a bot before it can
// message you
#define CHAT_ID "XXXXXXXXXX"

WiFiClientSecure client;
UniversalTelegramBot bot(BOTtoken, client);

const int motionSensor = 27; // PIR Motion Sensor
bool motionDetected = false;

// Indicates when motion is detected
void IRAM_ATTR detectsMovement() {
  //Serial.println("MOTION DETECTED!!!");
  motionDetected = true;
}

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

  // PIR Motion Sensor mode INPUT_PULLUP
  pinMode(motionSensor, INPUT_PULLUP);
  // Set motionSensor pin as interrupt, assign interrupt function and set RISING mode
  attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING);

  // Attempt to connect to Wifi network:
  Serial.print("Connecting Wifi: ");
  Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  client.setCACert(TELEGRAM_CERTIFICATE_ROOT); // Add root certificate for api.telegram.org

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

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  bot.sendMessage(CHAT_ID, "Bot started up", "");
}

void loop() {
  if(motionDetected){
    bot.sendMessage(CHAT_ID, "Motion detected!!", "");
    Serial.println("Motion Detected");
    motionDetected = false;
  }
}

```

**Sketch 2: RFID door lock** from enter link description here

```
/*
 * This ESP32 code is created by esp32io.com
 *
 * This ESP32 code is released in the public domain
 *
 * For more detail (instruction and wiring diagram), visit https://esp32io.com/tutorials/esp32-rfid-nfc-door-lock-system
 */

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

#define SS_PIN    5  // ESP32 pin GIOP5
#define RST_PIN   27 // ESP32 pin GIOP27
#define RELAY_PIN 22 // ESP32 pin GIOP22 connects to relay

MFRC522 rfid(SS_PIN, RST_PIN);

byte keyTagUID[4] = {0xFF, 0xFF, 0xFF, 0xFF};

void setup() {
  Serial.begin(9600);
  SPI.begin(); // init SPI bus
  rfid.PCD_Init(); // init MFRC522
  pinMode(RELAY_PIN, OUTPUT); // initialize pin as an output.
  digitalWrite(RELAY_PIN, HIGH); // lock the door

  Serial.println("Tap an RFID/NFC tag on the RFID-RC522 reader");
}

void loop() {
  if (rfid.PICC_IsNewCardPresent()) { // new tag is available
    if (rfid.PICC_ReadCardSerial()) { // NUID has been readed
      MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);

      if (rfid.uid.uidByte[0] == keyTagUID[0] &&
          rfid.uid.uidByte[1] == keyTagUID[1] &&
          rfid.uid.uidByte[2] == keyTagUID[2] &&
          rfid.uid.uidByte[3] == keyTagUID[3] ) {
        Serial.println("Access is granted");
        digitalWrite(RELAY_PIN, LOW);  // unlock the door for 2 seconds
        delay(2000);
        digitalWrite(RELAY_PIN, HIGH); // lock the door
      }
      else
      {
        Serial.print("Access denied, UID:");
        for (int i = 0; i < rfid.uid.size; i++) {
          Serial.print(rfid.uid.uidByte[i] < 0x10 ? " 0" : " ");
          Serial.print(rfid.uid.uidByte[i], HEX);
        }
        Serial.println();
      }

      rfid.PICC_HaltA(); // halt PICC
      rfid.PCD_StopCrypto1(); // stop encryption on PCD
    }
  }
}

```

# Answer
No, you don't need an RTOS to do something simple like:

```
if (motionDetected)
    open_the_door ();

```

---

You basically have two loops:

```
void loop ()
  {
  if (motionDetected)
      send_a_message_to_open_the_door ();
  }

```

And:

```
void loop ()
  {
  if (message_received_to_open_the_door)
     open_the_door();
  }

```

So, you combine them into a single loop:

```
void loop ()
  {
  if (motionDetected)
     open_the_door();
  }

```

I'll leave you to make the actual code changes.
> 1 votes

---
Tags: arduino-ide, esp32, spi
---


# Question
Title: It is required to turn on the LED if the distance to the object is less than or equal to 200 centimeters. Find the error in the code
```
int trigPin = 10;

const int echoPin = 8;

int led = 7;

const int distance = 200;

void setup()
{
    pinMode(trigPin, OUTPUT);
    pinMode(echoPin, INPUT);
    pinMode(led, OUTPUT);
}
void loop()
{
    int duration, cm;
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);

    duration = pulseIn(echoPin, HIGH);
    cm = duration/58;
    if (cm < distance)
    {
        digitalWrite(led, HIGH);
    }
    else
    {
        digitalWrite(led, LOW);
    }
    delay(100);
}

```

# Answer
1. You have `trigPin` as pin 10, however your wiring diagram shows it connected to pin 9, so that won't work.
2. `pulseIn` returns an `unsigned long` (microseconds) - see pulseIn. You are collecting the results in an `int` which has a maximum value of 32767. The value may be overflowing and thus not be correct.
> 0 votes

---
Tags: arduino-uno, hc-sr04
---


# Question
Title: How can when the button is clicked to display its name
I need to recognize a signal from an IR remote, not to use a library for working with IR remotes/receivers. How can when the button is clicked to display its name. I have PIC12F615 microcontroller with this code: code and 5 buttons connected to him and I need recognise which button pressed. I have some code but it gives different hex codes if I pressed the same button.

```
byte IRpin = 2;

volatile boolean remote = false;
volatile unsigned long irCode = 0;

void remoting ()
{
  if ( remote )
  {
    remote = false;
    unsigned long T;
    for ( byte n = 0; n < 32; n ++ )
    {
      do
      {
        T = pulseIn ( IRpin, HIGH, 2200 );
      }
      while ( T < 64 );
      bitWrite ( irCode, n, T > 1120 );
    }
  }
}

void setup ()
{
  Serial.begin ( 9600 );
  Serial.println ( "\n\tReady for keyboard reading!\n" );
  pinMode ( IRpin, INPUT_PULLUP );
  attachInterrupt ( digitalPinToInterrupt ( IRpin ), remoting, FALLING );
}

void loop ()
{
  if (irCode)
  {
    Serial.println (irCode, HEX);
    irCode = 0;
  }
  delay (40);
  remote = true;
}

```

Schema:

# Answer
The function pulseIn() has this comment in the source code: "This function performs better with short pulses in noInterrupt() context" see: https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/wiring\_pulse.c. It is not clear if your code violates the "short pulse" rule, however, blocking an Interrupt Service Routine (in your case, the external interrupt call back routine remoting() ) for the entire length of an IR data stream is certain to cause other problems, for example, with the millis() timer.

This is in the style of your code but avoids using interrupts. It has been tested against an NEC remote control and gives repeatable results. Your code fails the same test.

```
byte IRpin = 2;

unsigned long irCode = 0;

void setup ()
{
  Serial.begin ( 9600 );
  Serial.println ( "\n\tReady for keyboard reading!\n" );
  pinMode ( IRpin, INPUT_PULLUP );
}

void loop () {
  while ( digitalRead ( IRpin ) );  // wait until start of first pulse
  unsigned long T;
  uint8_t validPulses = 0 ;
  for ( byte n = 0; n < 36 ; n ++ ) // enough to drop long header
  {
    T = pulseIn ( IRpin, HIGH , 12000 );  // 12ms timeout
    if ( T < 4000 && T > 400 && validPulses < 32 ) {
      // valid pulse
      bitWrite ( irCode, validPulses++, T > 1120 );
    }
  }
  if (irCode > 0 ) Serial.println (irCode, HEX);
  else Serial.println ("no code");
  irCode = 0 ;
}

```
> 1 votes

---
Tags: arduino-uno, interrupt
---


# Question
Title: override pinMode, digitalWrite and digitalRead
I am using the ESP32 Arduino Framework and I have some GPIO expanders attached via I²C. They work fine and I now want to map some unused pin numbers to them so I can used my custom pin numbers in `pinMode`, `digitalRead` and `digitalWrite`.

Luckily, the Arduino core links these functions weakly.

```
extern void pinMode(uint8_t pin, uint8_t mode) __attribute__ ((weak, alias("__pinMode")));

```

I defined my own functions like so:

```
void pinMode(uint8_t pin, uint8_t mode) {
    if(pin<0x80)
        // call conventional handler
    else
        // communicate with GPIO expander via I²C
}

```

Unfortunately, calling any of the functions will not result in the linker picking my implementation but the linker picks the default implementation.

Any ideas how to override the weakly linked `pinMode`, `digitalWrite` and `digitalRead`?

# Answer
I found the issue: I ran `platformio run --target clean` instead of `platformio run --target cleanall`. It seems that only the latter command cleans all build artifacts. The next time I compiled and uploaded, it worked as expected.

Another issue occurs only with Adafruit libraries: Some libraries do not use `uint8_t` for ports but `int8_t` and they do checks like

```
if(pin_number >=0)  {
    // code that only works with pin numbers between 0x01 and 0x80
}

```

Take the Adafruit GFX library as an example. As a workaround, I will map my GPIO expander ports to 0x40, 0x41, ...
> 3 votes

---
Tags: linker, io-expander
---


title: ArduinoJson library parsing error

text:
# Question
Title: ArduinoJson library parsing error
I am trying to retrieve JSON mqtt message I received in ESP32.

```
void mqttMsgCallback(char* topic, byte* payload, unsigned int length) {
    payload[length] = '\0';
    String _message = String((char*)payload);
    String _topic = String(topic);
    if (_topic.equals("Sys.GetInfo/"+getMacAddr()) == 1)
    {
      Serial.println("Message arrived for sys.GetInfo");
      StaticJsonDocument <256> msg1;
      Serial.println(_message);
      deserializeJson(msg1,_message);
      String callbackTopic = msg1["callbackTopic"];
      Serial.println(callbackTopic);
    }
}

```

The issue is when I publish `mosquitto_pub -t "Sys.GetInfo/2462ABFC2CD0" -m "{"callbackTopic" : "1234"}"` it works well like callbackTopic as 1234.

but when I publish `mosquitto_pub -t "Sys.GetInfo/2462ABFC2CD0" -m "{"callbackTopic" : "xyz"}"`  it prints callbackTopic value as null. Please point me if I an missing something.

Arduino version 1.8.15 ArduinoJson : 6.18.2 Borad : ESP32

Thanks

# Answer
> 2 votes
Your shell is stripping the " from inside the string. If you run the command:

```
$ echo "{"callbackTopic" : "xyz"}"

```

you get:

```
{callbackTopic : xyz}

```

so you see all the quotes are stripped. `xyz` isn't something that ArduinoJSON can parse. But `1234` is, so with the quotes stripped it's still considered valid.

You need to ensure the quotes aren't removed. There's two ways of doing this: escaping them, or encapsulating the string in single quotes which gives a more "literal" interpretation of the contents than double quotes:

Escaping:

```
"{\"callbackTopic\" : \"xyz\"}"

```

Single quotes:

```
'{"callbackTopic" : "xyz"}'

```

Either of those when used as a parameter to a command work - like:

```
$ echo '{"callbackTopic" : "xyz"}'
{"callbackTopic" : "xyz"}

```

# Answer
> -1 votes
To parse an ArduinoJSON one simply needs to

```
  String JSONpayload = "some JSON here";
  StaticJsonDocument <512> geoLocationInfoJson;
  DeserializationError error = deserializeJson(geoLocationInfoJson, JSONpayload);
  if (error) {
    this->mserial->printStrln("Error deserializing JSON");
  }

```

To use the values within the `StaticJsonDocument` one first needs to

```
if ( geoLocationInfoJson.isNull() == true ){
  String dataStr="NULL geoLocation data.\n";
  Serial.print( dataStr);
  return true;
}

```

next, is required to verify if a key exists. If TRUE, then is mandatory first to get the desired value into a corresponding data type, like below, and only afterward work on it, for instance, send it as a BLE message string:

```
if(this->interface->geoLocationInfoJson.containsKey("lat")){
  float lat = this->interface->geoLocationInfoJson["lat"];
  dataStr += "Latitude: "+ String(lat,4) + "\n";
}
if(this->interface->geoLocationInfoJson.containsKey("lon")){
  float lon = this->interface->geoLocationInfoJson["lon"];
  dataStr += "Longitude: "+ String(lon,4) + "\n";
}

if(this->interface->geoLocationInfoJson.containsKey("regionName"))
  dataStr += String(this->interface->geoLocationInfoJson["regionName"].as<char*>()) + ", ";

```

The full code above is available on this GitHub repository:

https://github.com/aeonSolutions/aeonlabs-ESP32-C-Base-Firmware-Libraries

---
Tags: arduino-ide, esp32, json, mqtt
---


# Question
Title: Printing elements of char array from PROGMEM
Given:

```
const char* PROGMEM names[] = {"Foo","Bar"};
Serial.print(names[0]);

```

I get garbage output. Is there some function that will print the string from PROGMEM? E.G.:

```
Serial.print(<function name>(names[0]);

```

# Answer
> 2 votes
Among many others, check out pgmspace.h utilities at AVR-libc

# Answer
> 0 votes
```
const char PROGMEM b0 = pgm_read_dword(&(names[0]));
Serial.print(b0);

```

---
Tags: serial, programming, progmem
---


# Question
Title: Why NEC IR remote control decoder does not work
I need to recognize a signal from an IR remote, not to use a library for working with IR remotes/receivers. How can when the button is clicked to display its name. I have PIC12F615 microcontroller with this code: code and 5 buttons connected to him and I need recognise which button pressed. Why NEC IR remote control decoder does not work, it doesn't set nec\_ok to true.If output nec\_state to the terminal, I get 0 1 0 1 0 1 and so on.

```
    boolean nec_ok = 0;
byte i, nec_state = 0, command, inv_command;
unsigned int address;
unsigned long nec_code;

void setup() {
Serial.begin(9600);
// Timer1 module configuration
TCCR1A = 0;
TCCR1B = 0; // Disable Timer1 module
TCNT1 = 0; // Set Timer1 preload value to 0 (reset)
TIMSK1 = 1; // enable Timer1 overflow interrupt
attachInterrupt(digitalPinToInterrupt(2), remote_read, CHANGE); // Enable external interrupt (INT0)
}

void remote_read() {
unsigned int timer_value;
if(nec_state != 0){
timer_value = TCNT1; // Store Timer1 value
TCNT1 = 0; // Reset Timer1
}
switch(nec_state){
case 0 : // Start receiving IR data (we're at the beginning of 9ms pulse)
TCNT1 = 0; // Reset Timer1
TCCR1B = 2; // Enable Timer1 module with 1/8 prescaler ( 2 ticks every 1 us)
nec_state = 1; // Next state: end of 9ms pulse (start of 4.5ms space)
i = 0;
return;
case 1 : // End of 9ms pulse
if((timer_value > 19000) || (timer_value < 17000)){ // Invalid interval ==> stop decoding and reset
nec_state = 0; // Reset decoding process
TCCR1B = 0; // Disable Timer1 module
}
else
nec_state = 2; // Next state: end of 4.5ms space (start of 562µs pulse)
return;
case 2 : // End of 4.5ms space
if((timer_value > 10000) || (timer_value < 8000)){
nec_state = 0; // Reset decoding process
TCCR1B = 0; // Disable Timer1 module
}
else
nec_state = 3; // Next state: end of 562µs pulse (start of 562µs or 1687µs space)
return;
case 3 : // End of 562µs pulse
if((timer_value > 1400) || (timer_value < 800)){ // Invalid interval ==> stop decoding and reset
TCCR1B = 0; // Disable Timer1 module
nec_state = 0; // Reset decoding process
}
else
nec_state = 4; // Next state: end of 562µs or 1687µs space
return;
case 4 : // End of 562µs or 1687µs space
if((timer_value > 3600) || (timer_value < 800)){ // Time interval invalid ==> stop decoding
TCCR1B = 0; // Disable Timer1 module
nec_state = 0; // Reset decoding process
return;
}
if( timer_value > 2000) // If space width > 1ms (short space)
bitSet(nec_code, (31 - i)); // Write 1 to bit (31 - i)
else // If space width < 1ms (long space)
bitClear(nec_code, (31 - i)); // Write 0 to bit (31 - i)
i++;
if(i > 31){ // If all bits are received
nec_ok = 1; // Decoding process OK
detachInterrupt(0); // Disable external interrupt (INT0)
return;
}
nec_state = 3; // Next state: end of 562µs pulse (start of 562µs or 1687µs space)
}
}

ISR(TIMER1_OVF_vect) { // Timer1 interrupt service routine (ISR)
nec_state = 0; // Reset decoding process
TCCR1B = 0; // Disable Timer1 module
}

void loop() {
Serial.println(nec_ok);
if(nec_ok){ // If the mcu receives NEC message with successful
nec_ok = 0; // Reset decoding process
nec_state = 0;
TCCR1B = 0; // Disable Timer1 module
address = nec_code >> 16;
command = nec_code >> 8;
inv_command = nec_code;

attachInterrupt(digitalPinToInterrupt(2), remote_read, CHANGE); // Enable external interrupt (INT0)
}
}

```

Schema:

# Answer
External interrupt version of NEC protocol decoder using micros() for timing instead of Timer 1. Drops NEC repeat codes, Otherwise, in the style of the code in the question.

```
volatile boolean nec_ok = 0;
byte command, inv_command;
volatile byte nec_state = 0 ;
unsigned int address;
volatile unsigned long nec_code;
volatile uint32_t errFlag = 0 ;
volatile uint32_t decodeStartAtMs = 0 ;

void setup() {
  Serial.begin(9600);
  pinMode( 2, INPUT_PULLUP ) ;
  attachInterrupt(digitalPinToInterrupt(2), remote_read, CHANGE); // Enable external interrupt (INT0)
}

void remote_read() {

  static byte i = 0 ;
  static bool wasSpace;
  static unsigned long enteredAtUs = 0 ;
  static unsigned long pulseLengthLastUs ;

  wasSpace = ! digitalRead( 2 ) ;
  pulseLengthLastUs = micros() - enteredAtUs; // Calculate pulse length
  enteredAtUs = micros(); // Store current time for next entry

  switch (nec_state) {

    case 0 : // Wait here until 9ms pulse found )
      if ( pulseLengthLastUs > 8000 && pulseLengthLastUs < 10000 ) {  // got a 9ms pulse
        decodeStartAtMs = millis() ;  // for timeout
        nec_state = 1 ;
        nec_code = 0 ;
        i = 0 ;
      }
      break;

    case 1 : // handle 4.5ms space
      /*
      if ((pulseLengthLastUs > 2000) && (pulseLengthLastUs < 2500)) {
          // silently drop repeat codes !!!
          nec_state = 0; // Reset decoding process
      }
      else
      */
      if ((pulseLengthLastUs > 5500) || (pulseLengthLastUs < 3500)) {
        errFlag = 10000000 + pulseLengthLastUs ;
        nec_state = 0; // Reset decoding process
      }
      else
        nec_state = 2; // Next state: end of 562µs pulse (start of 562µs or 1687µs space)
      break;

    case 2 : // handle 562µs or 1687µs space
      if ((pulseLengthLastUs > 1900) || (pulseLengthLastUs < 400)) { // Time interval invalid ==> stop decoding
        errFlag = 20000000 + pulseLengthLastUs ;
        nec_state = 0; // Reset decoding process
        break;
      }

      if ( wasSpace ) {
        // we are interested only in the space length
        if ( pulseLengthLastUs > 1000) // If space width > 1ms (short space)
          bitSet(nec_code, (31 - i)); // Write 1 to bit (31 - i)
        else // If space width < 1ms (long space)
          bitClear(nec_code, (31 - i)); // Write 0 to bit (31 - i)
        i++;
        if (i > 31) { // If all bits are received
          i = 0 ;
          nec_ok = 1; // Decoding process OK
          detachInterrupt(0); // Disable external interrupt (INT0)
        }
      }
      break;
  }
}

void loop() {

  if ( errFlag > 0 ) {
    Serial.print( "Error: " ) ;
    Serial.println( errFlag ) ;
    errFlag = 0 ;
  }

  if ( nec_state > 0 && millis() - decodeStartAtMs > 90 ) {
    Serial.println( "Timeout" ) ;
    nec_state = 0 ;
  }

  if (nec_ok) {
    Serial.print( "Code received = " ) ;
    Serial.println( nec_code, HEX ) ;

    address = (nec_code >> 16) & 0xFF; // Extract address from received code
    inv_command = (nec_code >> 8) & 0xFF; // Extract inverted command from received code
    command = nec_code & 0xFF; // Extract command from received code
    if (command == ((~inv_command) & 0xFF)) { // Verify command validity
      Serial.print("Received valid NEC code: ");
      Serial.print(address, HEX); Serial.print(", ");
      Serial.print(command, HEX); Serial.print(", ");
      Serial.println(inv_command, HEX);
    }
    else {
      Serial.println("Received invalid NEC code!");
    }
    nec_ok = 0; // Reset decoding process
    nec_state = 0; // Reset decoding state
    attachInterrupt(digitalPinToInterrupt(2), remote_read, CHANGE); // Re-enable external interrupt (INT0)
  }

}

```

This utility can be used to verify the output of an IR receiver showing the timings of the pulses and spaces to 4us resolution.

```
// protocol analyser utility
// intended to dump timings to the serial console for example from demodulated NEC IR codes
// Connect the IR receiver output to pin 2

const uint8_t DATA_SIZE = 100 ;

struct intervalRead_t {
  uint32_t durationUs ;
  bool space ;
} ;

intervalRead_t intervalRead[ DATA_SIZE ] ;

volatile unsigned long enteredAtUs = 0 ;
volatile uint8_t index = 0 ;
volatile bool firstPulse = true ;

void saveTimes() {

  bool wasSpace;
  uint32_t pulseLengthLastUs ;

  wasSpace = ! digitalRead( 2 ) ;
  pulseLengthLastUs = micros() - enteredAtUs; // Calculate pulse length
  enteredAtUs = micros(); // Store current time for next entry

  if ( firstPulse ) {
    firstPulse = false ;
    index = 0 ;
  }
  else {
    if ( index < DATA_SIZE  )  {
      intervalRead[ index ].durationUs = pulseLengthLastUs ;
      intervalRead[ index ].space = wasSpace ;
      index++ ;
    }
  }
}

void setup() {
  Serial.begin(9600);
  pinMode( 2, INPUT_PULLUP ) ;
  attachInterrupt(digitalPinToInterrupt(2), saveTimes, CHANGE); // Enable external interrupt (INT0)
}

void loop() {
  if ( !firstPulse && micros() - enteredAtUs > 500000UL  ) {
    for ( uint8_t i = 0; i < index ; i++ ) {
      Serial.print( i ) ;
      Serial.print( "\tinterval= " ) ;
      Serial.print( intervalRead[ i ].durationUs ) ;
      Serial.print( "us  \t") ;
      Serial.print( intervalRead[ i ].space ? "space" : "pulse" ) ;
      Serial.println( ) ;
    }
    Serial.println( ) ;
    firstPulse = true ;
  }
}

```
> 1 votes

---
Tags: arduino-uno, interrupt
---


# Question
Title: Creating formatted String (including floats) in Arduino-compatible C++
I'm using a Mega2560 and a generic SSD1306 OLED display with the Adafruit\_SSD1306 (and by extension, Adafruit\_gfx) library.

I need to print a bunch of float values (ranging between 30.0 and 99.9) to the display with exactly one decimal place of precision. The catch is, the Adafruit library doesn't have a printf() method, only one that takes a single ready-to-print string.

Here's an (obviously non-Arduino) Java-like example of what I'm trying to accomplish:

```
String foo = String.format("%.1f, %.1f\%", temp1, hum1);
// "display" is my instance of Adafruit_SSD1306
display.print(foo);

```

So... how can I do something similar in Arduino-compatible C(++)?

Note: for this specific program, I have (relatively speaking) RAM to burn, so I really don't care if whatever library I use to generate formatted Strings is particularly efficient (as long as it isn't leaking). If it wants to use 4k of RAM and 80k of flash to format a 20-character String, so be it.

# Answer
Normally for formatting strings I'd suggest the venerable `snprintf` and similar functions. However, on an 8-bit Arduino when you're using floats that's not an option: the function that does all the formatting for this family if functions has had floating point support surgically removed from it. This is to make the function a fraction of the size so it's not as bloaty in small microcontrollers.

I believe there is a float-capable version somewhere on the internet that could be somehow installed, though I have never looked into doing that.

Instead you need to do the formatting of floats manually. Everything else can be done with `snprintf`, but the floats need to be done separately.

Fortunately there's a function specifically for formatting a float into a character array (C-string), called `dtostrf` and is used thus:

```
float myVal = 23.49173783;
char *buffer[10]; // Enough room for the digits you want and more to be safe
dtostrf(myVal, 9, 1, buffer);

```

The first number in the parameter list is how many characters you want to have in your output, including the `.` and any leading `-`. Any extra characters are padded with space. The second number is how many decimal places. If the first number is negative the value is left-aligned. If it's positive it's right-aligned. So the code above would give you:

```
〿〿〿〿〿23.5␀

```

(Note: I am using  to denote a space character.) If you used `-9` you'd get:

```
23.5〿〿〿〿〿␀

```

You can, of course, feed that created string into another string using `snprintf` and the `%s` placeholder.

```
char buf2[32];
snprintf(buf2, 32, "The temperature is: %s\r\n", buffer);

buf2 ⇒ "The temperature is: 23.5〿〿〿〿〿"

```

If you want to trim the string down to just contain the number portion and lose the spaces it's best to left-align it with a negative width, then change the first space to a :

```
char *space = strchr(buffer, ' ');
if (space != NULL) {
    *space = '\0';
}

```
> 4 votes

# Answer
The `Adafruit_GFX` class has two methods named `print()` and `println()`. These behave exactly like `Serial.print()` and `Serial.println()`. Specifically, when printing a float, you can provide a second argument telling it the number of decimal places you want after the decimal point:

```
display.print(temp1, 1);  // 1 digit after the decimal point
display.print(", ");
display.print(hum1, 1);  // ditto
display.print("%");

```

**Background**: the reason these methods behave like the ones of `Serial` is that both `Adafruit_GFX` and `HardwareSerial` inherit them from the `Print` virtual class.
> 3 votes

# Answer
One can use the `String()` type initialization to convert any number, including float to String. For example to convert `3.14159` simply type ⤵

```
float num = 3.14159
String str1 = String(num, 1) // 3.1
String str2 = String(num, 2) // 3.14
String str3 = String(num, 3) // 3.141

```

To the right of the comma is the number of decimal places one wants the string result to have. It has a lot of functionality but that's one of the overloads. You can see them all here!

To see this code working on a .ino sketch check out this GitHub repo https://github.com/aeonSolutions/aeonlabs-ESP32-C-Base-Firmware-Libraries
> 0 votes

---
Tags: c++, string
---


title: How do you use SPI on an Arduino?

text:
# Question
Title: How do you use SPI on an Arduino?
With reference to the Arduino Uno, Mega2560, Leonardo and similar boards:

* How does SPI work?
* How fast is SPI?
* How do I connect between a master and a slave?
* How do I make an SPI slave?

---

*Please note: This is intended as a reference question.*

# Answer
## Introduction to SPI

The Serial Peripheral Interface Bus (SPI) interface is used for communication between multiple devices over short distances, and at high speed.

Typically there is a single "master" device, which initiates communications and supplies the clock which controls the data transfer rate. There can be one or more slaves. For more than one slave, each one has its own "slave select" signal, described later.

---

## SPI signals

In a full-blown SPI system you will have four signal lines:

* Master Out, Slave In (**MOSI**) - which is the data going from the master to the slave
* Master In, Slave Out (**MISO**) - which is the data going from the slave to the master
* Serial Clock (**SCK**) - when this toggles both the master and the slave sample the next bit
* Slave Select (**SS**) - this tells a particular slave to go "active"

When multiple slaves are connected to the MISO signal they are expected to tri-state (keep at high impedance) that MISO line until they are selected by Slave Select being asserted. Normally Slave Select (SS) goes low to assert it. That is, it is active low. Once a particular slave is selected it should configure the MISO line as an output so it can send data to the master.

This image shows the way that data is exchanged as one byte is sent:

Note that three signals are outputs from the master (MOSI, SCK, SS) and one is an input (MISO).

---

## Timing

The sequence of events is:

* `SS` goes low to assert it and activate the slave
* The `SCK` line toggles to indicate when the data lines should be sampled
* The data is sampled by both master and slave on the **leading** edge of `SCK` (using the default clock phase)
* Both master and slave prepare for the next bit on the **trailing** edge of `SCK` (using the default clock phase), by changing `MISO` / `MOSI` if necessary
* Once the transmission is over (possibly after multiple bytes have been sent) then `SS` goes high to de-assert it

Note that:

* The most significant bit is sent first (by default)
* Data is sent and received at the same instant (full duplex)

Because data is sent and received on the same clock pulse it is not possible for the slave to respond to the master immediately. SPI protocols usually expect the master to request data on one transmission, and get a response on a subsequent one.

Using the SPI library on the Arduino, doing a single transfer looks like this in code:

```
 byte outgoing = 0xAB;
 byte incoming = SPI.transfer (outgoing);

```

---

## Sample code

Example of sending only (ignoring any incoming data):

```
#include <SPI.h>

void setup (void)
  {
  digitalWrite(SS, HIGH);  // ensure SS stays high
  SPI.begin ();
  } // end of setup

void loop (void)
  {
  byte c;

  // enable Slave Select
  digitalWrite(SS, LOW);    // SS is pin 10

  // send test string
  for (const char * p = "Fab" ; c = *p; p++)
    SPI.transfer (c);

  // disable Slave Select
  digitalWrite(SS, HIGH);

  delay (100);
  } // end of loop

```

---

## Wiring for output-only SPI

The above code (which sends only) might be used to drive an output serial shift register. These are output-only devices, so we don't need to worry about any incoming data. In their case the SS pin might be called the "store" or "latch" pin.

Examples of this are the 74HC595 serial shift register, and various LED strips, just to mention a couple. For example, this 64 pixel LED display driven by a MAX7219 chip:

In this case you can see that the board maker has used slightly different signal names:

* DIN (Data In) is MOSI (Master Out, Slave In)
* CS (Chip Select) is SS (Slave Select)
* CLK (Clock) is SCK (Serial Clock)

Most boards will follow a similar pattern. Sometimes DIN is just DI (Data In).

Here is another example, this time a 7-segment LED display board (also based on the MAX7219 chip):

This uses exactly the same signal names as the other board. In both of these cases you can see that the board only needs 5 wires to it, the three for SPI, plus power and ground.

---

## Clock phase and polarity

There are four way you can sample the SPI clock.

The SPI protocol allows for variations on the polarity of the clock pulses. CPOL is clock polarity, and CPHA is clock phase.

* Mode 0 (the default) - clock is normally low (CPOL = 0), and the data is sampled on the transition from low to high (leading edge) (CPHA = 0)
* Mode 1 - clock is normally low (CPOL = 0), and the data is sampled on the transition from high to low (trailing edge) (CPHA = 1)
* Mode 2 - clock is normally high (CPOL = 1), and the data is sampled on the transition from high to low (leading edge) (CPHA = 0)
* Mode 3 - clock is normally high (CPOL = 1), and the data is sampled on the transition from low to high (trailing edge) (CPHA = 1)

These are illustrated in this graphic:

You should refer to the datasheet for your device to get the phase and polarity correct. There will usually be a diagram which shows how to sample the clock. For example, from the datasheet for the 74HC595 chip:

As you can see the clock is normally low (CPOL = 0) and it is sampled on the leading edge (CPHA = 0) so this therefore is SPI mode 0.

You can change the clock polarity and phase in code like this (choose one only, of course):

```
SPI.setDataMode (SPI_MODE0);
SPI.setDataMode (SPI_MODE1);
SPI.setDataMode (SPI_MODE2);
SPI.setDataMode (SPI_MODE3);

```

This method is deprecated in versions 1.6.0 onwards of the Arduino IDE. For recent versions you change the clock mode in the `SPI.beginTransaction` call, like this:

```
SPI.beginTransaction (SPISettings (2000000, MSBFIRST, SPI_MODE0));  // 2 MHz clock, MSB first, mode 0

```

---

## Data order

The default is most-significant bit first, however you can tell the hardware to process the least significant bit first like this:

```
SPI.setBitOrder (LSBFIRST);   // least significant bit first
SPI.setBitOrder (MSBFIRST);   // most significant bit first

```

Again, this is deprecated in versions 1.6.0 onwards of the Arduino IDE. For recent versions you change the bit order in the `SPI.beginTransaction` call, like this:

```
SPI.beginTransaction (SPISettings (1000000, LSBFIRST, SPI_MODE2));  // 1 MHz clock, LSB first, mode 2

```

---

## Speed

The default setting for SPI is to use the system clock speed divided by four, that is, one SPI clock pulse every 250 ns, assuming a 16 MHz CPU clock. You can change the clock divider by using `setClockDivider` like this:

```
SPI.setClockDivider (divider);

```

Where "divider" is one of:

* SPI\_CLOCK\_DIV2
* SPI\_CLOCK\_DIV4
* SPI\_CLOCK\_DIV8
* SPI\_CLOCK\_DIV16
* SPI\_CLOCK\_DIV32
* SPI\_CLOCK\_DIV64
* SPI\_CLOCK\_DIV128

The fastest rate is "divide by 2" or one SPI clock pulse every 125 ns, assuming a 16 MHz CPU clock. This would therefore take 8 * 125 ns or 1 µs to transmit one byte.

This method is deprecated in versions 1.6.0 onwards of the Arduino IDE. For recent versions you change the transfer speed in the `SPI.beginTransaction` call, like this:

```
SPI.beginTransaction (SPISettings (4000000, MSBFIRST, SPI_MODE0));  // 4 MHz clock, MSB first, mode 0

```

However empirical testing shows that it is necessary to have two clock pulses between bytes, so the maximum rate at which bytes can be clocked out is 1.125 µs each (with a clock divider of 2).

To summarize, each byte can be sent at a maximum rate of one per 1.125 µs (with a 16 MHz clock) giving a theoretical maximum transfer rate of 1/1.125 µs, or 888,888 bytes per second (excluding overhead like setting SS low and so on).

---

## Connecting to Arduino

### Arduino Uno

Connecting via digital pins 10 to 13:

Connecting via the ICSP header:

### Arduino Atmega2560

Connecting via digital pins 50 to 52:

You can also use the ICSP header, similar to the Uno above.

### Arduino Leonardo

The Leonardo and Micro do not expose the SPI pins on the digital pins, unlike the Uno and Mega. Your only option is to use the ICSP header pins, as illustrated above for the Uno. However the Leonardo and ProMicro don't expose the SS pin and thus cannot be used as an SPI slave.

---

## Multiple slaves

A master can communicate with multiple slaves (however only one at a time). It does this by asserting SS for one slave and de-asserting it for all the others. The slave which has SS asserted (usually this means LOW) configures its MISO pin as an output so that slave, and that slave alone, can respond to the master. The other slaves ignore any incoming clock pulses if SS is not asserted. Thus you need one additional signal for each slave, like this:

In this graphic you can see that MISO, MOSI, SCK are shared between both slaves, however each slave has its own SS (slave select) signal.

---

## Protocols

The SPI spec does not specify protocols as such, so it is up to individual master/slave pairings to agree on what the data means. Whilst you can send and receive bytes simultaneously, the received byte cannot be a direct response to the sent byte (as they are being assembled simultaneously).

So it would be more logical for one end to send a request (eg. 4 might mean "list the disk directory") and then do transfers (perhaps just sending zeros outwards) until it receives a complete response. The response might terminate with a newline, or 0x00 character.

Read the datasheet for your slave device to see what protocol sequences it expects.

---

## How to make an SPI slave

The earlier example shows the Arduino as the master, sending data to a slave device. This example shows how the Arduino can be a slave.

### Hardware setup

Connect two Arduino Unos together with the following pins connected to each other:

* 10 (SS)
* 11 (MOSI)
* 12 (MISO)
* 13 (SCK)
* +5v (if required)
* GND (for signal return)

On the Arduino Mega, the pins are 50 (MISO), 51 (MOSI), 52 (SCK), and 53 (SS).

In any case, MOSI at one end is connected to MOSI at the other, you **don't** swap them around (that is you **do not have** MOSI \<-\> MISO). The software configures one end of MOSI (master end) as an output, and the other end (slave end) as an input.

On some boards (like Leonardo, ProMicro — see above) the SS pin isn't exposed (rather it is connected to RX\_LED). It is not possible to remap SS to another pin to be able to use those boards as an SPI slave as the AVR uses fixed SPI pins according to the datasheets (PB0-PB3 on 32U4).

### Master example

```
#include <SPI.h>

void setup (void)
{

  digitalWrite(SS, HIGH);  // ensure SS stays high for now

  // Put SCK, MOSI, SS pins into output mode
  // also put SCK, MOSI into LOW state, and SS into HIGH state.
  // Then put SPI hardware into Master mode and turn SPI on
  SPI.begin ();

  // Slow down the master a bit
  SPI.setClockDivider(SPI_CLOCK_DIV8);

}  // end of setup

void loop (void)
{

  char c;

  // enable Slave Select
  digitalWrite(SS, LOW);    // SS is pin 10

  // send test string
  for (const char * p = "Hello, world!\n" ; c = *p; p++)
    SPI.transfer (c);

  // disable Slave Select
  digitalWrite(SS, HIGH);

  delay (1000);  // 1 seconds delay
}  // end of loop

```

### Slave example

```
#include <SPI.h>

char buf [100];
volatile byte pos;
volatile bool process_it;

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

  // turn on SPI in slave mode
  SPCR |= bit (SPE);

  // have to send on master in, *slave out*
  pinMode (MISO, OUTPUT);

  // get ready for an interrupt
  pos = 0;   // buffer empty
  process_it = false;

  // now turn on interrupts
  SPI.attachInterrupt();

}  // end of setup

// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR;  // grab byte from SPI Data Register

  // add to buffer if room
  if (pos < sizeof buf)
    {
    buf [pos++] = c;

    // example: newline means time to process buffer
    if (c == '\n')
      process_it = true;

    }  // end of room available
}  // end of interrupt routine SPI_STC_vect

// main loop - wait for flag set in interrupt routine
void loop (void)
{
  if (process_it)
    {
    buf [pos] = 0;
    Serial.println (buf);
    pos = 0;
    process_it = false;
    }  // end of flag set

}  // end of loop

```

The slave is entirely interrupt-driven, thus it can doing other stuff. The incoming SPI data is collected in a buffer, and a flag set when a "significant byte" (in this case a newline) arrives. This tells the slave to get on and start processing the data.

### Example of connecting master to slave using SPI

---

## How to get a response from a slave

Following on from the code above which sends data from an SPI master to a slave, the example below shows sending data to a slave, having it do something with it, and return a response.

The master is similar to the example above. However an important point is that we need to add a slight delay (something like 20 microseconds). Otherwise the slave doesn't have a chance to react to the incoming data and do something with it.

The example shows sending a "command". In this case "a" (add something) or "s" (subtract something). This is to show that the slave is actually doing something with the data.

After asserting slave-select (SS) to initiate the transaction, the master sends the command, followed by any number of bytes, and then raises SS to terminate the transaction.

A very important point is that the slave cannot respond to an incoming byte at the same moment. The response has to be in the next byte. This is because the bits which are being sent, and the bits which are being received, are being sent simultaneously. Thus to add something to four numbers we need five transfers, like this:

```
transferAndWait ('a');  // add command
transferAndWait (10);
a = transferAndWait (17);
b = transferAndWait (33);
c = transferAndWait (42);
d = transferAndWait (0);

```

First we request action on number 10. But we don't get a response until the next transfer (the one for 17). However "a" will be set to the reply to 10. Finally we end up sending a "dummy" number 0, to get the reply for 42.

### Master (example)

```
  #include <SPI.h>

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

    digitalWrite(SS, HIGH);  // ensure SS stays high for now
    SPI.begin ();

    // Slow down the master a bit
    SPI.setClockDivider(SPI_CLOCK_DIV8);
    }  // end of setup

  byte transferAndWait (const byte what)
    {
    byte a = SPI.transfer (what);
    delayMicroseconds (20);
    return a;
    } // end of transferAndWait

  void loop (void)
    {

    byte a, b, c, d;

    // enable Slave Select
    digitalWrite(SS, LOW);

    transferAndWait ('a');  // add command
    transferAndWait (10);
    a = transferAndWait (17);
    b = transferAndWait (33);
    c = transferAndWait (42);
    d = transferAndWait (0);

    // disable Slave Select
    digitalWrite(SS, HIGH);

    Serial.println ("Adding results:");
    Serial.println (a, DEC);
    Serial.println (b, DEC);
    Serial.println (c, DEC);
    Serial.println (d, DEC);

    // enable Slave Select
    digitalWrite(SS, LOW);

    transferAndWait ('s');  // subtract command
    transferAndWait (10);
    a = transferAndWait (17);
    b = transferAndWait (33);
    c = transferAndWait (42);
    d = transferAndWait (0);

    // disable Slave Select
    digitalWrite(SS, HIGH);

    Serial.println ("Subtracting results:");
    Serial.println (a, DEC);
    Serial.println (b, DEC);
    Serial.println (c, DEC);
    Serial.println (d, DEC);

    delay (1000);  // 1 second delay
    }  // end of loop

```

The code for the slave basically does almost everything in the interrupt routine (called when incoming SPI data arrives). It takes the incoming byte, and adds or subtracts as per the remembered "command byte". Note that the response will be "collected" next time through the loop. This is why the master has to send one final "dummy" transfer to get the final reply.

In my example I am using the main loop to simply detect when SS goes high, and clear the saved command. That way, when SS is pulled low again for the next transaction, the first byte is considered the command byte.

More reliably, this would be done with an interrupt. That is, you would physically connect SS to one of the interrupt inputs (eg, on the Uno, connect pin 10 (SS) to pin 2 (an interrupt input), or use a pin-change interrupt on pin 10.

Then the interrupt could be used to notice when SS is being pulled low or high.

### Slave (example)

```
// what to do with incoming data
volatile byte command = 0;

void setup (void)
  {

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);

  // turn on SPI in slave mode
  SPCR |= _BV(SPE);

  // turn on interrupts
  SPCR |= _BV(SPIE);

  }  // end of setup

// SPI interrupt routine
ISR (SPI_STC_vect)
  {
  byte c = SPDR;

  switch (command)
    {
    // no command? then this is the command
    case 0:
      command = c;
      SPDR = 0;
      break;

    // add to incoming byte, return result
    case 'a':
      SPDR = c + 15;  // add 15
      break;

    // subtract from incoming byte, return result
    case 's':
      SPDR = c - 8;  // subtract 8
      break;

    } // end of switch

  }  // end of interrupt service routine (ISR) SPI_STC_vect

void loop (void)
  {

  // if SPI not active, clear current command
  if (digitalRead (SS) == HIGH)
    command = 0;
  }  // end of loop

```

### Example output

```
Adding results:
25
32
48
57
Subtracting results:
2
9
25
34
Adding results:
25
32
48
57
Subtracting results:
2
9
25
34

```

### Logic analyzer output

This shows the timing between sending and receiving in the above code:

---

## New functionality in IDE 1.6.0 onwards

Version 1.6.0 of the IDE has changed the way SPI works, to an extent. You **still need to do** `SPI.begin()` before using SPI. That sets up the SPI hardware. However now, when you are about to start communicating with a slave you **also** do `SPI.beginTransaction()` to set up SPI (for this slave) with the correct:

* Clock speed
* Bit order
* Clock phase and polarity

When you are done communicating with the slave, you call `SPI.endTransaction()`. For example:

```
SPI.beginTransaction (SPISettings (2000000, MSBFIRST, SPI_MODE0));
digitalWrite (SS, LOW);        // assert Slave Select
byte foo = SPI.transfer (42);  // do a transfer
digitalWrite (SS, HIGH);       // de-assert Slave Select
SPI.endTransaction ();         // transaction over

```

---

## Why use SPI?

> I would add one preliminary question: when/why would you use SPI? A need for multi-master configuration or a very large number of slaves would tilt the scale toward I2C.

This is an excellent question. My answers are:

* Some devices (quite a few) only support the SPI transfer method. For example the 74HC595 output shift register, the 74HC165 input shift register, the MAX7219 LED driver, and quite a few LED strips that I have seen. So, you might use it because the target device only supports it.
* SPI is really the fastest method available on the Atmega328 (and similar) chips. The fastest rate quoted above is 888,888 bytes per second. Using I2C you can only get around 40,000 bytes per second. The overhead of the I2C is quite substantial, and if you are trying to interface really quickly, SPI is the preferred choice. Quite a few chip families (eg. MCP23017 and MCP23S17) actually support both I2C and SPI so you often can choose between speed, and the ability to have multiple devices on a single bus.
* The SPI and I2C devices are both supported in hardware on the Atmega328 so you could conceivably be doing a transfer via SPI simultaneously with I2C which would give you a speed boost.

Both methods have their place. I2C lets you connect many devices to a single bus (two wires, plus ground) so it would be the preferred choice if you needed to interrogate a substantial number of devices, perhaps fairly infrequently. However the speed of SPI could be more relevant for situations where you need to output rapidly (eg. a LED strip) or input rapidly (eg. an ADC converter).

---

## References
> 113 votes

# Answer
Thank you for the information.

Mr. Nick Gammon said

> However the Leonardo and ProMicro don't expose the SS pin and thus cannot be used as an SPI slave.

but I could use ProMicro and Leonardo as SPI slave devides by wiring SS signal.

Reference: https://asukiaaa.blogspot.com/2023/05/atmega32u4-as-spi-slave.html
> 1 votes

---
Tags: arduino-uno, arduino-mega, c++, arduino-leonardo, spi
---


title: Avoid 1-LSB noise on ADC readings

text:
# Question
Title: Avoid 1-LSB noise on ADC readings
I have a potentiometer connected to an ADC input of an Arduino Leonardo. The ADC resolution is 10-bit (0..1024), while I need just 7-bit (0..127).

I use a simple filter to reduce the noise and then a `map` to cut the unused bits:

```
#define ADC_CH                18
#define ADC_FILTER            0.90

uint16_t value;

uint16_t adc = analogRead(ADC_CH);
value = (uint16_t) ((float) ADC_FILTER * adc + (1. - ADC_FILTER) * value);

```

I show `value` on an LCD. It's very stable, but it may happen that if the adc readings are in the nearby of two values, there is nothing that could prevent a change in the final value, even if the noise is of just few LSBs.

Is there a simple way to implement an hysteresis for each low-res value?

In this way the change between N and N+1 happens on a different ADC reading than between N and N-1, improving the noise rejection without increasing the filter delay (that would only increase the change interval).

# Answer
> 4 votes
When you reduce the resolution from 10 bits to 7 bits, every possible output corresponds to an interval of inputs. If you add some hysteresis, then those intervals should overlap. Below is a representation of the input intervals corresponding to outputs 0, 1,… 6, for an hysteresis width of 4:

```
input: 0    5   10   15   20   25   30   35   40   45   50   55   60
       └────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴────┴
       ├─────0────┤
           ├───────1──────┤
                   ├───────2──────┤
                           ├───────3──────┤
                                   ├───────4──────┤
                                           ├───────5──────┤
                                                   ├───────6──────┤

```

To implement this in code, you have to remember the last output, and change it only if the input lies outside the interval assigned to this output. Here is an example implementation:

```
const int hysteresis = 4;  // tune to taste

/* Remove 3 bits of resolution while adding some hysteresis. */
int resample(int adc)
{
    static int value;  // last output
    if (adc < (value<<3) - hysteresis) {
        value = (adc + hysteresis) >> 3;
    } else if (adc >= ((value+1)<<3) + hysteresis) {
        value = (adc - hysteresis) >> 3;
    }
    return value;
}

```

Note that a `static` local variable keeps its value between successive calls to the function.

---
Tags: adc, potentiometer, filter
---


# Question
Title: Why Did I Have To Program Duemilanove Bootloader?
As a volunteer for Public Invention, I have developed an Atmega328 based design in which I thought I was largely duplicating the Arduino UNO. Unlike the UNO, I did choose a CH340 USB to UART chip as that was a part on some UNO clones I have purchased.

Our project, the General Alarm Device, is at: https://github.com/PubInv/general-alarm-device

In the summer of 2022 We built up 15 Verion 1 assemblies. When we went to put boot loader into them we found we could put the Duemilanove bootloader but not the UNO. We do not know why.

Even with the Duemilanove bootloader we from time to time have problems uploading code. Some times the IDE reports a problem but the code uploaded. And perhaps some times we had to try to load more than once. Here is an issue written up after one user had some difficulty with firmware upload: https://github.com/PubInv/general-alarm-device/issues/127

Related questions, Is their a way to check which boot loader is in a board?

Could our root problem have been due to which boot loader was on the UNO we were using as the ICP?

# Answer
> 2 votes
> Related questions, Is their a way to check which boot loader is in a board?

I wrote some code to detect chip signatures a while ago which also reports on known bootloaders: http://www.gammon.com.au/forum/?id=11633

It really is too long to post here. The code however is at https://github.com/nickgammon/arduino\_sketches in particular in the **Atmega\_Board\_Detector** folder.

It's the same processor chip, you shouldn't have problems uploading, provided you use the appropriate clock speed and baud rate.

See my answers here:

---

> Where do I learn what is appropriate?

Well, the bootloaders have hard-coded into them the speed at which they expect the serial data to arrive. In the case of Optiboot it is 115200 baud, some other bootloaders may use 9600, 57600 or other speeds.

Now this baud rate is also dependent on the clock rate of the processor, because the baud rate is derived from the system clock.

So for example, on a Uno, Optiboot "expects" (in the sense that a computer can expect anything) that it will be running on a board at 16 MHz, and that the communication will be at 115200 baud.

So, if you are running at 8 MHz (half that speed) then the baud rate will naturally be 57600. However you can compensate for that by editing the file `boards.txt` in your Arduino installation and changing the baud rate, eg.

```
uno.name=Arduino Uno

uno.vid.0=0x2341
uno.pid.0=0x0043
uno.vid.1=0x2341
uno.pid.1=0x0001
uno.vid.2=0x2A03
uno.pid.2=0x0043
uno.vid.3=0x2341
uno.pid.3=0x0243

uno.upload.tool=avrdude
uno.upload.protocol=arduino
uno.upload.maximum_size=32256
uno.upload.maximum_data_size=2048
uno.upload.speed=115200

uno.bootloader.tool=avrdude
uno.bootloader.low_fuses=0xFF
uno.bootloader.high_fuses=0xDE
uno.bootloader.extended_fuses=0xFD
uno.bootloader.unlock_bits=0x3F
uno.bootloader.lock_bits=0x0F
uno.bootloader.file=optiboot/optiboot_atmega328.hex

uno.build.mcu=atmega328p
uno.build.f_cpu=16000000L
uno.build.board=AVR_UNO
uno.build.core=arduino
uno.build.variant=standard

```

Change the line "uno.upload.speed" to read 57600 in this case. That way the program (avrdude) which uploads to the board will upload slower, and since you are running at a slower speed, all will be well.

---

So, to make it all work:

* Find which bootloader you have (by comparing signatures) or simply upload a new bootloader of a known type. I have a page about uploading bootloaders which might help you there.
* Look up (eg. in that file) what the baud rate this particular bootloader uses (eg. 115200 for Optiboot).
* Set your processor to run at that clock speed with a crystal or resonator. (see the line "uno.build.f\_cpu" which is 16000000 in this case).
* If you choose to run the processor at a different speed (eg. using the internal clock, at 8 MHz) then either use a bootloader designed for 8 MHz, or change the upload speed baud rate line in the file as mentioned above. I suggest copy/pasting an existing entry, changing for example "uno" at the start of each line to "myboard" or something like that, and the "name" line as well, so it will appear in the drop-down menu of available boards).

---
Tags: arduino-uno, bootloader, arduino-duemilanove
---


# Question
Title: ARDUINO DC Motor Control over IR Sensor INPUT
I'm working on a school project where I'm building a small convyeor belt using an ARDUINO, DC motor and IR sensor for moving object detection so my color sensor can read color value.

I'm using single mosfet IRFZ44N to control DC motor. I can control DC motor using mosfet normally as turning it ON/OFF using digitalWrite using an arduino.

So, I want to stop convyeyor belt for 500ms when IR sensor detects HIGH and let color sensor read color of object and then let object move ahead normally on belt. I have written below code but the IR sensor detect object but motor never stops running.

```
#define IR_COLOR 34

const int MOTORpin = 32;
const long onDuration = 1000;// OFF time for LED
const long offDuration = 1000;// ON time for LED
int MOTORState =HIGH;// initial state of LED

boolean MOTOROnFlag          = true;

long rememberTime=0;

void setup() {
  pinMode(IR_COLOR, INPUT);
  pinMode(MOTORpin,OUTPUT);// define MOTORpin as output
  digitalWrite(MOTORpin,MOTORState);// set initial state
}

void loop() {

  int state = digitalRead(IR_COLOR);

 if( state == false )
 {
    if( (millis()- rememberTime) >= onDuration){
    MOTORState = LOW;
    rememberTime=millis();
    }
 }
 else if(state == true)
 {
    if( (millis()- rememberTime) >= offDuration){
    MOTORState =HIGH;// change the state of LED
    rememberTime=millis();// remember Current millis() time
    }
 }

 digitalWrite(MOTORpin,MOTORState);// turn the LED ON or OFF

}// loop ends

```

# Answer
You have the general idea.

Your code looks a bit cluttered. Comments are not part of the program, keep them away from the code.

The `if` statements reduce to `if (true)`, that means that `== true` part is redundant. All you need is `if(state)`. The `if` block will execute when `state` is true. Conversely `if (!state)` tests for `state` being false

When there are only two possible values, then `else if(state == true)` can be simply `else`.

Identical code that is in both parts of the `if-else` block should be moved to outside of the block, `rememberTime=millis();` should be moved to after the closing brace `}` of the `if-else` block.

Here is some code that does what you want.

This code has not been tested on a hardware device.

https://wokwi.com/projects/364353854313747457

```
const int     sensor_blocked  = LOW;              // define sensor values
const int     sensor_clear    = HIGH;

const int     motor_on        = HIGH;
const int     motor_off       = LOW;

const int     master_enable   =  2;
const int     motor_pin       =  3;
const int     sensor_pin      = 12;

int           sensor_state;
int           sensor_previous = sensor_clear;
int           motor_state     = motor_on;

unsigned long millis_previous = 0;
unsigned long millis_now;

const long    interval        = 500;

void setup() {

  pinMode(master_enable, INPUT_PULLUP);
  pinMode(sensor_pin,    INPUT_PULLUP);
  pinMode(motor_pin,     OUTPUT);

}

void loop() {

  sensor_state = digitalRead( sensor_pin );

  // ---------------------------------------------------------------------------------------------------

  if ( sensor_state != sensor_previous ) {             // only run this code when sensor state changes
    sensor_previous = sensor_state;                    // remember new sensor state

    if ( sensor_state == sensor_blocked ) {            // sensor became blocked
      motor_state = motor_off;                         // turn off motor
      millis_previous = millis();                      // start of "motor off" interval
    }
    delay(20);                                         // debounce sensor
  }

  // ---------------------------------------------------------------------------------------------------

  if ( motor_state == motor_off ) {                    // timer check is relevant only when motor is off
    millis_now = millis();
    if ( millis_now - millis_previous >= interval ) {  // check if timer expired
      motor_state = motor_on;                          // enable motor
    }
  }

  // ---------------------------------------------------------------------------------------------------

  if ( digitalRead( master_enable ) != LOW ) motor_state = motor_off;     // master switch

  // ---------------------------------------------------------------------------------------------------

  digitalWrite(motor_pin, motor_state);                // translate motor state into action

}

```
> 2 votes

---
Tags: arduino-uno, esp8266, esp32, motor, voltage-level
---


# Question
Title: How to make the built-in LED blink with a frequency of 5 Hz using interrupts
The task is: after five clicks on OK, the built-in LED starts flashing with a frequency of 5Hz using an interrupt. After the eighth click on OK, the flashing (and glowing) should stop.Why is flashing not working

```
bool ledState = false;
volatile bool ledOn = true;

void setup(){
TCCR2A = 0;
  TCCR2B = 0;
  TIMSK2 = 0;
  TCNT2 = 0;
  OCR2A = 77;
  TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20);
  TIMSK2 |= (1 << OCIE2A);
 pinMode(13, OUTPUT);
}

void loop(){
 if(button5.buttonPressedCount >= 5 && button5.buttonPressedCount < 8){
    ledState = true;
  }

  if(button5.buttonPressedCount > 7){
    ledState = false;
  }
}

ISR(TIMER2_COMPA_vect){
  if(ledState){
  digitalWrite(13, ledOn);
  ledOn = !ledOn;
  }
}

```

# Answer
> 2 votes
On the Uno (ATmega328P microcontroller), timers 0 and 2 are 8-bit only: they cannot count beyond 255. Timer 1, on the other hand, is 16-bits. This is the most convenient timer for generating low frequencies.

Speaking of frequencies... One LED period involves two toggles (turn on, then turn off). Thus, if you want the LED to blink at 5 Hz, the toggle action should happen at 10 Hz. Given that the CPU is clocked at 16 MHz, this means you have to toggle the LED every 1,600,000 CPU cycles.

If you set the prescaler to 1,024, you then you have to count 1,600,000/1,024 = 1,562.5 timer cycles. You cannot count a non-integer number of cycles, but you probably do not care about such accuracy. If you do care, set the prescaler to 256 and count 1,600,000/256 = 6,250 timer cycles by setting the compare match register to 6,249.

One last issue: keep in mind that, in normal counting mode, the timer counts up to its maximum value (65,535, or 255 on an 8-bit timer) and then restarts at zero. If you want it to count only up the value set in the compare match register, you should choose the appropriate waveform generation mode: the fast PWM mode that lets you control the TOP value with OCR1A.

---
Tags: arduino-uno, interrupt
---


# Question
Title: How do I reset my libraries back to original condition?
How do I reset my arduino installation back to its original state? i.e., no extra downloaded libraries, etc. If I delete Documents/Arduino/libraries is there any other state that needs to be cleaned up?

# Answer
> 2 votes
1. Delete the Documents -\> Arduino -\> Libraries to remove all your libraries.
2. Delete the User -\> AppData -\> Local -\> Arduino15 folder to remove all the preferences.
3. Uninstall Arduino IDE.
4. Install a fresh one.

# Answer
> 0 votes
Directory to suppress for reset config.

* C:\Users\YourName\\.arduinoIDE
* C:\Users\YourName\AppData\Local\Arduino15
* C:\Users\YourName\AppData\Local\Programs\Arduino IDE
* C:\Users\YourName\AppData\Local\arduino-ide-updater
* C:\Users\YourName\Documents\Arduino
* C:\Users\YourName\AppData\AppData\Roaming\Arduino IDE
* C:\Users\YourName\AppData\AppData\Roaming\arduino-ide

---
Tags: arduino-ide, installation
---


# Question
Title: Program work when used Delay() but same program doesn't work with millis()
I'm running a dc motor using esp32 and mosfet by taking readings of IR.

Program works fine when used delay() but same program doesn't work when uploaded using millis().

```
//This uses fixed delay()

// Pin definitions
const int irSensorPin = 34;  // IR sensor connected to GPIO 2
const int motorPin = 32;     // DC motor connected to GPIO 4

// Variables
bool isObjectDetected = false;

void setup() {
  // Initialize serial communication
  Serial.begin(9600);

  // Set pin modes
  pinMode(irSensorPin, INPUT);
  pinMode(motorPin, OUTPUT);
}

void loop() {
  // Check if object is detected
  if (digitalRead(irSensorPin) == LOW) {
    if (!isObjectDetected) {
      // Object detected for the first time
      isObjectDetected = true;
      Serial.println("Object detected. Stopping motor.");
      digitalWrite(motorPin, LOW);  // Stop the motor
      delay(500);                   // Wait for 500ms
      Serial.println("Resuming motor.");
      digitalWrite(motorPin, HIGH); // Start the motor
    }
  } else {
    if (isObjectDetected) {
      // Object is no longer detected
      isObjectDetected = false;
    }
  }
}

```

```
//This uses millis()

// Pin definitions
const int irSensorPin = 34;  // IR sensor connected to GPIO 34
const int motorPin = 32;     // DC motor connected to GPIO 32

// Variables
bool isObjectDetected = false;
unsigned long motorStopTime = 0;
const unsigned long motorDelayTime = 500;  // Delay time in milliseconds

void setup() {
  // Initialize serial communication
  Serial.begin(9600);

  // Set pin modes
  pinMode(irSensorPin, INPUT);
  pinMode(motorPin, OUTPUT);

  // Initialize motor state
  digitalWrite(motorPin, HIGH);  // Start the motor
}

void loop() {
  // Check if object is detected
  if (digitalRead(irSensorPin) == HIGH) {
    if (!isObjectDetected) {
      // Object detected for the first time
      isObjectDetected = true;
      Serial.println("Object detected. Stopping motor.");
      digitalWrite(motorPin, LOW);  // Stop the motor
      motorStopTime = millis();     // Record the stop time
    }
  } else {
    if (isObjectDetected) {
      // Object is no longer detected
      isObjectDetected = false;
      unsigned long currentTime = millis();
      if (currentTime - motorStopTime >= motorDelayTime) {
        Serial.println("Resuming motor.");
        digitalWrite(motorPin, HIGH); // Start the motor
      }
    }
  }
}

```

# Answer
> 1 votes
I am not sure I quite understand what the requirements are for this program. However, they do not do the same thing. I tried to represent their behavior as state diagrams, and here is what I got:

Version using `delay()`:

Version using `millis()`:

In the above diagrams, states with a gray background are those where the motor is off. As can be seen here, the first version never keeps the motor off for more than 0.5 s, where the second one can keep the motor indefinitely off if the sensor remains HIGH.

I suggest you start by drawing the state diagram corresponding to the behavior you actually want. Then, use the technique outlined in this tutorial on finite state machines to turn the diagram into code. Note that finite state machines work well with `millis()`-based timing.

---
Tags: arduino-uno, sensors, power, esp32, voltage-level
---


# Question
Title: Arduino Readings Update Correctly on Windows but not Linux
I have written a simple script to get angle measurements from a magnetic sensor. The script works very well on Windows. However, when compiling the script on a Linux VirtualBox (Ubuntu 20.04), the sensor repeats the first angle reading and does not change from this, despite the angle changing. There are no errors/warnings given by Windows or Linux at any stage of compiling/uploading.

Uploading the script on Windows and then viewing in Linux serial monitor works. However, uploading it on Linux and then viewing in Windows serial monitor does not work ("Board is not available"), even when connecting the board to Linux and not Windows.

I've compared both systems and everything seems to be the same: the same Arduino Uno R3 board, Arduino IDE 1.8.19 on both systems, Arduino AVR Boards 1.8.3 on both, "Arduino Uno" selected as the board on both, the library is SimpleFOC v2.2.0 on both. The only difference I can see is that the Windows port is COM3, whereas the Linux port is /dev/ttyACM0.

My script is the following and I would appreciate any help or advice to get this working on Linux. Thank you.

```
#include <SimpleFOC.h>

#define PI 3.1415926535897932384626433832795

// Magnetic sensor instance
MagneticSensorSPI AS5x4x = MagneticSensorSPI(8, 14, 0x3FFF);

void setup() {
  // initialize magnetic sensor hardware
  AS5x4x.init();

  // use monitoring with serial
  Serial.begin(9600);

  Serial.println("Ready.");
  _delay(1000);
}

void loop() {
  Serial.println(AS5x4x.getAngle()); // display angle
}

```

# Answer
> 0 votes
It turns out that the Arduino Library Manager was giving me incorrect information about the library version installed. By removing the library it was using and then installing the correct library that corresponds to the required version number, the code now works well.

---
Tags: arduino-uno, sensors, linux, windows, ubuntu
---


# Question
Title: How can I observe the "voltage dips" the starter kit talks about in Project 5?
Project 5 of the Arduino Starter Kit book (page 63) involves wiring up a potentiometer to control a servomotor (see diagram). The book also recommends wiring up decoupling capacitors as shown in the diagram:

> When a servo motor starts to move, it draws more current than if it were already in motion. This will cause a dip in the voltage on your board. By placing a 100uf capacitor across power and ground right next to the male headers as shown in Fig. 1, you can smooth out any voltage changes that may occur. You can also place a capacitor across the power and ground going into your potentiometer.

Since the book doesn't explicitly warn against it, I decided to do this whole project without the capacitors just to see what would happen. It seemed to work fine, I didn't notice any erratic behavior. Is there some experiment I could do to actually measure these voltage "dips"?

I thought maybe I could try to measure the voltage drop across the servo, so I wired it in series with a resistor and connected the A0 ADC pin between the servo and the resistor. I did measure a drop, but the servo didn't work... I'm guessing it wasn't getting enough power because of the resistor?

# Answer
> 1 votes
> I'm guessing it wasn't getting enough power because of the resistor?

Yes, that is probably what happened (you didn't specify what value your resistor had). When the servo tries to draw more current, more current has to flow through the resistor. This means more voltage over the resistor and less for the servo, which then doesn't have enough to to powerful or even run at all (depending on the resistors value).

> Is there some experiment I could do to actually measure these voltage "dips"?

You tried to measure the dips with the Arduino. Since the servo is connected directly to the 5V line of the Arduino, so its own Vcc, you cannot measure it the same way as the potentiometer. By default `analogRead()` uses Vcc as reference, meaning the max value. Instead you can configure it to use the internal 1.1V fixed reference (which doesn't depend on Vcc)(refer to `analogReference()`) and divide down Vcc with a fixed voltage divider (so that the voltage on the analog input pin would not exceed 1.1V).

Though to see the dips you still would need to measure the data points fast enough to catch them. Without knowing how long the dips might be it is difficult to say, if you can easily catch them. There are ways to do analog measurements relatively fast, but for a beginner (and specifically for a beginner book) that is a bit much.

The easier, but also more expensive solution (in terms of tools) is to measure Vcc with an oscilloscope. As entry a USB oscilloscope might be fitting (in the range of maybe 50$). If you don't wanna buy, you might be able to get access to one at the next makerspace or university. Some schools also might have some oscilloscopes.

> Since the book doesn't explicitly warn against it, I decided to do this whole project without the capacitors just to see what would happen. It seemed to work fine

Dips in your supplied voltage might cause the Arduino to reset. But that only happens, when the dip is too big. And that depends on multiple factors:

* How much current can be drawn from your power supply. USB ports on a PC won't give you more than 500mA for example. And some battery types have a big series resistance, meaning that the voltage will drop significantly, when you draw too much current from them.
* Sometimes, when working on a breadboard, the contacts might also have a significant resistance to them. This can lead to a voltage loss there.
* How strong the motor is. In starter kits you typically have these cheap and small SG90 micro servos. These don't draw a lot of power generally and are not really strong.
* How much load is on the motor. A motor draws different amounts of current depending on its load. When it runs feely the currently is the smallest. When its starting, then it needs to fight against its own inertia, thus needing more current. The most current is used, when the motor stalls, because it is not powerful enough to push against the load.

The last two points affect the motor current, which might cause a voltage dip, if the power supply cannot provide that much current with the specified voltage.

The capacitors are a precaution in this case. I think the author wanted to explain this to make sure that it would work for everyone and that students would already know about this, when moving to bigger, more power hungry projects.

---
Tags: arduino-uno
---


# Question
Title: Arduino uno weird behavior on a simple counter program
So I just got my first Arduino Uno board and the output on the serial monitor doesn't make sense to me. For this code

```
int counter = 0;

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

}

void loop() {
  counter++;
  Serial.println(counter);
  delay(1);
}

```

I'm expecting to see an increment once every 1ms. But what I see from the console is odd

First, I'm expecting to see the timestamp like this: 27.270, 27.271, 27.272... Second, from 27.301 to 27.334, I only saw the counter increase by 7 instead of ~30.

# Answer
If you do something like

```
Serial.println(580);

```

that is 5 characters printed (3 digits, then CR and LF to end the line). Each character takes ten bits worth of transmission time (one start bit, 8 data bits and one stop bit). The whole message is then 50-bit long on the serial line. At 9600 bits per second, this takes about 5.2 milliseconds.

Note that the PC seems to be buffering the data, which is displayed in batches, each batch having a single timestamp. Thus you see that, on **average** there are 5.2 ms between increments.
> 5 votes

---
Tags: arduino-uno
---


# Question
Title: timing changes once DC motors are connected to power
I'm using an arduino uno with two DC motors. I'm also using the built in LED to tell me when the motors should be on as a debug tool. The code is a simple while loop that turns both the motors and the LED on for 10 seconds, and off for 5, and repeat, while a witch is on. This works fine when the motors are not connected to power (when the switch is on, the LED turns on for 10 secs, off for 5 and repeat), but when the motor driver is connected to the power the timing is changed. The motors and the LED are on for less than a second, and off for 5. the "on" period changes a bit, once it even reached the intended 10 seconds.

Why is that and how do I fix that? I tried changing batteries (though i don't know how that might change things, as the led is also working incorrectly and it works of a seperate power source).

the Arduino is connected to a 9V battery and the motors are connected to 4 AA batteries through a L298N motor driver.

this is my code:

```
#include <Arduino.h>
int RightSpeedPin = 5;
int Rdir2 = 6;
int Rdir1 = 7;
int led = 13;
int LeftSpeedPin = 10;
int Ldir2 = 8;
int Ldir1 = 9;
int SwitchPin = 4;
int ReadVal;
void setup() {
  // put your setup code here, to run once:
  pinMode(Rdir1, OUTPUT);
  pinMode(Rdir2, OUTPUT);
  pinMode(RightSpeedPin, OUTPUT);
  pinMode(LeftSpeedPin, OUTPUT);
  pinMode(Ldir1, OUTPUT);
  pinMode(Ldir2, OUTPUT);
  pinMode(SwitchPin, INPUT);
  pinMode(led, OUTPUT);
}

void loop() {
  ReadVal = digitalRead(SwitchPin);
  while (ReadVal == 1)
  {
    digitalWrite(led, HIGH);
  // starting situation- both motors heading forward
    // running for 10 secs
    digitalWrite(Rdir1, HIGH);
    digitalWrite(Ldir1, HIGH);
    digitalWrite(Rdir2, LOW);
    digitalWrite(Ldir2, LOW);
    analogWrite(RightSpeedPin, 255);
    analogWrite(LeftSpeedPin, 255);
    delay(10000);
    // off for 5
    analogWrite(RightSpeedPin, 0);
    analogWrite(LeftSpeedPin, 0);
    digitalWrite(led, LOW);
    ReadVal = digitalRead(SwitchPin);
    delay(5000);
  }
}

```

link to the schematics. its rough, I'm not very experienced at drawing schematics. Note that all the ground wires are connected to a breadboard ground rail other that the 9V that powers the arduino. its connected with a round plug, so i don't have individual wires. EDIT: fixed the schematic

# Answer
> 0 votes
After debugging by printing:

```
sTime = millis();
analogWrite(RightSpeedPin, 255);
analogWrite(LeftSpeedPin, 255);
delay(5000);
analogWrite(RightSpeedPin, 0);
analogWrite(LeftSpeedPin, 0);
Serial.print(millis() - stime);

```

I got times that are less than 300 ms, and no reset (added print to setup). I still have no idea why. after that, I just replaced delay with `while (millis() < Stime + t) {` which solved my problem.

---
Tags: arduino-uno, motor
---


# Question
Title: MKR 1010 WIFI Built-in RGB LED not working with BLE
in addition to the standard LED\_BUILTIN, MKR 1010 WIFI comes with a built-in **RGB LED**.

This RGB LED fails when used along the on-board BLE, no matter what program sequence I test.

To reproduce the issue, turn on the LED and then start BLE which will turn the LED off.

```
#include <WiFiNINA.h>
#include <utility\wifi_drv.h>
#include <ArduinoBLE.h>

void setup() {

  const int ledPin = 27;  //R=26 G=25 B=27

  WiFiDrv::pinMode(ledPin, OUTPUT);

  WiFiDrv::digitalWrite(ledPin, HIGH);

  Serial.begin(115200);
  while (!Serial);

  if (!BLE.begin()) { // ble.begin trun the led off
    Serial.println("BLE Failed");
    while (1);
  }

  Serial.println("BLE started"); // last line shown on console

  WiFiDrv::digitalWrite(ledPin, HIGH);

  // program never gets here

}

void loop() {}

```

The RGB LED is connected to NINA’s GPIO pins. Two of them (green and blue) are part of the UART, and another one is used for system control signals (red).

I assumed that BLE.begin uses the UART to communicate with the processor and therefore avoided the red pin and added delays between commands hoping to separate the actions, but it didn’t work.

My goal is to use the RGB LED to indicate BLE states without adding three sets of MOSFETs and resistors. Ideas?

# Answer
> 1 votes
The ArduinoBLE library resets the NINA firmware to BLE mode (code here). In this mode the NINA firmware just sets ESP32 SDK (IDF framework) to handle the BLE commands.

The RGB LED is handled by the part of the Arduino NINA firmware which handles the commands from the WiFiNINA library. These commands are communicated over SPI and are not handled if the firmware is in BLE mode.

---
Tags: rgb-led, ble, mkr1010wifi
---


# Question
Title: Why do you need a second resistor when using a photoresistor/LDR?
A photoresistor is already a resistor and will limit the voltage in the circuit. Why can't this be connected to a pin and measured? Why is a second resistor needed to connect the photoresistor to ground?

# Answer
The simple answer is that **voltage** is very easy for the Arduino to measure, while **resistance** is not, and most sensors such as Photoresistor (LDR), flex sensor, thermistors and more - are actually a variable resistors.

The main reason it's hard to measure resistance changes is that the Arduino (and most IC) contain a tiny system called **Analog to Digital Converter (ADC)**. This system translates changes in **analog voltage** to a series of 1's and 0's that can be in turn converted to an Integer for example.

The ADC is designed to read *voltage* changes, and if we want to use the Arduino's **analogRead** (which utilizes the ADC) to get the Photoresistor readings for example, we will need a way to convert the changes in *resistance* to changes in *voltage* \- and a voltage divider is the easiest way to do it.

It is true that the sensor is already a resistor, and as such it should change the voltage across it. But you would have trouble measuring the voltage changes, since there is no reference point except for Vcc (5V) and Ground:

In contrary, when using a voltage divider, you have a well defined reference point to measure the voltage changes:
> 13 votes

# Answer
This isn't strictly an Arduino question, but I appreciate that things like photo-resistors are common early projects for Arduino users.

Resistors (and other components) don't really limit the voltage in the circuit as such. Rather, each component in a series circuit gets a proportion of the total voltage. That proportion is determined by its resistance.

If you only have one component, then the entire voltage is dropped across it no matter what resistance it has. Changing the resistance in that situation would only affect the amount of current flowing through it.

You need the second resistor as a fixed reference point. You know how much voltage it will get if both resistances are equal, and that the relationship between voltage and resistance is (hypothetically) linear. You can therefore use that to figure out what resistance the other component has, e.g. the photo-resistor.

As a side note, the second resistor can also play an important role for safety. Without it, you could potentially end up with a short-circuit if the other component's resistance goes too low.
> 8 votes

# Answer
Accurate measurement of resistance requires a precise current source (http://www.digikey.com/product-search/en/integrated-circuits-ics/pmic-current-regulation-management/2556448?k=current%20source).

Ohm's law, V=IR or R=V/I states that for linear components, the value of resistance in the circuit can be estimated by the ratio of the applied voltage divided by the current. With a simple voltage divider, as the resistance of the sensor changes so does the current in the circuit. So measuring the voltage at the junction does not necessarily provide an accurate indication of the current in the circuit. Both the imposed voltage and current should be controlled to obtain accurate measurements.
> 2 votes

# Answer
also another big reason for it is if you have just in series, a power source, an LDR and say a bulb, then the bulb may come on as soon as the LDR resistance gets low enough, then it will get brighter as the resistance keeps decreasing. If configured with more resistors in a potential divider with a transistor and the bulb at the collector side, then you can vary the resistors to define the exact amount of light that will allow approx 1.6V (?)(whatever voltage turns the base into a conductor anyway), and therefore the light at which the bulb will suddenly turn on with a constant power supply direct from the power source through a fixed resistor if needed.

So in series an LDR will vary the current with light around the circuit, in a divider and transistor it functions as a light dependant switch
> 1 votes

# Answer
Unlike other electric components, a photoresistor(or light-dependent resistor,LDR,or photocell) is a variable resistor. This means its resistance can depend according to light intensity.

I will go first with half of the circuit diagram to understand clearly.

The resistance of a photoresistor decreases with increasing light intensity. Strong Light —\> LDR resistance(decreases to 0ohms) So the 10k(ohm) resistor sees closer to 5V.

The resistance of a photoresistor increases with decreasing light intensity. Dim Light —\>LDR resistance(increases to infinity).

So, the 10k(ohm) resistor only gets a little voltage.

Here is the full circuit diagram that you want to ask why second resistor is needed.

The key point is Arduino board also has Vcc(5V) and ground. So, there is no current if the potential difference is zero. Therefore, firstly, Vcc(5V) will flow through the photoresistor and go to the 10k(ohm) resistor.

Then, since there is a parallel circuit, arduino will get the same voltage as the 10k(ohm) resistor. So this LDR resistor does the function of a pull-up resistor which draws the current to VCC.
> 1 votes

# Answer
I THINK NONE OF THE ABOVE ANSWERS ARE CLEARLY DEFINING THE SOLUTION. I WILL ANSWER WITH RESPECT TO THE WORKINGS OF AN LDR CIRCUIT WITH A LIGHT BULB THAT SWITCHES ON IN THE DARK AND OFF IN LIGHT.

LETS ASSUME THAT WE HAVE AN LDR ONLY CONNECTED IN SERIES TO A LIGHT BULB. THE LDR IS ALREADY ACTING AS A VARIABLE RESISTOR AND HENCE WILL ALLOW CURRENT TO FLOW IN THE PRESENCE OF LIGHT, (LIGHT INTENSITY BEING DEPENDANT ON THE CURRENT RESISTANCE) AND WILL LIMIT THE CURRENT WHEN IT IS DARK. THIS MEANS THAT THE BULB LIGHTS UP IN LIGHT AND IS OFF WHEN IT IS DARK. THERE IS NO PRACTICAL USE FOR THIS. I WANT THE BULB TO LIGHT IN THE DARK AND SWITCH OFF IN THE PRESENCE OF LIGHT.

SO WHAT I DO IS ADD A RESISTOR IN SERIES TO THE LDR. THIS RESISTOR HAS A FIXED RESISTANCE MUCH LOWER THAN THE LDR AT ITS HIGHEST RESISTANCE BUT MUCH HIGHER THAN THE LDR AT ITS LOWEST RESISTANCE. THE BULB ELECTRIC PATH IS CONNECTED BETWEEN THE LDR AND THE RESISTOR. PLEASE NOTE THAT THE RESISTOR IS PLACED ABOVE THE LDR.

NOW LOOK AT IT IN TERMS OF CURRENT FLOW.

WHEN THERE IS LIGHT, THE LDR RESISTANCE IS LESSER THAN THE RESISTOR. HENCE THE CURRENT FLOWS FROM THE BATTERY TO THE RESISTOR AND A SIGNIFICANT PORTION OF THAT CURRENT CONTINUES TO FLOW IN SERIES THROUGH THE LDR AND BACK TOWARDS THE BATTERY. THE REMAINDER OF CURRENT IS CARRIED OVER TO THE BULB ELECTRIC PATH WHICH IS NOT SUFFICIENT TO LIGHT THE BULB. HENCE THE BULB STAYS OFF IN THE LIGHT.

WHEN ITS DARK, THE LDR RESISTANCE IS HIGHER THAN THE RESISTOR. HENCE THE CURRENT FLOWS FROM THE BATTERY TO THE RESISTOR AND INSTEAD OF CONTINUING TO THE LDR WHICH IS CONNECTED IN SERIES, IT TAKES THE PATH OF LEAST RESISTANCE TOWARDS THE BULB. THE LDR RESISTANCE HAS EFFECTIVELY BLOCKED THE CURRENT FROM FLOWING THROUGH IT AND DIRECTED IT TOWARD THE BULB. HENCE THE BULB LIGHTS UP IN THE DARK.

IN TERMS OF PRACTICAL USAGE THIS IS MOST IMPORTANT CONCEPT. ALL OTHER REASONS FOR USING A SECOND RESISTOR WITH AN LDR ARE SECONDARY.
> -1 votes

---
Tags: photoresistor
---


title: RFID card read loop seems to stop

text:
# Question
Title: RFID card read loop seems to stop
I successfully programmed an RFID card reader to switch lights on and off if any rfid card is presented. I have tested this and it works, with the lights continually switching on and off if any rfid enabled card is is presented.

I tried to add a command that if two specific cards are read (identified by their UID numbers) then only those cards would reset the lights to "off" no matter what the state they were currently in - like a reset button.

The problem is that once one of those cards is presented, the light goes off but the system stops responding and presenting one of the other cards no longer turns the light on and off.

I am fairly new to programming Arduino, as well as with RFID technology, but it seems like the loop does not reset to the beginning properly, or my IF statement somehow leaves the system in a state where the beginning code can't be run.

My code is below. Any thoughts would be appreciated.

\`

```
#define r1 A0
int relay1 = LOW;

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

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

void setup()
{
  pinMode(r1, OUTPUT);

  Serial.begin(9600);   // Initiate a serial communication
  SPI.begin();      // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522
  Serial.println("Approximate your card to the reader...");
  Serial.println();
}

void loop()
{
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }

// Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }

  //Show UID on serial monitor
  Serial.print("UID tag :");
  String content = "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
    Serial.print(mfrc522.uid.uidByte[i], HEX);
    content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
    content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();
  Serial.print("Message : ");
  content.toUpperCase();

  if ((content.substring(1) == "23 49 1F BE") || (content.substring(1) == "CB CB 2C E3")) //change here the UID of the card/cards that you want to give access
  {
   Serial.println("Staff access");
    Serial.println();
    relay1 = HIGH;
    digitalWrite(r1, relay1);
    delay(500);
  }
  else
  {

    Serial.println("Authorized access");
    Serial.println();
    relay1 = ~ relay1;
    digitalWrite(r1, relay1);
    delay(500);
  }
}

```

\`

# Answer
> 1 votes
The problem is the inappropriate use of the tilde (~) , which is a bitwise NOT operator, against the `int` variable `relay1`. It appears to work correctly when relay1 starts with LOW which has the value 0. That is, relay1 has the internal value 0b0000000000000000. If now the statement `relay1 = ~relay1` is executed, relay1 has the internal value 0b1111111111111111. This is treated as a HIGH in the expression `digitalWrite(r1, relay1);` So it appears to work correctly. If again the statement `relay1 = ~relay1` is executed, relay1 has the internal value 0b0000000000000000 This is treated as a LOW in the expression `digitalWrite(r1, relay1);` So that would also appear to work continuously, turning the relay on and off.

The problem comes when you explicitly set relay1 to HIGH here: `relay1 = HIGH;`. HIGH has the value 1, that is relay1 now has the intenal value 0b0000000000000001 and again that works, however, the next execution of the statement `relay1 = ~relay1` gives relay1 the internal value 0b1111111111111110 which is also treated as HIGH. So, from now on, the statement `relay1 = ~relay1` will always result in relay1 having a value which is interpreted as HIGH. So the relay appears to be stuck.

The solution, which already appears in a comment, is to change the statement `int relay1 = LOW;` to `bool relay1 = LOW;` and change this statement `relay1 = ~ relay1;` to `relay1 = ! relay1;`

---
Tags: arduino-uno, programming, rfid
---


title: Write faster on AT24C32

text:
# Question
Title: Write faster on AT24C32
I'm using AT24C32 EEPROM chip from ATmel. I found code that will write and read bytes from chip. Code writes and reads bytes correctly and without any problem.

But I have to write few 8-byte values often(every 10-15 seconds). I did "cut" those variables to 48 bit(so 6-byte variable) and with that I speeded up saving but it's still slow.

Is there any chance to speed up saving proccess? Code is below

```
void EEPROMClass::write48(int16_t address, uint64_t value)
{
    uint8_t byteValue = (value & 0xFF);
    write8(address, byteValue);

    byteValue = ((value >> 8) & 0xFF);
    write8(address + 1, byteValue);

    byteValue = ((value >> 16) & 0xFF);
    write8(address + 2, byteValue);

    byteValue = ((value >> 24) & 0xFF);
    write8(address + 3, byteValue);

    byteValue = ((value >> 32) & 0xFF);
    write8(address + 4, byteValue);

    byteValue = ((value >> 40) & 0xFF);
    write8(address + 5, byteValue);
}

void EEPROMClass::write8(int16_t const address, uint8_t const value)
{
    Wire.beginTransmission(AT24C32);

    Wire.write(highAddressByte(address));
    Wire.write(lowAddressByte(address));

    Wire.write(value);
    delay(2);
    Wire.endTransmission();
}

```

`delay` of 2ms is required otherwise EEPROM will write different value. Code has 4 "6-byte" variables(total of 24 bytes). Every byte is minimum 2ms, so total time to save only "6-byte" variables is 48ms(round to 50ms). That is too slow for me. How to speed up `write` function?

# Answer
after writing a value to EEPROM, and terminating the I2C connection with a STOP, the EEPROM enters a self writing mode to write what you have sent to it, to it's internal memory. (you don't actually write the values to the memory section; you write them to a buffer, and then the internal controller writes them to its memory section).

this "self writing mode" takes about 5ms, and you cant do nothing about it. but you can use "page writing" instead of byte writing. that 32K model, has a 32 bytes page buffer. you have to send all the bytes (as long as they are under 32 bytes) at once in one I2C transaction. this time, the chip fills its page buffer and then after a STOP, writes it all at once on its memory. in your code, you just write one byte in your buffer each time in a single transaction. like sending a bus with just one passenger at a time.

remember in this mode, you only set the address of the first byte. the next bytes automatically settle in the next addresses.
> 5 votes

# Answer
Mostly the best speed you get, is if you use the 'page' size, which is 32 bytes. It will take longer than 4 bytes, but less then 4 times 8 bytes.

You could do a check to see if using one page write (of 32 bytes) is faster than 6 times a one byte write.

However, it depends if you can change your design so it writes 32 bytes at a time. E.g. by writing 60 seconds 4 times 8 bytes (32 bytes) in one page write, instead of every 15 seconds 8 bytes. This will be much faster.
> 1 votes

# Answer
I never let processor wait a process to finish. I call a procedure do whatever could be done put a mark where I got and return to do other stuff. Next scan I pick up from where I left and continue if the conditions allow, if not i leave it for the next scan. I would never put a waiting time in a loop. In your case I would open the communication, send as many bytes as I can, put a mark how far I got, close the communication and return. Next scans(when the data are transferred from the buffer to the EEPROM) I would repeat the same process for the rest of the data. At any scan I invest a few hundreds of microseconds.
> 1 votes

---
Tags: eeprom
---