body:
I am working on a tilt compensated compass with the LSM303DLHC. I manage to calibrate the magnetic and accelero part. I managed to calculate pitch and roll. But when it comes to calculate tilt compensation for the compass something goes wrong. My values on the serial monitor just don't make sense...If I calculate compass heading from calibrated magneto values it works using the Y axis as the magnetic vector. How would I be able to change that to the X-axis?
```/*This program is reading out a magnetometer sensor
   LSM303DLHC including accelerometer to correct for position

*/
#include <Wire.h>

const int LSM303_ADDR = 0x19;
const int LSM303_ADDR_MAG = 0x1E;

//control register addresses
const int CTRL_REG1_ADDR = 0x20;
const int CTRL_REG2_ADDR = 0x21;
const int CTRL_REG3_ADDR = 0x22;
const int CTRL_REG4_ADDR = 0x23;
const int CTRL_REG5_ADDR = 0x24;
const int CTRL_REG6_ADDR = 0x25;

const int CRA_REG_M_ADDR = 0x00;
const int CRB_REG_M_ADDR = 0x01;
const int MR_REG_M_ADDR = 0x02;

//data register addresses LSB first for accelero, MSB first for magneto
const int Accelero_First_data_addr = 0x28;
const int Magneto_First_data_addr = 0x03;
const int Temp_out_data_addr = 0x31;//MSB first 12 bits

int CTRL_REG1_A_value = 0x47; //50Hz Low Power disable, all axes enabled
int CTRL_REG2_A_value = 0x00; //
int CTRL_REG3_A_value = 0x00; //no interrupt or watermark enabled
int CTRL_REG4_A_value = 0x00; // 2G full scale, high resolution, no SPI mode selected
int CTRL_REG5_A_value = 0x00; // nothing enabled
int CTRL_REG6_A_value = 0x00; // nothing enabled

int CRA_REG_M_value = 0x14; // Temp sens enabled, 15Hz data rate output
int CRB_REG_M_value = 0x20; // 2G is data 1100 - 980 G/LSB

int MR_REG_M_value = 0x00;

int16_t MagRaw_X_axis_value, MagRaw_Y_axis_value, MagRaw_Z_axis_value;
int16_t AccRaw_X_axis_value, AccRaw_Y_axis_value, AccRaw_Z_axis_value;

float pitch, roll;
float Xm_calibrated, Ym_calibrated, Zm_calibrated;
float Xm_norm, Ym_norm, Zm_norm, Xa_norm, Ya_norm, Za_norm;
float norm_a, norm_m;

void setup() {// put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();
  setupLSM303();
  Serial.println("Setup complete..");
}

void loop() {// put your main code here, to run repeatedly:
  MagnetoDataRead();
  AcceleroDataRead();

}

void setupLSM303() {
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG1_ADDR);
  Wire.write(CTRL_REG1_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG2_ADDR);
  Wire.write(CTRL_REG2_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG3_ADDR);
  Wire.write(CTRL_REG3_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG4_ADDR);
  Wire.write(CTRL_REG4_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG5_ADDR);
  Wire.write(CTRL_REG5_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG6_ADDR);
  Wire.write(CTRL_REG6_A_value);
  Wire.endTransmission();
  //magneto register setup
  Wire.beginTransmission(LSM303_ADDR_MAG);
  Wire.write(CRA_REG_M_ADDR);
  Wire.write(CRA_REG_M_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR_MAG);
  Wire.write(CRB_REG_M_ADDR);
  Wire.write(CRB_REG_M_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR_MAG);
  Wire.write(MR_REG_M_ADDR);
  Wire.write(MR_REG_M_value);
  Wire.endTransmission();
}

void MagnetoDataRead() {
  Wire.beginTransmission(LSM303_ADDR_MAG );
  Wire.write(Magneto_First_data_addr);
  Wire.endTransmission();

  Wire.requestFrom(LSM303_ADDR_MAG , 6);
  if (Wire.available() <= 6) {
    MagRaw_X_axis_value = (Wire.read() << 8) | (Wire.read());
    MagRaw_Y_axis_value = (Wire.read() << 8) | (Wire.read());
    MagRaw_Z_axis_value = (Wire.read() << 8) | (Wire.read());

    float X_mag_cal = MagRaw_X_axis_value / 1100.0;
    float Y_mag_cal = MagRaw_Y_axis_value / 1100.0;
    float Z_mag_cal = MagRaw_Z_axis_value / 980.0;

    //input calibration factors
    float Xm_offset_corrected = MagRaw_X_axis_value - 0.041423;
    float Ym_offset_corrected = MagRaw_Y_axis_value + 0.022448;
    float Zm_offset_corrected = MagRaw_Z_axis_value + 0.078354;

    Xm_calibrated = 94.622065 * Xm_offset_corrected + 0.831029 * Ym_offset_corrected + 1.647934 * Zm_offset_corrected;
    Ym_calibrated = 0.831029 * Xm_offset_corrected + 93.462985 * Ym_offset_corrected + 3.416885 * Zm_offset_corrected;
    Zm_calibrated = 1.647934 * Xm_offset_corrected + 3.416885 * Ym_offset_corrected + 76.477691 * Zm_offset_corrected;

    //normalization formula
    norm_m = sqrt(sq(Xm_calibrated) + sq(Ym_calibrated) + sq(Zm_calibrated));
    Xm_norm = Xm_calibrated / norm_m;
    Ym_norm = Ym_calibrated / norm_m;
    Zm_norm = Zm_calibrated / norm_m;

    //float Heading = ((atan2(Ym_calibrated, Xm_calibrated)) * 180 ) / PI;
    //if (Heading < 0) {
    //  Heading = 360 + Heading;
    //}
    /*
        Serial.print(X_mag_cal, 10);
        Serial.print("\t");
        Serial.print(Y_mag_cal, 10);
        Serial.print("\t");
        Serial.print(Z_mag_cal, 10);
        Serial.println("\t");
    */

    delay(50);

  }
}

void AcceleroDataRead() {
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(Accelero_First_data_addr | 0x80);
  Wire.endTransmission();

  Wire.requestFrom(LSM303_ADDR, 6);
  if (Wire.available() <= 6) {
    AccRaw_X_axis_value = (Wire.read()) | (Wire.read() << 8);
    AccRaw_Y_axis_value = (Wire.read()) | (Wire.read() << 8);
    AccRaw_Z_axis_value = (Wire.read()) | (Wire.read() << 8);

    float X_Acc =  (AccRaw_X_axis_value >> 4);
    float Y_Acc =  (AccRaw_Y_axis_value >> 4);
    float Z_Acc =  (AccRaw_Z_axis_value >> 4);
//calibrate offset
    float X_acc_offset_corrected = X_Acc + 6.676443;
    float Y_acc_offset_corrected = Y_Acc - 6.622381;
    float Z_acc_offset_corrected = Z_Acc + 55.408804;
//calibrate
    float X_acc_calibrated = 0.977273 * X_acc_offset_corrected - 0.003458 * Y_acc_offset_corrected + 0.012639 * Z_acc_offset_corrected;
    float Y_acc_calibrated = -0.003458 * X_acc_offset_corrected + 0.979674 * Y_acc_offset_corrected - 0.001130 * Z_acc_offset_corrected;
    float Z_acc_calibrated = 0.012639 * X_acc_offset_corrected - 0.001130 * Y_acc_offset_corrected + 0.897083 * Z_acc_offset_corrected;
//normalize
    norm_a = sqrt(sq(X_acc_calibrated) + sq(Y_acc_calibrated) + sq(Z_acc_calibrated));
    Xa_norm = X_acc_calibrated / norm_a;
    Ya_norm = Y_acc_calibrated / norm_a;
    Za_norm = Z_acc_calibrated / norm_a;

//calculate pitch and roll
    pitch = asin(-Xa_norm) * 180 / PI;
    roll = (atan2(Ya_norm, Za_norm) * 180) / PI;
//calculate vectors fo tilt compensation
    float Xh = Xm_norm * cos(pitch * PI / 180) + Zm_norm * sin(pitch * PI / 180);
    float Yh = Xm_norm * sin(roll * PI / 180) * sin(pitch * PI / 180) + Ym_norm * cos(roll * PI / 180) - Zm_norm * sin(roll * PI / 180) * cos(pitch * PI / 180);
//calculate tilt compensated heading
    float Heading = ((atan2(Yh, Xh)) * 180.0 ) / PI;
    if (Heading < 0) {
      Heading = 360 + Heading;
    }

    Serial.print("Pitch \t");
    Serial.print(pitch);
    Serial.print("\t roll \t");
    Serial.print(roll);
    Serial.print("\t");
    Serial.println(Heading);

    delay(50);
  }
}
 ```
I have been stuck on this for a few days now. Any help is appreciated!

title: LSM303 unable to compensate tilt

Answers: 2

body: Found it...Magneto data is coming out XZY not XYZ...when I changed this it works! Sorry, RTFMA would have given me the answer straight away.

body:
It seems I got it working! Thanks a lot for your help, I owe you a few beers. For anyone following and interested here is my code:
```/*This program is reading out a magnetometer sensor
   LSM303DLHC including accelerometer to correct for position
  Vector calculation to be implemented
*/
#include <Wire.h>
#include <Math.h>

const int LSM303_ADDR = 0x19;
const int LSM303_ADDR_MAG = 0x1E;

//control register addresses
const int CTRL_REG1_ADDR = 0x20;
const int CTRL_REG2_ADDR = 0x21;
const int CTRL_REG3_ADDR = 0x22;
const int CTRL_REG4_ADDR = 0x23;
const int CTRL_REG5_ADDR = 0x24;
const int CTRL_REG6_ADDR = 0x25;

const int CRA_REG_M_ADDR = 0x00;
const int CRB_REG_M_ADDR = 0x01;
const int MR_REG_M_ADDR = 0x02;

//data register addresses LSB first for accelero, MSB first for magneto
const int Accelero_First_data_addr = 0x28;
const int Magneto_First_data_addr = 0x03;
const int Temp_out_data_addr = 0x31;//MSB first 12 bits

int CTRL_REG1_A_value = 0x47; //50Hz Low Power disable, all axes enabled
int CTRL_REG2_A_value = 0x00; //
int CTRL_REG3_A_value = 0x00; //no interrupt or watermark enabled
int CTRL_REG4_A_value = 0x00; // 2G full scale, high resolution, no SPI mode selected
int CTRL_REG5_A_value = 0x00; // nothing enabled
int CTRL_REG6_A_value = 0x00; // nothing enabled

int CRA_REG_M_value = 0x14; // Temp sens enabled, 15Hz data rate output
int CRB_REG_M_value = 0x20; // 2G is data 1100 - 980 G/LSB

int MR_REG_M_value = 0x00;

int16_t MagRaw_X_axis_value, MagRaw_Y_axis_value, MagRaw_Z_axis_value;
int16_t AccRaw_X_axis_value, AccRaw_Y_axis_value, AccRaw_Z_axis_value;

float pitch, roll;
float Xm_calibrated, Ym_calibrated, Zm_calibrated;
float Xm_norm, Ym_norm, Zm_norm, Xa_norm, Ya_norm, Za_norm;
float norm_a, norm_m;

void setup() {// put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();
  setupLSM303();
  Serial.println("Setup complete..");
}

void loop() {// put your main code here, to run repeatedly:
  MagnetoDataRead();
  AcceleroDataRead();

}

void setupLSM303() {
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG1_ADDR);
  Wire.write(CTRL_REG1_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG2_ADDR);
  Wire.write(CTRL_REG2_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG3_ADDR);
  Wire.write(CTRL_REG3_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG4_ADDR);
  Wire.write(CTRL_REG4_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG5_ADDR);
  Wire.write(CTRL_REG5_A_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(CTRL_REG6_ADDR);
  Wire.write(CTRL_REG6_A_value);
  Wire.endTransmission();
  //magneto register setup
  Wire.beginTransmission(LSM303_ADDR_MAG);
  Wire.write(CRA_REG_M_ADDR);
  Wire.write(CRA_REG_M_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR_MAG);
  Wire.write(CRB_REG_M_ADDR);
  Wire.write(CRB_REG_M_value);
  Wire.endTransmission();
  Wire.beginTransmission(LSM303_ADDR_MAG);
  Wire.write(MR_REG_M_ADDR);
  Wire.write(MR_REG_M_value);
  Wire.endTransmission();
}

void MagnetoDataRead() {
  Wire.beginTransmission(LSM303_ADDR_MAG );
  Wire.write(Magneto_First_data_addr);
  Wire.endTransmission();

  Wire.requestFrom(LSM303_ADDR_MAG , 6);
  if (Wire.available() <= 6) {
    MagRaw_X_axis_value = (Wire.read() << 8) | (Wire.read());
    MagRaw_Z_axis_value = (Wire.read() << 8) | (Wire.read());
    MagRaw_Y_axis_value = (Wire.read() << 8) | (Wire.read());

    float X_mag_cal = MagRaw_X_axis_value / 1100.0;
    float Y_mag_cal = MagRaw_Y_axis_value / 1100.0;
    float Z_mag_cal = MagRaw_Z_axis_value / 980.0;

    //input calibration factors
    float Xm_offset_corrected = X_mag_cal - 0.032874;
    float Ym_offset_corrected = Y_mag_cal + 0.047876;
    float Zm_offset_corrected = Z_mag_cal + 0.039649;

    Xm_calibrated = 92.387197 * Xm_offset_corrected - 0.307374 * Ym_offset_corrected + 1.151625 * Zm_offset_corrected;
    Ym_calibrated = -0.307374 * Xm_offset_corrected + 85.002110 * Ym_offset_corrected + 1.169755 * Zm_offset_corrected;
    Zm_calibrated = 1.151625 * Xm_offset_corrected + 1.169755 * Ym_offset_corrected + 80.276037 * Zm_offset_corrected;

    //normalization formula
    norm_m = sqrt(sq(Xm_calibrated) + sq(Ym_calibrated) + sq(Zm_calibrated));
    Xm_norm = Xm_calibrated / norm_m;
    Ym_norm = Ym_calibrated / norm_m;
    Zm_norm = Zm_calibrated / norm_m;

    /*
        Serial.print(X_mag_cal, 10);
        Serial.print("\t");
        Serial.print(Y_mag_cal, 10);
        Serial.print("\t");
        Serial.print(Z_mag_cal, 10);
        Serial.println("\t");
    */

    //float Heading = ((atan2(Ym_norm, Xm_norm)) * 180.0 ) / PI;
    //if (Heading < 0) {
    // Heading = 360 + Heading;
    //}
    //Serial.println(Heading);
    //delay(50);

  }
}

void AcceleroDataRead() {
  Wire.beginTransmission(LSM303_ADDR);
  Wire.write(Accelero_First_data_addr | 0x80);
  Wire.endTransmission();

  Wire.requestFrom(LSM303_ADDR, 6);
  if (Wire.available() <= 6) {
    AccRaw_X_axis_value = (Wire.read()) | (Wire.read() << 8);
    AccRaw_Y_axis_value = (Wire.read()) | (Wire.read() << 8);
    AccRaw_Z_axis_value = (Wire.read()) | (Wire.read() << 8);

    float X_Acc =  (AccRaw_X_axis_value >> 4);
    float Y_Acc =  (AccRaw_Y_axis_value >> 4);
    float Z_Acc =  (AccRaw_Z_axis_value >> 4);

    //calibrate offset
    float X_acc_offset_corrected = X_Acc + 6.676443;
    float Y_acc_offset_corrected = Y_Acc - 6.622381;
    float Z_acc_offset_corrected = Z_Acc + 55.408804;

    //calibrate
    float X_acc_calibrated = 0.977273 * X_acc_offset_corrected - 0.003458 * Y_acc_offset_corrected + 0.012639 * Z_acc_offset_corrected;
    float Y_acc_calibrated = -0.003458 * X_acc_offset_corrected + 0.979674 * Y_acc_offset_corrected - 0.001130 * Z_acc_offset_corrected;
    float Z_acc_calibrated = 0.012639 * X_acc_offset_corrected - 0.001130 * Y_acc_offset_corrected + 0.897083 * Z_acc_offset_corrected;
    //normalize
    norm_a = sqrt(sq(X_acc_calibrated) + sq(Y_acc_calibrated) + sq(Z_acc_calibrated));
    Xa_norm = X_acc_calibrated / norm_a;
    Ya_norm = Y_acc_calibrated / norm_a;
    Za_norm = Z_acc_calibrated / norm_a;

    //calculate pitch and roll
    /*
      pitch = asin(-Xa_norm) * 180 / PI;
      roll = asin(Ya_norm / cos(pitch * PI / 180)) * 180 / PI;
    */
    roll = atan2(Ya_norm, Za_norm);
    float  Gz2 = Ya_norm * sin(roll) + Za_norm * cos(roll);
    pitch = atan(-Xa_norm / Gz2);
    float By2 = Zm_norm * sin(roll) - Ym_norm * cos(roll);
    float Bz2 = Ym_norm * sin(roll) + Zm_norm * cos(roll);
    float Bx3 = Xm_norm * cos(pitch) + Bz2 * sin(pitch);
    float yaw = (atan2(By2, Bx3)*180)/PI;
    if (yaw < 0) {
      yaw = 360 + yaw;
    }

    float tilt = atan2(sqrt((sq(Xa_norm)+(sq(Ya_norm)))),Za_norm);

    //calculate vectors fo tilt compensation
    float Xh = Xm_norm * cos(pitch) + Zm_norm * sin(pitch);
    float Yh = Xm_norm * sin(roll ) * sin(pitch) + Ym_norm * cos(roll) - Zm_norm * sin(roll) * cos(pitch);

        // calculate tilt compensated heading
        float Heading = ((atan2(Yh, Xh)) * 180.0 ) / PI;
        if (Heading < 0) {
          Heading = 360 + Heading;
        }

    Serial.print("Pitch \t");
    Serial.print(pitch * 180 / PI);
    Serial.print("\t roll \t");
    Serial.print(roll * 180 / PI);
    Serial.print("\t tilt \t");
    Serial.print(tilt*180/PI);
    Serial.print("\t");
    Serial.println(Heading);
    delay(500);
  }
}
```


body:
I was programming my ATTiny84 when it randomly stopped being able to be programmed.
I have an external 32768 Hz crystal connected to it, and I have been using my Arduino UNO with the ArduinoISP sketch to program it. The following command was working at least once before, but isn't anymore:

```
C:\Users\Anubhav\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/bin/avrdude -CC:\Users\Anubhav\Documents\ArduinoData\packages\arduino\tools\avrdude\6.3.0-arduino17/etc/avrdude.conf -v -pattiny84 -cstk500v1 -PCOM3 -b19200 -Uflash:w:C:\Users\Anubhav\AppData\Local\Temp\arduino_build_256583/watch.ino.hex:i -U lfuse:w:0xe6:m -U hfuse:w:0xdf:m -U efuse:w:0xff:m
```

I tried with ```-B 5``` as well but that didn't seem to help either. The problems seems to be that it's always reading the fuses as 0x000000. This is my output:

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

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

             Using Port                    : COM3
             Using Programmer              : stk500v1
             Overriding Baud Rate          : 19200
             AVR Part                      : ATtiny84
             Chip Erase delay              : 4500 us
             PAGEL                         : P00
             BS2                           : P00
             RESET disposition             : possible i/o
             RETRY pulse                   : SCK
             serial program mode           : yes
             parallel program mode         : yes
             Timeout                       : 200
             StabDelay                     : 100
             CmdexeDelay                   : 25
             SyncLoops                     : 32
             ByteDelay                     : 0
             PollIndex                     : 3
             PollValue                     : 0x53
             Memory Detail                 :

                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               eeprom        65     6     4    0 no        512    4      0  4000  4500 0xff 0xff
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               flash         65     6    32    0 yes      8192   64    128  4500  4500 0xff 0xff
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00

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

avrdude.exe: PAGEL and BS2 signals not defined in the configuration file for part ATtiny84, using dummy values
avrdude.exe: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.05s

avrdude.exe: Device signature = 0x000000 (retrying)

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

avrdude.exe: Device signature = 0x000000 (retrying)

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

avrdude.exe: Device signature = 0x000000
avrdude.exe: Yikes!  Invalid device signature.
             Double check connections and try again, or use -F to override
             this check.

avrdude.exe done.  Thank you.
```

How do I fix the ```Yikes!  Invalid device signature.``` error and why is it occurring?

title: ATTiny84 fuses reading as 0

Answers: 1

body:
As noted in question, the 32kHz crystal is used as a clock source and also at least the first programming was working.

The ArduinoISP sketch has hardcoded ISP clock speed and ISP clock has to be at most 1/4 of MCU speed. So the ArduinoISP sketch `SPI_CLOCK` has to be set to the much lower value than default 166kHz, which is way too fast for 32kHz MCU clock. The safe value is about `5000` (5kHz)

    #define SPI_CLOCK 5000   // (1000000/6)

There is also baud_rate settings for the avrdude, but it's just communication speed between computer and ArduinoISP programmer and changing it won't change `SPI_CLOCK` (which is ISP clock).


body:
I am using the ATMega32u4 to generate multiple pulses at 2.5 kHz. I am using Timer 3, which is a 16-bit timer and using a prescaler of 1, so I have a 0.0625uS resolution. I want to generate pulses with pretty high accuracy and consistency. I have my previous post [here][1], which gave me accuracy. But when I look at the pulse with my oscilloscope it has some jitter. [Youtube Video of Jitter][2].

My final goal is to create a pulse on multiple different pins in this configuration.
[![enter image description here][3]][3]

What I am **assuming** is that the reason there is jitter is that there are other interrupts going on in the background, that could be shifting when the pulse stops and starts by a few microseconds. Looking through the datasheet, I found this, which seems to show interrupt priority.
[![enter image description here][4]][4]

It seems that my TIMER3 COMPA and COMPB are very low down the list of priorities, is there a way to change this priority list? Or is there something else that is causing the jitter?

I have posted my code below:

[1]: https://arduino.stackexchange.com/questions/75628/timer-accuracy-always-off-by-1us
  [2]: https://youtu.be/YRgCiZAUc9M
  [3]: https://i.stack.imgur.com/fHB5J.png
  [4]: https://i.stack.imgur.com/WgJb5.png

``` #define pin1 4
#define pin2 12
#define pin3 6
#define pin4 8

#define REFRESH 6400

int PULSEIndex;

class Pulse {
  public:
    int pulseLength;
    void Begin(byte GPIO_PIN) {
      pinMode(GPIO_PIN, OUTPUT);
    }
    void writeMicro(double pulse) {
      pulseLength = (pulse * 16);
    }
};

Pulse PULSE1;
Pulse PULSE2;
Pulse PULSE3;
Pulse PULSE4;

void setup() {
  PULSE1.Begin(pin1);
  PULSE2.Begin(pin2);
  PULSE3.Begin(pin3);
  PULSE4.Begin(pin4);

  // Reset Timer 3 Control Register to 0
  TCCR3A = 0;
  TCCR3B = 0;

  // Set CTC Mode
  TCCR3B &= ~(1 << WGM33); //0
  TCCR3B |= (1 << WGM32);  //1

  // Set prescaler to 1
  TCCR3B &= ~(1 << CS32); //0
  TCCR3B &= ~(1 << CS31); //0
  TCCR3B |= (1 << CS30);  //1

  //Reset Timer 3 and set compare value
  TCNT3 = 0;

  // Enable Timer 3 compare interrupt A and B
  TIMSK3 |= (1 << OCIE3B);
  TIMSK3 |= (1 << OCIE3A);

  //Enable global interrupts
  sei();

  //Set Refresh Rate
  OCR3A = REFRESH;
  OCR3B = 1000;
}

void loop() {
  PULSE1.writeMicro(40);
  PULSE2.writeMicro(40);
  PULSE3.writeMicro(40);
  PULSE4.writeMicro(40);
  delay(2);
}

ISR(TIMER3_COMPA_vect) {
  digitalWrite(pin1, HIGH);
  OCR3B = PULSE1.pulseLength;
}

ISR(TIMER3_COMPB_vect) {

  if (PULSEIndex == 1) {
    digitalWrite(pin1, LOW);
    digitalWrite(pin2, HIGH);
    OCR3B += PULSE2.pulseLength;
  }

  if (PULSEIndex == 2) {
    digitalWrite(pin2, LOW);
    digitalWrite(pin3, HIGH);
    OCR3B += PULSE3.pulseLength;
  }

  if (PULSEIndex == 3) {
    digitalWrite(pin3, LOW);
    digitalWrite(pin4, HIGH);
    OCR3B += PULSE4.pulseLength;
  }

  if (PULSEIndex == 4) {
    digitalWrite(pin4, LOW);
  }

  PULSEIndex++;
  if (PULSEIndex > 4) PULSEIndex = 1;
} ```

title: Arduino Timer Precision

Answers: 1

body:
> What I am **assuming** is that the reason there is jitter is that
> there are other interrupts going on in the background

This seems like a reasonable assumption. Since you are not doing serial
communication, the Timer 0 interrupt is likely the only one triggering
in the background. You can disable it with:

```c++
TIMSK0 = 0;
```

but then all the Arduino timing functions will stop working. You will
have to `#include <util/delay.h>` and replace `delay()` with
`_delay_ms()`. Note that this avr-libc function only works with
compile-time constant delays. On the other hand, it is cycle-accurate
and accepts floating point delays.

> is there a way to change this priority list?

There is not, and even if this was possible, it would not be that
useful. Interrupts in the Arduino are not interruptible: if a
low-priority interrupt is running when a high-priority one triggers, the
high-priority interrupt has to wait for the currently running one to
terminate. Priorities are only relevant when the processor is about to
serve an interrupt request but has to decide which one, among several
pending requests, it will serve first.

Now, a small remark about this:

```c++
void loop() {
  PULSE1.writeMicro(40);
  PULSE2.writeMicro(40);
  PULSE3.writeMicro(40);
  PULSE4.writeMicro(40);
  delay(2);
}
```

There is no point in rewriting those values over and over again. If you
plan to change the code in order to make those widths non-constant, then
you have to take care to:

1. make the `pulseLength` properties (or the whole `Pulse` objects)
   volatile
2. within `writeMicro()`, disable interrupts while changing
   `pulseLength`.


body:
I'm using a MacBook Pro Mojave 10.14.6 to code genuine Arduinos. Been working with multiple Uno R3s, no issue. Got a genuine Nano and get the following error: ser_open(): can't open device "/dev/cu.usbmodem14201": No such file or directory

The USB cable I'm using works fine with a cheap Chinese Uno clone, so there are data pins in the cable.

I followed instructions to delete the kext file, rebooted, installed CH341SER_MAC file and rebooted. Still getting the error message. I notice that others have asked this question; where are the answers? Thanks in advance.

title: Macbook Pro CH340 Nano 14201 error

Answers: 1

body:
Timekeeping isn't exact with any of the boards, though .05% - just over 7 minutes/day - doesn't sound like too high an expectation.

Restarting when you connect it to your computer is by design and doesn't indicate a fault. Opening the IDE's terminal or connecting another terminal program to a connected and running Arduino will - and is supposed to - reset it. Here is a forum discussion on [how to disable the auto-reset function][1] (Uno-specific) if you want to. Note that it involves modifying the board.

It's quite possible that this one board has a fault, though it still could be the cable. A couple of swaps should confirm it one way or the other.

I'm still not clear on where the error message,

> ser_open(): can't open device "/dev/cu.usbmodem14201"

came from, but I'm guess it's from AVRdude, the uploader application on your Mac, and still I'm wondering if the correct port is selected in the IDE's Tools | Port menu? For some reason, a USB device called "cu.usbmodem14201" is expected but not found. Since neither the Mac nor the IDE inherently knows this name - a USB device announces its name when you connect it - could this selection be left over from having previously used the genuine Arduino? Another reason to check the Ports menu. Also note that the Ports menu doesn't update its list spontaneously - only when you open it (and maybe only when you open the top-level, Tools, menu; I don't remember exactly).

Update:

>  The regular Arduino at 0.5% is pretty crude, I'd pay more for a more
> accurate crystal, but I was able to develop a sketch that adjusts for
> the Arduino's inaccuracy.

You could try putting the Arduino in an "oven" - and I emphasize the quotes. This is not a heating chamber per-se but a temperature controlled chamber. If you're getting good results by adjusting the count, adding the oven should get you even better results, especially as the seasons change and if that makes enough difference where you are.

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


body:
I'm working on a home automation project to control my [Sommer Base+][1] garage door opener through [Home Assistant][2].

The project consists of a WeMos D1 Mini with two reed switches (to detect door open/closed) and a 5V relay to control the door opener.

When the door is open the 'top / open' switch is triggered, giving a status of open. Likewise when the door is closed, the 'bottom / closed' switch is triggered, giving a status of closed. When neither switch is triggered (i.e. when the door is in motion), the status is either opening or closing, depending on the previous status.

[![enter image description here][3]][3]

This works fine unless the WeMos is powered up while either reed switch is closed (so if the door is open or closed).

[I know this is because `D3` and `D8` GPIO pins][4] for the open/close sensors and those can put the device into boot mode (I think that's what it's called).

What I want to know is which pins are the best to use for this project.

Is it possible for me to just change to pins `??` and `??` without needing to update my code?
Is it possible that the WeMos D1 Mini isn't a good fit for what I want?

  [1]: https://www.sommer.eu/en-GB/pro-base.html
  [2]: https://home-assistant.io
  [3]: https://i.stack.imgur.com/6AgId.png
  [4]: https://randomnerdtutorials.com/esp8266-pinout-reference-gpios/

title: What are the best GPIO pins to use for my project?

Answers: 1

body:
**NodeMCU and "Wemos D1 R2 and Mini" esp8266 (esp-12) pins and io overview**

----------

**Serial**

RX io3 RX0

TX io1 TX0

----------

**boot config pins** with pullup or pulldown on board

D3 io0 PULLUP (LOW for boot to flashing mode)

D4 io2 TX1 PULLUP (Serial1 TX. no RX for Serial1)

D8 io15 PULLDOWN (SS pin if esp8266 is SPI slave); TX if Serial.swap()

----------

**untroubled GPIOs** with optional function for I2C or SPI bus:

D1 io5 default pin for I2C SCL

D2 io4 default pin for I2C SCA

D5 io14 SPI CLK

D6 io12 SPI MISO

D7 io13 SPI MOSI; RX if Serial.swap()

----------

**RTC pin** for timed deep sleep wake-up (if connected to reset pin)

D0 io16 - optional internal pulldown, internal pullup not available

----------
**not useable**: on NodeMcu S*x* pins io 6 to io 11 connect QIO SPI flash memory
(in a very special setup the SPI bus can be used with other SPI device)
(in other very special setup the QIO pins can be used as gpio)

*note: most digital IO start as INPUT_PULLUP*


body:
Is it possible for a function/method to know if a constant array that has been passed in is in flash or RAM?

If I have a method or function that receives a constant array that is in RAM, the array is declared like this:  ```const uint8_t MY_ARRAY[] = { 1, 2, 3, 4 };```

gets passed into a method or function like this:  ```MyFunction(MY_ARRAY);```

and the method or function can handle it like this:

```
void MyFunction(const uint8_t *MY_ARRAY) {
     uint8_t secondElement = MY_ARRAY[1];
     ...
```

However, if the array is in Flash (because it's a constant array, so that's where it should go), then the declaration adds PROGMEM:   ```const uint8_t PROGMEM MY_ARRAY[] = { 1, 2, 3, 4 };```

The pass looks the same:  ```MyFunction(MY_ARRAY);```

And the function declaration looks the same but it needs to use pgm_read_byte_near to get the correct values back:
```
void MyFunction(const uint8_t *MY_ARRAY) {
     uint8_t secondElement = pgm_read_byte_near(MY_ARRAY+1);
     ...
```

How can the receiving method know if the array is in flash (PROGMEM) or RAM (no PROGMEM) so it knows to use pgm_read_byte_near or not?  Ideally I'd like a compiler error, but the type is the same (both are const arrays of uint8_t).

If pgm_read_byte_near is used when it shouldn't be, or it's not used when it should be, the results are garbage.

Some relevant questions:
[How to pass a static const (progmem) array to a function][1]

[RAM usage question: PROGMEM vs const vs #define][2]

[Storing array in PROGMEM][3]

[PROGMEM: do I have to copy data from flash to RAM for reading?][4]

UPDATE:
It looks like what I want to do is not possible.  The responses below are very interesting options though:  using __flash in plain C, using OOP to make PROGMEM and non-PROGMEM data holders or trying to (somehow?) use non-deprecated progmem specific data types from avr/gpmspace.h.

The best answer to my original question is that the method can not make this determination.  The best solution, from a comment by Delta_G, is to create regular (ram) and "_P" (flash/ progmem) versions of the functions and to be as obvious as possible in the naming of those functions.

  [1]: https://arduino.stackexchange.com/questions/25680/how-to-pass-a-static-const-progmem-array-to-a-function
  [2]: https://forum.arduino.cc/index.php?topic=79436.0
  [3]: https://arduino.stackexchange.com/questions/16012/storing-array-in-progmem
  [4]: https://arduino.stackexchange.com/questions/4572/progmem-do-i-have-to-copy-data-from-flash-to-ram-for-reading

title: How can a function/method determine if a const array passed in is PROGMEM (flash) or not (RAM)?

Answers: 4

body:
I am afraid there is no good solution to this problem. One option I do
like is to use the `__flash` qualifier instead of `PROGMEM`:

```c
const uint8_t ram_array[] = { 1, 2, 3, 4 };
__flash const uint8_t flash_array[] = { 5, 6, 7, 8 };

void function_reading_ram(const uint8_t *array)
{
    uint8_t secondElement = array[1];
    // ...
}

void function_reading_flash(__flash const uint8_t *array)
{
    uint8_t secondElement = array[1];
    // ...
}

int main(void)
{
    function_reading_ram(ram_array);      // OK
    function_reading_flash(flash_array);  // OK
    function_reading_ram(flash_array);    // Warning
    function_reading_flash(ram_array);    // Warning
}
```

Note that, with `__flash`, you don't need `pgm_read_byte_near()` or
anything similar. You just use the array like you would use any regular
array, and the compiler is smart enough to generate the code required to
access the Flash memory.

The warnings generated by gcc are:

```text
warning: conversion from address space ‘__flash’ to address space ‘generic’ [-Waddr-space-convert]
     function_reading_ram(flash_array);
     ^
warning: conversion from address space ‘generic’ to address space ‘__flash’ [-Waddr-space-convert]
     function_reading_flash(ram_array);
     ^
```

Given how nice this solution is, you may wonder why I wrote “there is no
good solution”. Well, this comes with two caveats, one small and one
huge. The small caveat is that you need to explicitly pass the option
`-Waddr-space-convert` to the compiler if you want it to generate the warnings.
It is not implied even with
`-Wall -Wextra`. The huge caveat is that _this only works in plain C_.
If you try to use this trick in C++ you get:

```text
error: ‘__flash’ does not name a type
```

This is an implementation of the “named address spaces” extension to the
standard C. Since nothing like this is standardized in C++, the authors
of gcc assumed it would not be useful to users of C++. :-( You can mix C
and C++ sources in Arduino, but you can't call class methods from C.

body:
There is also an OO solution possible, using the strategy design pattern, but this comes with some (slight) memory and performance penalties. You need to use C++ for this.

- Put each array you want to differ between flash/SRAM in a separate class (one per type). You get data hiding and possible separation of concerns for free.
- Instead of putting the array in each class, put a reference/pointer or use it directly.
- You can use inheritance:
  - Create a Flash Array class with a SRAM array reader/writer
  - Create an SRAM Array class with a Flash array reader/writer
  - Inherit each of the array types you use from one of these classes where the base class takes care of reading/writing.
- Alternative solution: use the strategy pattern; involves a bit more work, but you can prevent multiple inheritance (although since you use C now, you don't use inheritance (yet)). This would involve roughly:
  - Create a Flash and SRAM Array class reader as above.
  - Instead of inheritance, create a pointer to one of these classes which suits the type of the array.

Although I can imagine this will mean quite some changes in your sketch.

**Explanation using Inheritance**

(requested by comment)

@Casey I assume you mean the Inheritance way. Assume in a class you have `x_array` which is of type `FlashArray`. You just call `x_array.Read(...)`. This method is implemented in `FlashArray`, but also with the same parameters in `RamArray`. You can enforce this by inheriting both `FlashArray` and `RamArray` by a base class (e.g. `ArduinoArray` and create a (pure) virtual function `Read` with the same arguments. Anyway, the implementation of `Read` method in `FlashArray` should read from Flash and the same method in `RamArray` should read from RAM.

When you change the type of `x_array` from `FlashArray` to `RamArray` or vice versa, you don't need to change anything (except the types). To make this easier consider defining a type for `x_array`, so when you later need to change it, you only need to do this in one location.

body:
The classic avr-gcc way is to have dedicated functions with different names

e.g. `void* memcpy(void* dest, const void* src, size_t n);`  // Only works if src is RAM

vs. `void* memcpy_P(void *dest, PGM_VOID_P src, size_t n);` // Only works if src is PROGMEM

BTW: That's mentioned in a comment to the question already by @Delta_G. More about the example memcpy_P [here][1]

  [1]: https://stackoverflow.com/questions/14365462/memcpy-p-function-avr

body:
I will expand on KIIV's comment here.

This is a known issue to the people who wrote the Arduino framework. Essentially, the pointers to PROGMEM and RAM are both data pointers (think of a pointer like an array index, but for the entire RAM/Flash itself rather than one chunk of it that you manage) of the same size and type. They cannot be told apart since pointer types are only determined by the size of the data, not where the data is.

So, they used a clever solution: Make the pointer into a _different_ pointer that _isn't_ compatible with the regular RAM pointer. This is done by casting to the __FlashStringHelper class (and then casting back when it must be read). The FSH class doesn't actually have any methods or do anything; it's simply used to define a custom pointer type that is different from the normal const *.

You can directly go read one of the better guides I've seen on it [here][1] (Note that it's for the ESP8266, but this part works the same), or I can try to explain it. I suggest reading it anyway, since it has a lot of other info that's useful but not relevant to this question. Do note that they have a few examples near the end which don't de-allocate memory when they are done using it, though, so copying them directly could cause a memory leak (see my string processing example to see the proper method).

First, you need to cast the array to the FSH class:
```
const byte MyProgmemArray[] PROGMEM = {4,4,4,4,4,4,4,4}; //Fixes issue #82 (add randomness); see https://xkcd.com/221/ for details :D
__FlashStringHelper * MyArray = (__FlashStringHelper *) MyProgmemArray;
```
I am unaware if there is any method (and I did look) to declare these in-place, i.e. to make the original array declaration into a __FlashStringHelper * directly. So you still need, as the programmer/user, to know which strings are in flash when you add them, and add the conversion line. This means that what you wanted (fully automatic RAM/Flash detection) isn't *quite* possible, but this is as close as I think it gets. A further warning is that the original array still exists, meaning that it could accidentally be used instead (will still cause the original mismatch issue) and the new definition takes up *slightly* more memory for the additional pointer (if the compiler does not optimize it out?).

Oddly, it works fine if your want to store a string:
```
__FlashStringHelper * MyString = PSTR("yaddayaddayadda...");
```
Strings *can* be inlined, but I think it's because of both the PSTR macro _and_ because string definitions might be treated differently than an array of values (even though they are physically the same thing). Perhaps you could experiment with however PSTR works (it's actually a macro that does something, and isn't just a keyword) and see if you can implement this in your own code after all.

---

Now, you still need to get the data OUT of the array in that function you mentioned. To do that, we actually use two versions of that function. This is called overloading (and I think it's C++ only, but this is Arduino, which is by definition C++, so it's safe).

The RAM function you declare as normal:
```
void MyFunction(const uint8_t *MY_ARRAY){
  byte index_two = MY_ARRAY[1];
  ...
}
```
The PROGMEM function you declare as follows (assuming that pgm_read_byte_near IS the right function. Also note that it gets more complicated if you need multi-byte values, like `int` or something...):
```
void MyFunction(__FlashStringHelper *MY_PROGMEM_ARRAY){
  const byte *MY_ARRAY = (const byte *)MY_PROGMEM_ARRAY; //convert back to normal
  byte index_two = pgm_read_byte_near(MY_ARRAY+1); //still have to read it as flash, of course
  ...
}
```

---

As a bonus bit of info that is **unrelated** to the question *as asked*, but that may interest you/be relevant later:

There are a few more notes if you use this for string data (or pretend it's a string for this part, which works if your data contains no zeros and ends in one). By the latter, I refer to the fact that strings in C (NOT the C++ `std::string` or Arduino `String`, though, so keep this in mind) are basically char arrays with a 0 tacked on the end. All string-processing functions run an infinite loop until they read a 0 at their current index, which allows them to work with strings of any length but still know when they are done. As a result, when reading it, you can treat your data like a string, with three caveats:

 1. It can never contain a 0, except for the very last item, which won't be read.
 2. When defining it, you'd need to still use {} instead of "" since most values don't have printable ASCII characters. (And even so, you'd have to write `" "` for 32, for instance.)
 3. You can't actually print the alleged string, since the data won't actually contain printable characters. You'll get any mix of numbers, letters, punctuation, and fun things like backspace and newline all jumbled together. You would need to read each character and convert it (via, say, `String num = <your value here>;` or `itoa()` etc).

If you want to print it using an existing Arduino function, like Serial.print, and it is *actually* a string (and not data pretending to be a string), it will natively support __FlashStringHelper *, so you don't need the conversion step (this lets you do `Serial.print(F("No static RAM used here!"));` and similar).

There are two ways to read the data if it is for your own string-processing function, however. The first, the simple one, is not memory efficient and creates a full copy of the data or string in RAM while it's being used. As a result, it is not capable of processing strings that are too large for RAM and may have issues if it's called while a lot of RAM is already in use or it is called deep down a set of nested functions. It is very convenient, however:
```
//convert from __FlashStringHelper * as above, but let's assume it's a char* here
int size = strlen_P(MY_ARRAY);
if (size!=0){
  char * data = new char[size];
  if (data!=NULL){
    strcpy_P(data,MY_ARRAY);
    //do stuff with the string
    delete data;
  }
}
```
The second method is more annoying to actually do, and requires more control over how the data is processed, but you can also read out the data byte-by-byte as shown in my first decoding example above using pgm_read_byte_near. This lets you work with data that is too large to fit in RAM and keeps a constant stack size too. The downside is that it requires that you are actually able to stream the data byte-by-byte in all places that it's then used (or that you re-read it when it needs to be accessed out-of-order).

  [1]: https://arduino-esp8266.readthedocs.io/en/latest/PROGMEM.html


body:
I have set up a 433 MHz transmitter and receiver pair on one Arduino Uno board. Using the RCSwitch library, I could successfully send and receive signals. Using the Radiohead library however, I could only send and got no reception. I am curious why and grateful for any help.

Here is the sketch. Both receiver and transmitter draw power from Arduino 5V and GND. The DATA pin of transmitter is attached to pin 12 of Arduino. The DATA pin of receiver is attached to pin 11. These appear to be "hard-coded" in the Radiohead library. My reciever has an additional chip select (CS) pin which I have wired to pin 10.

Using the serial monitor, it looks like transmitter and receiver are initialized without problem and message is sent. I have used the RCSwitch library with transmitter and receiver on the same board and that worked, (i.e. messages sent were received correctly) so I am curious why the issue with Radiohead.

```
// Include RadioHead Amplitude Shift Keying Library
#include <RH_ASK.h>
// Include dependent SPI Library
#include <SPI.h>

// Create Amplitude Shift Keying Object
RH_ASK rf_receiver;
RH_ASK rf_transmitter;

void setup()
{
    // Initialize ASK Object
    if (!rf_receiver.init())
        Serial.println("Failed to initialize receiver.");
    if (!rf_transmitter.init())
        Serial.println("Failed to initialize transmitter.");

    Serial.begin(9600);

    digitalWrite(10, HIGH);   // enable CS on some receiver devices
}

void loop()
{
    const char *msg = "Hello world!";
    rf_transmitter.send((uint8_t *)msg, strlen(msg));
    rf_transmitter.waitPacketSent();
    Serial.print("Message sent: ");
    Serial.println((char*)msg);

    uint8_t buf[12];
    uint8_t buflen = sizeof(buf);

    if (rf_receiver.recv(buf, &buflen))
    {
      Serial.print("Message received: ");
      Serial.println((char*)buf);
    }
    else
    {
      Serial.print("No message rec'd: ");
      Serial.println(*&buflen);
      Serial.println((char*)buf);
    }

    delay(1000);
}
```

title: Setting up 433 MHz Transmitter and Receiver in the same Arduino sketch using Radiohead

Answers: 1

body:
The answer can be found in the source code 0f RH_ASK.h (you should read the well made documentation before using this library):

> At present only one instance of RH_ASK per sketch is supported.

So you will have to write such an extension yourself, use two Arduinos or use another lib for testing.


body:
I am interfacing the HTU21D sensor with my nodeMCU v3. All good! I managed to get some readings etc. But when I re-upload my code the device does not respond. If I remove the power supply from the pin and hard reset it, it works again. I have exactly the same problem using the Sparkfun library, so it seems more of a hardware problem. Anyone else had the same problem?
link to the sparkfun library
<https://github.com/sparkfun/SparkFun_HTU21D_Breakout_Arduino_Library>
for reference, here is my code

```/*
   This program interfaces the HTU21 temp/humidity sensor via I2C
*/

#include <Wire.h>
#include <Math.h>

const int HTU21_ADDR = 0x40;
const int Trigger_Temp_Measurement = 0xE3;// hold master
const int Trigger_Hum_Measurement = 0xE5; // hold master
const int Trigger_Temp = 0xF3; //No Hold Master
const int Trigger_Hum = 0xF5; //No Hold Master

int16_t Temp, Hum;//variables to store temp and humidity
int8_t TmpCrc, HumCrC;

void setup() {// put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();
  Wire.beginTransmission(HTU21_ADDR);
  Wire.write(0xFE);
  Wire.endTransmission(true);

}

void loop() {// put your main code here, to run repeatedly:
  TempReading();
  HumReading();

}

void TempReading() {

  Wire.beginTransmission(HTU21_ADDR);
  Wire.write(Trigger_Temp_Measurement);
  Wire.endTransmission();

  Wire.requestFrom(HTU21_ADDR, 3, true);
  if (Wire.available() <= 3) {
    Temp = (Wire.read() << 8) | (Wire.read() );
    TmpCrc = Wire.read();
  }
  float TempCalc = -46.85 + (175.72 * ((float)Temp / (pow(2, 16))));
  Serial.print("Temperature \t");
  Serial.print(TempCalc);
  //Serial.println(TmpCrc, HEX);

}

void HumReading() {
  Wire.beginTransmission(HTU21_ADDR);
  Wire.write(Trigger_Hum_Measurement);
  Wire.endTransmission();

  Wire.requestFrom(HTU21_ADDR, 3, true);
  if (Wire.available() <= 3) {
    Hum = (Wire.read() << 8) | (Wire.read());
    HumCrC = Wire.read();
  }

  float HumCalc = -6 + 125 * (Hum / (pow(2, 16)));
  Serial.print("\t Humidity \t");
  Serial.println(HumCalc);
  //Serial.println(HumCrC, HEX);

}```

title: HTU21 on GY-21 breakout board I2C problem

Answers: 1

body:
Yes the setup runs completely. I found out that the bus hangs if I terminate communication by uploading new code to the board. I found a piece of code that releases the bus which works. See below:
```int I2C_ClearBus() {
#if defined(TWCR) && defined(TWEN)
  TWCR &= ~(_BV(TWEN)); //Disable the Atmel 2-Wire interface so we can control the SDA and SCL pins directly
#endif

  pinMode(SDA, INPUT_PULLUP); // Make SDA (data) and SCL (clock) pins Inputs with pullup.
  pinMode(SCL, INPUT_PULLUP);

  boolean SCL_LOW = (digitalRead(SCL) == LOW); // Check is SCL is Low.
  if (SCL_LOW) { //If it is held low Arduno cannot become the I2C master.
    return 1; //I2C bus error. Could not clear SCL clock line held low
  }

  boolean SDA_LOW = (digitalRead(SDA) == LOW);  // vi. Check SDA input.
  int clockCount = 20; // > 2x9 clock

  while (SDA_LOW && (clockCount > 0)) { //  vii. If SDA is Low,
    clockCount--;
    // Note: I2C bus is open collector so do NOT drive SCL or SDA high.
    pinMode(SCL, INPUT); // release SCL pullup so that when made output it will be LOW
    pinMode(SCL, OUTPUT); // then clock SCL Low
    delayMicroseconds(10); //  for >5uS
    pinMode(SCL, INPUT); // release SCL LOW
    pinMode(SCL, INPUT_PULLUP); // turn on pullup resistors again
    // do not force high as slave may be holding it low for clock stretching.
    delayMicroseconds(10); //  for >5uS
    // The >5uS is so that even the slowest I2C devices are handled.
    SCL_LOW = (digitalRead(SCL) == LOW); // Check if SCL is Low.
    int counter = 20;
    while (SCL_LOW && (counter > 0)) {  //  loop waiting for SCL to become High only wait 2sec.
      counter--;
      delay(100);
      SCL_LOW = (digitalRead(SCL) == LOW);
    }
    if (SCL_LOW) { // still low after 2 sec error
      return 2; // I2C bus error. Could not clear. SCL clock line held low by slave clock stretch for >2sec
    }
    SDA_LOW = (digitalRead(SDA) == LOW); //   and check SDA input again and loop
  }
  if (SDA_LOW) { // still low
    return 3; // I2C bus error. Could not clear. SDA data line held low
  }

  // else pull SDA line low for Start or Repeated Start
  pinMode(SDA, INPUT); // remove pullup.
  pinMode(SDA, OUTPUT);  // and then make it LOW i.e. send an I2C Start or Repeated start control.
  // When there is only one I2C master a Start or Repeat Start has the same function as a Stop and clears the bus.
  /// A Repeat Start is a Start occurring after a Start with no intervening Stop.
  delayMicroseconds(10); // wait >5uS
  pinMode(SDA, INPUT); // remove output low
  pinMode(SDA, INPUT_PULLUP); // and make SDA high i.e. send I2C STOP control.
  delayMicroseconds(10); // x. wait >5uS
  pinMode(SDA, INPUT); // and reset pins as tri-state inputs which is the default state on reset
  pinMode(SCL, INPUT);
  return 0; // all ok
}
```
Thanks for pointing me in the right direction!


body:
I am in need of 12VDC from my Wemos D1 R2. How do I configure the Vin pin to output the max (I think its 12VDC)?

board: Wemos D1 R2 V2.1.0 - ESP8266 (LOLIN D1 R2)

Pinout [here][1] in pictures below

  [1]: https://protosupplies.com/product/esp8266-d1-r2-wifi-processor-with-uno-footprint/

title: How do I configure WEMOS D1 R2 Vin pin to output max voltage?

Answers: 2

body:
You cannot. You are misunderstanding, what that pin is. Vin means Voltage In. It's a voltage input, connected to a voltage regulator, which will regulate the provided voltage at that pin down to 3.3V for the Wemos to work with. It is **not** an output. The regulator cannot convert the 3.3V from the Wemos to 12V. That is not, what it is build for.

To get 12V you either need a separate 12V power source, or you need to buy a stepup/boost converter, which brings the 3.3V (or 5V, if you are powering from USB) up to 12V. For the latter, be sure, that the converter and the source, where you get the input voltage of the converter, can provide enough current for your use case.

body:
After looking into it and seeing all the previous answers, I noticed the Vin pin can be used as an output but only up to the input from the barrel connector.

When using a 9V input to the barrel jack, the voltage difference between the ground pin and Vin pin was just under 9V. Similarly, when measuring the voltage difference when using a 12V supply, the multimeter reported just under 12V.

This is in line with @StarCat comment.


body:
Given an Arduino Uno Wifi Rev2 with this small U-blox NINA wifi module.

All work great however after a long time (I can't be more exact but we talk here about weeks if not months), it suddenly disconnects.

This board is unattended, and the only way to recover is to reset the Arduino.

Here is my code:

    WiFiServer server(PORT);

    void setup() {
      connectToWifi();
      server.begin();
    }

    void connectToWifi() {
      // attempt to connect to Wifi network:
      while (status != WL_CONNECTED) {
        Serial.print("Attempting to connect to SSID: ");
        Serial.println(ssid);
        // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
        status = WiFi.begin(ssid, pass);
        if (status == WL_CONNECTED) break;

        // wait 10 seconds for connection:
        delay(10000);
      }
    }

    void loop() {
      // check WiFi status
      if (WL_CONNECTED != WiFi.status()) connectToWifi();

      WiFiClient client = server.available();
      if (client) {
        while (client.connected()) {
          if (client.available()) {
            char c = client.read();

            ... (other wifi-unrelated code)

            // close the connection:
            client.stop();
          }
        }
      }
    }

When it disconnects from wifi, the router's dhcp manager console shows it with "waiting" status.

Note: I'm the only client, and only one character is sent to the Arduino at once, then the socket is closed. It is very unlikely, that a client hangs, and the board is stuck in the while loop.

Is this a known problem, or I have to dig myself more into this?

Thank you!

title: Uno Wifi rev2 - after long time it disconnects

Answers: 1

body:
As you have not given the details there are some things to check

 - is your Nina-Firmware > 1.2.4
 - If not update to the latest 1.3.0 via the [WiFi101-FirmwareUpdater-Plugin 0.10.10](https://github.com/arduino-libraries/WiFi101-FirmwareUpdater-Plugin/tree/v0.10.10) is included in the ArduinoIDE 1.8.12 or greater
 - Disconnect before you reconnect (in case of router drop-outs) and
 - Close any connection before sending/receiving. This will free the socket on the Nina module. Stop the client after doing the stuff needed with   `client.stop();`
 - If there is any server connection code in setup this should be run in a reconnect routine (as you did not include setup) just as a hint
 - Make sure that after a certain period the `while (status != WL_CONNECTED)` and `while (client.connected())` are broken and error testing takes place e.g.<br> `if (status==WL_DISCONNECTED || status==WL_CONNECTION_LOST){.. do something to change that ..} `

 - If all fails implement a routine that checks the signal and restarts the sketch if the router has dropped out (for whatever reason).

Disconnect code:

    void connectToWifi() {
        // This new line is required to disconnect the previous connection otherwise
        // it will try to use the old connection and never reconnect if the connection fails
        status = WiFi.disconnect();

        // attempt to connect to Wifi network:
        while (status != WL_CONNECTED) {
        .... REST of your code ...
        }
    }

Hint (as you did not show setup) if you have something like

    client.connect(server, 80);

move it to the reconnection routine in the form of

    if (client.connect(server, 80)) {
        Serial.println("connecting...");
    .... REST of reconnect ...
    }

Restart code if wifi signal is lost

    void(* resetFunc) (void) = 0; // Declare reset function at address 0

    void loop() {
      if (WiFi.RSSI() == 0) // Checks if Wifi signal lost.
      { resetFunc(); // Calls Reset
      }
    // Rest of code goes here.
    }

This should altogether ensure a long and stable running client


body:
@Majenko says in the leading (19 Upvote) answer [here][1] not to use VIN and USB socket at the same time.

> You must never ever connect VIN to a power source and connect the USB socket. That can destroy the USB port in your computer. There is zero back-powering protection on [LoLin v3 board] board.

I need to do diagnostics on my Wemos (LOLIN) D1 R2 V2.1.0 while it's connected via 9-12V barrel jack and the Vin pin connected to an L9110H H-bridge as an output (bridge input).

Does the Wemos (LOLIN) D1 R2 V2.1.0 (ESP8266) work like this as well? Would I be able to run diagnosics with Serial through my USB socket while running this setup?

  [1]: https://arduino.stackexchange.com/questions/51873/nodemcu-vin-pin-as-5v-output

title: Vin pin vs USB vs Barrel connector: Wemos D1 R2

Answers: 1

body:
The D1 R2 uses the same power supply arrangement as the Arduino Uno (albeit with a better switching regulator for the 5V instead of the Arduino's basic linear regulator).

So it should be safe to use both the USB and the barrel jack at the same time.

The NodeMCU *doesn't include a 5V regulator* and doesn't have the power switching circuitry of the Uno / D1 R2, and thus is a completely different arrangement.


body:
I am using Arduino nano 33 Sense BLE in which I want GPS to run and display its location . The GPS module which I am using is Adafruit GPS. I want both Bluetooth and GPS to run synchronously. But only one of them shows output. I have tried Adafruit-GPS library with the Hardware Serial but it shows the GPS location not the Bluetooth working.
I also checked the code individually both are working well.I have used the example of **Adafruit-GPS library->GPS_HardwareSerial_Parsing** and **ArduinoBLE library->LED** , these codes both work individually well but when I have combined them and tried to make it run only the GPS shows its location the bluetooth seems to be not working.Below is the combined code:

    #include <Adafruit_GPS.h>
    #include <ArduinoBLE.h>

    // what's the name of the hardware serial port?
    #define GPSSerial Serial1
    // Connect to the GPS on the hardware port
    Adafruit_GPS GPS(&GPSSerial);
    // Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
    // Set to 'true' if you want to debug and listen to the raw GPS sentences
    #define GPSECHO false
    uint32_t timer = millis();

    BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // BLE LED Service
    // BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
    BLEByteCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
    const int ledPin = LED_BUILTIN; // pin to use for the LED

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

     // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
      GPS.begin(9600);
      GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
      GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate

      pinMode(ledPin, OUTPUT);
      BLE.setLocalName("LED");
      BLE.setAdvertisedService(ledService);
      // add the characteristic to the service
      ledService.addCharacteristic(switchCharacteristic);
      // add service
      BLE.addService(ledService);
      // set the initial value for the characeristic:
      switchCharacteristic.writeValue(0);
      // start advertising
      BLE.advertise();

      delay(1000);
    }

    void loop()
    {
      char c = GPS.read();

      BLEDevice central = BLE.central();

      if (GPS.newNMEAreceived()) {
       // Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false
        if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false
          return; // we can fail to parse a sentence in which case we should just wait for another
      }

     if (timer > millis()) timer = millis();

    //BLE code to connect to bluetooth

      // if a central is connected to peripheral:
      if (central) {
        Serial.print("Connected to central: ");
        // print the central's MAC address:
        Serial.println(central.address());
        // while the central is still connected to peripheral:
        while (central.connected()) {
          // if the remote device wrote to the characteristic,
          // use the value to control the LED:
          if (switchCharacteristic.written()) {
            if (switchCharacteristic.value()) {   // any value other than 0
              Serial.println("LED on");
              digitalWrite(ledPin, HIGH);         // will turn the LED on
            } else {                              // a 0 value
              Serial.println(F("LED off"));
              digitalWrite(ledPin, LOW);          // will turn the LED off
            }
          }
        }
        // when the central disconnects, print it out:
        Serial.print(F("Disconnected from central: "));
        Serial.println(central.address());
      }

    //GPS to print latitude and longitude
      // approximately every 5 seconds or so, print out the current stats
      if (millis() - timer > 5000) {
        timer = millis(); // reset the timer
        Serial.print("Fix: "); Serial.print((int)GPS.fix);
        Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
        if (GPS.fix) {
          Serial.print("Location: ");
          Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
          Serial.print(", ");
          Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
        }
      }

    }

title: Arduino Nano 33 BLE work with its Bluetooth and GPS synchronously?

Answers: 0


body:
[![The wiring][1]][1]

I am having some difficulties in trying to make my servo motor move to a specific angle based on the button pressed.

For example, having the motor start at 0 degrees and then having it move to 180 when the 3rd button is pressed, have it return to 0 degrees when the first button is pressed, and have it go to 90 degrees when the second button is pressed, etc, etc.

I can't tell if I am going about this all wrong or not with my code, so if anyone could provide some assistance with this it would be a great help

EDIT: Added the wiring as a just in case

```
#include <Servo.h>

Servo myservo;
int angle = 0;
int anglestep = 10;

#define FIRST 2 // pin 2 is connected to 1st floor button
#define SECOND 3 // pin 3 is connected to 2nd floor button
#define THIRD 4 // pin 4 is connected to 3rd floor button
#define SIGNAL 10

void setup()
{
Serial.begin(9600);
myservo.attach(10);
myservo.write(angle);
pinMode(2,INPUT_PULLUP);
pinMode(3,INPUT_PULLUP);
pinMode(4,INPUT_PULLUP);
Serial.println("Lift/Descend");
}

void loop()
{
while (digitalRead(FIRST) == LOW)
 {
 if (angle > 0 && angle <= 90) //2to1
  {
  angle = angle - anglestep;
   if (angle < 0)
   {
   angle = 0;
   }
   else
   {
   myservo.write(angle);
   Serial.print("Moved to: ");
   Serial.print(angle);
   Serial.println(" degree");
   }
  }
 else if (angle > 90 && angle <= 180) //3to1
 {
  angle = angle - anglestep;
   if (angle < 0)
   {
   angle = 0;
   }
   else
   {
   myservo.write(angle);
   Serial.print("Moved to: ");
   Serial.print(angle);
   Serial.println(" degree");
   }
    }
   else //1on1
 {
  angle = 0;
 }

}
while (digitalRead(SECOND) == LOW)
 {
 if (angle > 90 && angle <= 180) //3to2
  {
  angle = angle - anglestep;
  if (angle > 90)
   {
   angle = 90;
   }
  else
  {
  myservo.write(angle);
  Serial.print("Moved to: ");
  Serial.print(angle);
  Serial.println(" degree");
  }
 }
 else if (angle > 0 && angle < 90) //1to2
  {
  angle = angle + anglestep;
  if (angle < 90)
   {
   angle = 90;
   }
  else
  {
  myservo.write(angle);
  Serial.print("Moved to: ");
  Serial.print(angle);
  Serial.println(" degree");
  }
 }
 else
 {//2on2//
 angle = 90;
 }
}

while (digitalRead(THIRD) == LOW)
{
 if (angle > 0 && angle <= 90) //1to3
 {
  angle = angle + anglestep;
  if (angle > 180)
   {
   angle = 180;
   }
  else
  {
  myservo.write(angle);
  Serial.print("Moved to: ");
  Serial.print(angle);
  Serial.println(" degree");
  }
 }
 else if (angle > 90 && angle < 180)
 {//2to3
  angle = angle + anglestep;
  if (angle > 180)
   {
   angle = 180;
   }
  else
  {
  myservo.write(angle);
  Serial.print("Moved to: ");
  Serial.print(angle);
  Serial.println(" degree");
  }
 }
 else
  {
  angle = 180;
  }
 }
}
```

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

title: Trying to move servo motor via 3 buttons

Answers: 1

body:
You are really overthinking things there. A servo will move to an angle if you just give it the final angle to move to. You don't need to nudge it to the final angle by visiting every angle in between, and you don't need to know what angle it's at currently.

You can simply do:

```
if (digitalRead(FIRST) == LOW) {
    myservo.write(0);
}

if (digitalRead(SECOND) == LOW) {
    myservo.write(90);
}

if (digitalRead(THIRD) == LOW) {
    myservo.write(180);
}
```

However if you wanted to slow the movement down, which would entail moving the servo in smaller steps, I would separate out the current angle and positioning from the buttons, which would set a *desired* angle.  Something more like:

```
static uint8_t desiredAngle = 0;
static uint8_t currentAngle = 0;
static uint32_t timestamp = millis();

// Choose a new desired angle
if (digitalRead(FIRST) == LOW) {
    desiredAngle = 0;
}

if (digitalRead(SECOND) == LOW) {
    desiredAngle = 90;
}

if (digitalRead(THIRD) == LOW) {
    desiredAngle = 180;
}

// Every 10ms "tick" the servo towards the desired
// angle by 1 degree
if (millis() - timestamp >= 10) {
    timestamp = millis();
    if (desiredAngle > currentAngle) {
        currentAngle++;
        myservo.write(currentAngle);
    } else if (desiredAngle < currentAngle) {
        currentAngle--;
        myservo.write(currentAngle);
    }
}
```


body:
I have following code in loop() in NodeMCU.

This part is before setup():

    String serial_data_read = "";   // for incoming serial string data
    String serial_data = "";   // for incoming serial string data

This part is in loop():

    if ((last_weight_time < millis() - 1000)) {
       last_weight_time = millis();
       serial_data_read = "";
       Serial.print("P");
       while(Serial.available()) {
          character = Serial.read();
          serial_data_read.concat(character);
       }
       serial_data = serial_data_read;
    }

I don't understand C programming that much, but I think it has something to do with memory leaking and eventually running out of memory. It runs for around 20 minutes and then just stops. When I manually restart NodeMCU it runs again fine.

I would be very grateful for any help, how to rewrite my code so it doesn't leak memory. Thank you very much.

title: How to fix memory-leak code in ESP8266/NodeMCU caused by string concenation?

Answers: 3

body:
The short answer is, don't use the String class at all. You need to read up on using C strings (which are simply null-terminated arrays of characters. There are C library functions for manipulating C strings. <del>You'll want to avoid printf, scanf, and related functions, as the library that supports those is quite large</del>

The basic idea is to use statically allocated C strings as buffers. Figure out the largest number of characters you need to store, and create a static array of characters at least one character larger (for the terminating null) and use that to collect the output you are building.

body:
To write code that will not cause memory leak, you need to understand of where and what caused the memory leak first. The memory leak in this particular case is caused by the line

    serial_data_read.concat(character);

When you instantiate a String object with `String serial_data_read = ""`, Arduino String class create a memory allocation using dynamic memory allocation in the heap, and since your initialised it with "", it therefore create a minimum size of allocation. This is all good if you know how to the dynamic memory is created and how it going to be used.

The problem started when you start doing String concatenation with the line `serial_data_read.concat(character)`, the original allocation for your global variable `serial_data_read` is no longer have enough space for the concatenated variable, so it create a temporary variable in the heap and do the concatenation, and then eventually put the result back to this newly allocated memory for `serial_data_read` on the heap, leaving a hole at the heap for the original `serial_data_read` variable (and the temp variable).

What make this worst is that this is happening for <del>each iteration</del> every 16 iterations(see Edgar Bonet's comment below) of the while loop. Theoretically the old `serial_data_read` prior the concatenation should be free-up at some point (e.g. if your while loop is within a function, the part of the heap might be free-up at the exit of the function), it however does not necessary be the case because your newly created `serial_data_read` stay on top of piles of to-be-free-up memory that blocking the free up(think of a piece of cheese with a lot of holes on it), so the heap memory get less and less at each iteration.

**Short term fix - do not do String concatenation in a loop**

String class is not always evil if you know what's going on and how to use it. One of the quick fix for your problem is simply do not do String concatenation within a loop. And if you are using it within a function, keep it local. This will minimise the heap fragmentation.

    if ((last_weight_time < millis() - 1000)) {
       last_weight_time = millis();
       if (Serial.available() > 0) {
          String serial_data_read = Serial.readStringUntil('\n');
       }
    }

BTW, you can add `ESP.getFreeHeap()` in your loop() to check if there is still memory leak.

**Long term fix - Don't use String class**

For a better fix, and especially for some one new to the programming or C/C++, do not use String class and learn how to use ***c string and array***. Here is the version without using String class.

    length = 80;
    char buffer[length] = {0};
    if ((last_weight_time < millis() - 1000)) {
       last_weight_time = millis();
       while(Serial.available()) {
          Serial.readBytesUntil('\n', buffer, length);
       }
    }

**Other resources to learn about**

https://www.cplusplus.com/reference/cstring/ all the functions for c string and array manipulation to replace Arduino String class.

https://hackingmajenkoblog.wordpress.com/2016/02/04/the-evils-of-arduino-strings/

body: SafeString is a great way to go.. only one instance of each SafeString can ever exist, and u can declare the length of each SafeString..


body:
I am trying to build a unlocker on my hardlid for my ute. I have replaced the manual unlocking mechanism with 2 of these https://www.jaycar.com.au/slave-door-lock-actuator/p/LR8813.

Now my code below works sometimes and I cannot work out why. The way the code should work is

 1. Press Unlock Button (Count increments)
 2. Press Unlock Button again
 3. When count = 2 turn relay on for 4 seconds then turn off
 4. reset count to 0
 5. If time between presses is longer than 10 seconds reset count to 0

Basic diagram below. Please note the push button is actually wired to a relay which is triggered by the car unlock remote and the LED is the actuators.

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

This is my code

    int switchPin = 2; // choose the input pin (for a pushbutton)
    int relayPin = 4; // choose the input pin (for a pushbutton)
    int val = 0; // variable for reading the pin status
    int counter = 0;
    int currentState = 0;
    int previousState = 0;
    bool lockOn = false;

    unsigned long currentMillis = 0;
    unsigned long previousMillis = 0;

    unsigned long LockcurrentMillis = 0;
    unsigned long LockpreviousMillis = 0;

    const long interval = 10000;
    const long Lockinterval = 4000;

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

      pinMode(switchPin, INPUT); // declare pushbutton as input
      pinMode(relayPin, OUTPUT); // declare pushbutton as input

      Serial.println("Ready");
      Serial.print("IP address: ");

    }

    void loop() {

      currentMillis = millis();
      LockcurrentMillis = millis();
    /*
      Serial.print("Current ");
      Serial.print(currentMillis);
      Serial.print(" | Previous ");
      Serial.println(previousMillis);
     //Serial.println(lockOn);

      Serial.print("Lock Current ");
      Serial.print(LockcurrentMillis);
      Serial.print(" | Lock Previous ");
      Serial.println(LockpreviousMillis);
      */
      if (lockOn == true){

        if (LockcurrentMillis - LockpreviousMillis >= Lockinterval) {
          // save the last time you blinked the LED
          LockpreviousMillis = LockcurrentMillis;
          digitalWrite(relayPin, LOW); // turn relayPin off
          lockOn = false;
          Serial.println("relay off");
        }
      }

      val = digitalRead(switchPin); // read input value
      if (val == HIGH) { // check if the input is HIGH (button released)
        currentState = 1;
      }
      else {
        currentState = 0;
      }
      if (currentState != previousState) {
        if (currentState == 1) {
          counter = counter + 1;
          previousMillis = currentMillis;   //reset timer
          Serial.println(counter);
        }
      }
      if (counter == 2) {
        counter = 0;
        digitalWrite(relayPin, HIGH); // turn relayPin on
        //delay(4000);
        //digitalWrite(relayPin, LOW); // turn relayPin off
        lockOn = true;
              LockpreviousMillis = LockcurrentMillis;

        Serial.println("relay on");
      }

      previousState = currentState;
      //delay(250);
      if (currentMillis - previousMillis >= interval) {
        // save the last time you presse the button
        previousMillis = currentMillis;
        //LockpreviousMillis = LockcurrentMillis;
        //if (counter >= 1) {
        Serial.println("Took too long reset count");
        counter = 0;
        lockOn = false;
        //}
      }
    }

Any Help would be highly appreciated

Thanks

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

title: Arduino Hardlid Unlocker

Answers: 1

body:
Your circuit drawing seems very wrong, but it is not helpful since, as
you say, it doesn't represent the real circuit. Please, add a proper
diagram of the actual circuit.

As for your reliability problem, I did not dig into the logic of the
code you posted, but I suspect it may be caused by the lack of
[debouncing][]. You could add you own debouncing code but, for the sake
of simplicity, I suggest you instead use a ready-made library, like
[Bounce2][].

For the kind of program you are trying to write, I find that the logic
becomes way easier to grasp if you think think of it as a [finite state
machine][fsm]. This is program construct based on the idea that the
system can be in any of a predefined set of possible states, and that
its behavior and the possible state transitions depend on what
particular state it is in. In this specific case, I would use three
states:

 * In the `LOCKED` state, the lid is locked and you need to press the
   button twice in order to unlock it. Once you press the button once,
   it transitions to the `WAITING` state.
 * In the `WAITING` state, the lid is still locked, but the first
   button press has already been registered. If you press the button
   again, the system transitions to the `UNLOCKED` state. If not,
   after a timeout it transitions back to `LOCKED`.
 * In the `UNLOCKED` state the lid is unlocked. After another timeout it
   transitions back to the `LOCKED` state.

Once you have this logic written down, it can be translated into code in
a very straightforward way:

```c++
#include <Bounce2.h>

const uint8_t  switch_pin = 2;
const uint8_t  relay_pin  = 4;
const uint32_t wait_interval = 10000;  // 10 s
const uint32_t lock_interval =  4000;  //  4 s

Bounce button;

void setup() {
    button.attach(switch_pin, INPUT_PULLUP);
    pinMode(relay_pin, OUTPUT);
    Serial.begin(9600);
    Serial.println("Ready.");
}

void loop() {
    static enum { LOCKED, WAITING, UNLOCKED } state = LOCKED;
    static uint32_t last_change;  // not used in the LOCKED state

    button.update();
    uint32_t now = millis();
    switch (state) {
    case LOCKED:
        if (button.fell()) {
            Serial.println(F("Waiting for second button press."));
            state = WAITING;
            last_change = now;
        }
        break;
    case WAITING:
        if (button.fell()) {
            Serial.println(F("Unlocking."));
            digitalWrite(relay_pin, HIGH);
            state = UNLOCKED;
            last_change = now;
        } else if (now - last_change >= wait_interval) {
            Serial.println(F("Wait time out."));
            state = LOCKED;
        }
        break;
    case UNLOCKED:
        if (now - last_change >= lock_interval) {
            Serial.println(F("Locking."));
            digitalWrite(relay_pin, LOW);
            state = LOCKED;
        }
        break;
    }
}
```

[debouncing]: https://www.arduino.cc/en/tutorial/debounce
[Bounce2]: https://github.com/thomasfredericks/Bounce2
[fsm]: https://majenko.co.uk/blog/finite-state-machine


body:
I've recently purchased an NFC tag reader from MikroE and ive been a little lost on connecting the reader to my arduino board.

I've also been looking online for a library that i could use for this device, and have found little to nothing, though i maybe looking in the wrong place. If you could provide any guidance to the matter please respond.

any help would be much appreciated.

link to the tag: https://www.mikroe.com/nfc-tag-click

title: guidance on Mikrobus NFC tag and connecting to arduino

Answers: 1

body:
To find an Arduino library for a device, you can search for the term combination

    Arduino github <devicename>

because most libraries are hosted on github. The devicename here means the chip on the product, not the product itself. You won't find much for "Mikrobus NFC", but when you search for the chip on it - the  M24SR64 - you can find some promising results.

For example [this library][1], which looks good to me. It was used for [this blog article][2], which is where I found it (though that is a german site. I just wanted to link as reference for the german speakers). It has some examples, that show the usage of the library.

---

In general: Sometimes there might be no ready to use library for a chip or product to use with Arduino. In that case you need to write that code yourself. Let's take this product as example. It uses the I2C interface and the seller also links to the datasheet of the used chip. In the datasheet you can read, how the chip is used, including the communication protocol, that is imposes on the I2C interface. You could then write the corresponding I2C code using the `Wire` library.

Fortunate for you there already is a library, so you can first try that.

  [1]: https://github.com/rena2019/ArduinoM24SR
  [2]: https://regnerischernachmittag.wordpress.com/2014/08/22/m24sr-arduino-library/


body:
I have a project to be made i.e. water Billing System using RFID(Mfrc522) on Arduino NANO.
There is one difficulty that I haven't been able to overcome. I hope someone could help me out.
Project flow:

1. water or any liquid flows through the sensor and quantity of water gets recorded
2. now according to quantity of water flown there is price decided
3. this price needs to be deducted by swiping rfid card
issue:
1. i haven't been able to control interrupts
2. my program calculates the water flown
required:
1. edit code such that it as soon as water flows through it, it calculates and ask user to swipe card and as user swipes a amount deductes and process continues.

if not clear please ask and help me out

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

#define RST_PIN         9          // Configurable, see typical pin layout above
#define SS_PIN          10         // Configurable, see typical pin layout above
MFRC522 mfrc522(SS_PIN, RST_PIN);
String tagUID = "10 90 70 38";  // String to store UID of tag. Change it with your tag's UID
int bal =1000;

byte statusLed    = 13;
byte sensorInterrupt = 0;  // 0 = digital pin 2
byte sensorPin       = 2;

// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 4.5;

volatile byte pulseCount;

float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitres;

unsigned long oldTime;

void setup()
{

  // Initialize a serial connection for reporting values to the host
  Serial.begin(9600);
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;
  totalMilliLitres  = 0;
  oldTime           = 0;
  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
  Serial.begin(9600);    // Initialize serial communications with the PC
  while (!Serial);
  SPI.begin();      // Init SPI bus
  mfrc522.PCD_Init();   // Init MFRC522
}

/**
 * Main program loop
 */
void loop()
{

   if((millis() - oldTime) > 2000)    // Only process counters once per second
  {
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);

    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;

    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = millis();

    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate / 60) * 1000;

    // Add the millilitres passed in this second to the cumulative total
    totalMilliLitres += flowMilliLitres;

    unsigned int frac;

    // Print the flow rate for this second in litres / minute
    Serial.print("Flow rate: ");
    Serial.print(int(flowRate));  // Print the integer part of the variable
    Serial.print("L/min");
    Serial.print("\t");       // Print tab space

    // Print the cumulative total of litres flowed since starting
    Serial.print("Output Liquid Quantity: ");
    Serial.print(totalMilliLitres);
    Serial.println("mL");
    Serial.print("\t");       // Print tab space
    Serial.print(totalMilliLitres/1000);
    Serial.print("L");
    rfid();

    // Reset the pulse counter so we can start incrementing again
    pulseCount = 0;

    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
  }
}

/*
Insterrupt Service Routine
 */
void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}

void rfid()
{
   // put your main code here, to run repeatedly:

  Serial.println("In Rfid Loop");
  delay(3000);
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
        return;
      }
      // Select one of the cards
      if ( ! mfrc522.PICC_ReadCardSerial()) {
        return;
      }
  //Reading from the card
      String tag = "";
      for (byte j = 0; j < mfrc522.uid.size; j++)
      {
        tag.concat(String(mfrc522.uid.uidByte[j] < 0x10 ? " 0" : " "));
        tag.concat(String(mfrc522.uid.uidByte[j], HEX));
      }
      tag.toUpperCase();
       if (tag.substring(1) == tagUID)
      {
        bal=bal-20;
        delay(100);
        if(bal>=30)
        {
          Serial.println(bal);
          Serial.println("YOUR BALANCE");
          delay(400);

          // Reset the pulse counter so we can start incrementing again
          //pulseCount = 0;

          // Enable the interrupt again now that we've finished sending output
          //attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
        }
       else
        {
          Serial.println("INSUFFICIENT BALANCE PLEASE RECHARGE");
         }
        delay(100);

      }
      else
      {
        Serial.println("WRONG CARD ENTERED");

       }
}
```

title: Arduino Project Interrupt Error?

Answers: 1

body:
You are disabling interrupts for way too long. Interrupts are meant for
handling time-critical tasks that cannot wait for a full loop iteration.
If you ever disable them, it should be for a time as short as possible.
In your case, you only need to disable interrupts while accessing the
`pulseCount` variable, as this variable is shared between the ISR and
the regular code. This can be done in a very short "critical section" as
follows:

```c++
noInterrupts();
uint8_t pulseCountCopy = pulseCount;
pulseCount = 0;
interrupts();
```

In the rest of the loop you then only access `pulseCountCopy`. Note that
you don't really need to reset `pulseCount` to zero. Since it is
incremented using the rules of modular arithmetic, you can just compute
the differences between consecutive readings. You will get the correct
result even when it rolls over. This makes the critical section even
shorter:

```c++
static byte oldPulseCount;
noInterrupts();
uint8_t pulseCountCopy = pulseCount;
interrupts();
uint8_t pulseIncrement = pulseCountCopy - oldPulseCount;
oldPulseCount = pulseCountCopy;
```

And then note that, since reading a single byte is an atomic operation
(a single machine instruction), you do not even need to disable
interrupts _al all_! However, if the flow can ever be larger than
0.47 L/s, then 8 bits will not be enough for `pulseCount`. You
will have to use a 16-bit variable (`uint16_t`) and keep the critical
section.

As a side note, you are calling `millis()` several times per loop
iteration. This is bad practice, as there is no guarantee that you will
always get the same value, so you end up with your timing calculations
being somewhat sloppy. You should rather do something like

```c++
uint32_t now = millis();
```

at the start of `loop()`, and use the same value for the whole
iteration.

Another side note: you are differentiating the pulse count in order to
get a flow rate, then integrating the flow rate to get a total volume.
This is completely useless. The pulse count is already a measure of the
total volume. Basic arithmetics shows you that the calibration factor is

   4.5 (pulses/s) / (L/min) = 270 pulses/L

Your calculations will be less sloppy (having less accumulated error) if
you just divide the total pulse count by 270 to get the total volume in
liters.


body:
I've tried to copy CH340G from other schematics and existing Arduino Uno Clones...
Searched online & StackExchange but no good :/ My problem is almost the same as [this][1] one

Here is my schematic

[![Schematics][2]][2]

I can read & send data from the serial monitor

* OS: Win 10 64 Bit
* USB Driver: 3.5.2019.1

**Upload Options:**

* Arduino IDE version: 1.8.12
* Board: Arduino Uno (*also tired nano & nano old bootloader options*)

What I've tried:

* With & without the driver
* Rebooted the computer
* Tried different ports
* Different cables
* In case of IC not working, I've desoldered IC from working UNO
* Changed RX, TX vice versa
* Without R1 & R2
* Different capacitors on C6 and C3
Buuut results are always the same as below

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

         System wide configuration file is "C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf"

         Using Port                    : COM3
         Using Programmer              : arduino
         Overriding Baud Rate          : 115200
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0xf3
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0xf3

avrdude done.  Thank you.

Problem uploading to board.  See http://www.arduino.cc/en/Guide/Troubleshooting#upload for suggestions.
```

I appreciate any help, idea, suggestion
Regards

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

title: CH340G Uploading problem

Answers: 1

body:
The schematic is totally working. My mistake was after burning bootloader, I was uploading code via ISP. If you upload code via ISP, you're removing bootloader.

Thank you everyone who helped me to I wasn't mistaken at schematic and else...


body:
I am new to the RFID Scene and Serial communication as well.

  So I am trying to use the RC522 RFID module and I wrote in block 22 - 0x36 which is 6. I want to write a code where I take whatever is in block 22 - 0x36, convert it into a float - 6.00 and then do some addition or deduction for example 6.00-2.5 = 3.5 and then I want to rewrite the value of 3.5 into that same sector but of course, convert it back to HEX ASCII - 33 2e 35. I've tried quite hard to find the solution online but couldn't.
  So is this possible to do?

Thanks.

title: RFID RC522 Serial Communication converting problem

Answers: 0


body:
the function write in nrf24LO1 (without antenna) works perfectly

but in nrf24LO1 (with antenna) not works. why?!

the code
```
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <printf.h>

 RF24 radio(7,8);
 const byte address[6] = "00001";
void setup() {
  radio.begin();
  radio.setDataRate(RF24_250KBPS);
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_HIGH);
  radio.setCRCLength(RF24_CRC_8);
  radio.stopListening();
  Serial.begin(9600);
}

void loop() {
  const char text[] = "example";
  if(radio.write(&text,sizeof(text))) //<==problem here
    Serial.println("ok");
  Serial.println(text);
  delay(1000);
}
```
nrf24l01 with antenna :

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

nrf24l01 without antenna :

[![enter image description here][2]][2]

  [1]: https://i.stack.imgur.com/M6Tbj.png
  [2]: https://i.stack.imgur.com/oFPmm.jpg

title: nrf24L01 with/without antenna

Answers: 0