body:
I am having trouble getting the two sensors to work together. There are a total of four sensors connected to the Arduino, and while the MPU and AFE individually work fine with the other two sensors, when the two are put together only the Serial Plotter for the AFE shows up while the MPU stays at zero. I initially assumed that there were address conflicts with the two, but their i2c addresses are different: the AFE at 0x58 and the MPU at 0x68 or 0x69. How can I resolve the issue so that I can get all four sensors' graphs printing?
Below is my Arduino code:
```
#include "I2Cdev.h"
#include "MPU6050.h"
#include "Wire.h"

//int preValue = 0;
String str = "0, 0, 0, 0";
int mic = A0;
MPU6050 mpu;
int16_t ax, ay, az;

//PPG Stuff
#define NUM_REGISTERS       40
/* Pinbelegung */

int RESETZ = 4;
int CLK = 5;
int INT = 6;
//const int ocr1aval = 1; //||0 = 8MHz|| 1 = 4MHz|| 3 = 2MHZ ||7 = 1MHz||
const byte interruptPin = 2;

char LED2 = 0x2A; // LED2 on AFE4404

struct Register {
  uint8_t addr;
  uint32_t val;
};
/* Variablendeklaration */

//float befehl = 0;
bool Ready = 1;
int AFE_ADDR = 0x58;

unsigned long counter = 0;

/* AFE440X registers */

#define AFE_CONTROL0                0x00
#define AFE_LED2STC                 0x01
#define AFE_LED2ENDC                0x02
#define AFE_LED1LEDSTC              0x03
#define AFE_LED1LEDENDC             0x04
#define AFE_ALED2STC                0x05
#define AFE_ALED2ENDC               0x06
#define AFE_LED1STC                 0x07
#define AFE_LED1ENDC                0x08
#define AFE_LED2LEDSTC              0x09
#define AFE_LED2LEDENDC             0x0A
#define AFE_ALED1STC                0x0B
#define AFE_ALED1ENDC               0x0C
#define AFE_LED2CONVST              0x0D
#define AFE_LED2CONVEND             0x0E
#define AFE_ALED2CONVST             0x0F
#define AFE_ALED2CONVEND            0x10
#define AFE_LED1CONVST              0x11
#define AFE_LED1CONVEND             0x12
#define AFE_ALED1CONVST             0x13
#define AFE_ALED1CONVEND            0x14
#define AFE_ADCRSTSTCT0             0x15
#define AFE_ADCRSTENDCT0            0x16
#define AFE_ADCRSTSTCT1             0x17
#define AFE_ADCRSTENDCT1            0x18
#define AFE_ADCRSTSTCT2             0x19
#define AFE_ADCRSTENDCT2            0x1A
#define AFE_ADCRSTSTCT3             0x1B
#define AFE_ADCRSTENDCT3            0x1C
#define AFE_PRPCOUNT                0x1D
#define AFE_CONTROL1                0x1E
#define AFE_TIA_GAIN_SEP            0x20
#define AFE_TIA_GAIN                0x21
#define AFE_LEDCNTRL                0x22
#define AFE_CONTROL2                0x23
#define AFE_ALARM                   0x29
#define AFE_LED2VAL                 0x2A
#define AFE_ALED2VAL                0x2B
#define AFE_LED1VAL                 0x2C
#define AFE_ALED1VAL                0x2D
#define AFE_LED2_ALED2VAL           0x2E
#define AFE_LED1_ALED1VAL           0x2F
#define AFE_CONTROL3                0x31
#define AFE_PDNCYCLESTC             0x32
#define AFE_PDNCYCLEENDC            0x33
#define AFE_PROG_TG_STC             0x34
#define AFE_PROG_TG_ENDC            0x35
#define AFE_LED3LEDSTC              0x36
#define AFE_LED3LEDENDC             0x37
#define AFE_CLKDIV_PRF              0x39
#define AFE_OFFDAC                  0x3A
#define AFE_DEC                     0x3D
#define AFE_AVG_LED2_ALED2VAL       0x3F
#define AFE_AVG_LED1_ALED1VAL       0x40

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

  //ECG
  pinMode(10, INPUT); // Setup for leads off detection LO +
  pinMode(11, INPUT); // Setup for leads off detection LO -

  //PCG
  /*none needed*/

  //PPG
  pinMode(RESETZ, OUTPUT);
  pinMode(CLK, OUTPUT);
  pinMode(INT, INPUT);
  AFE_Init();

  //SCG
  #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
  #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
  #endif
  // initialize device
  mpu.initialize();
}

void PCG_Init()
{
  double micOut;
  const int sampleTime = 50;
  double preValue = 0;
}

void loop() {
  // put your main code here, to run repeatedly:
  String ECG = "0";
  //String SCG = "0";

  int PCG_val;
  String PCG;
  PCG_val = PCG_loop();
  PCG = String(PCG_val);

  int PPG_val;
  String PPG;
  PPG_val = PPG_loop() * -1;
  PPG = String(PPG_val);

//  int ECG_val;
//  String ECG;
//  ECG_val = ECG_loop();
//  ECG = String(ECG_val);

  int SCG_val;
  String SCG;
  SCG_val = SCG_loop();
  SCG = String(SCG_val);

  str = PCG + "," + PPG + "," + ECG + "," + SCG;
  Serial.println(str);
  delay(10);
}

//ECG Loop
int ECG_loop() {
  // put your main code here, to run repeatedly:
  if((digitalRead(10) == 1)||(digitalRead(11) == 1)){
  Serial.println('!');
  }
  else{
  // send the value of analog input 0:
  Serial.println(analogRead(A1));
  }
  //Wait for a bit to keep serial data from saturating
  delay(1);
  //delay (30);
}

//SCG Loop
int SCG_loop() {
    mpu.getAcceleration(&ax, &ay, &az);
    Serial.println(az/(pow(2,9)*1.0));
}

//PCG Loop
int PCG_loop() {
  //switch
  //case 1:
  int returnfill;
   double micOutput = findPTPAmp();
   returnfill = VUMeter(micOutput);
   return returnfill;
}

// Find the Peak-to-Peak Amplitude Function
double findPTPAmp(){
// Time variables to find the peak-to-peak amplitude
   unsigned long startTime= millis();  // Start of sample window
   /*unsigned int*/ double PTPAmp = 0;

// Signal variables to find the peak-to-peak amplitude
   /*unsigned int*/ double maxAmp = 0;
   /*unsigned int*/ double minAmp = 1023;

// Find the max and min of the mic output within the 50 ms timeframe
   while(millis() - startTime < sampleTime)
   {
      micOut = analogRead(mic);
      if( micOut < 1023) //prevent erroneous readings
      {
        if (micOut > maxAmp)
        {
          maxAmp = micOut; //save only the max reading
        }
        else if (micOut < minAmp)
        {
          minAmp = micOut; //save only the min reading
        }
      }
   }

  PTPAmp = maxAmp - minAmp; // (max amp) - (min amp) = peak-to-peak amplitude
  double micOut_Volts = (PTPAmp * 3.3) / 1024; // Convert ADC into voltage
  return PTPAmp;
}

// Volume Unit Meter function: map the PTP amplitude to a volume unit between 0 and 10.
int VUMeter(double micAmp){
  double fill = map(micAmp, 23, 750, 0, 10);
  while(fill != preValue)
  {
    preValue = fill;
  }
  return fill;
}

//PPG Loop
signed long val = 0;
void readADC()
{
  {
    val = AFE_Reg_Read(LED2);
    Ready = 1;
  }
}

int PPG_loop() {
  if (digitalRead(INT))
  {
    val = AFE_Reg_Read(LED2);
  }
  return val;
}

//More PPG Stuff
void AFE_Init()
{
  AFE_RESETZ_Init();
  AFE_Enable_HWPDN();
  AFE_Disable_HWPDN();
  AFE_Trigger_HWReset();
  Wire.begin();
  Wire.beginTransmission (AFE_ADDR);
  Serial.println("Initializing AFE4404...");
  if (Wire.endTransmission () == 0)
  {
    AFE_Enable_Write (); // enable to writting to registers
    AFE_Reg_Init();
    AFE_CLK_Init();
    AFE_Enable_Read ();  // enable to reading from registers
    Serial.println("Initialized Success!");
  }
  else
    Serial.println("Initialized Fail!");

}

/**********************************************************************************************************/
/*                              AFE4404_Registerinitialisierung                                           */
/**********************************************************************************************************/
void AFE_Reg_Init()
{
  //AFE_Reg_Write(34, 0x0033C3);
  AFEinitRegisters();
}

/**********************************************************************************************************/
/*                              AFE4404_Enable_Read                                                       */
/**********************************************************************************************************/
void AFE_Enable_Read ()         //Prohibit writing to registers
{
  byte configData[3];
  configData[0] = 0x00;
  configData[1] = 0x00;
  configData[2] = 0x01;// 0x01
  I2C_write (AFE_ADDR, AFE_CONTROL0, configData, 3);
}

/**********************************************************************************************************/
/*                              AFE4404_Disable_Read                                                      */
/**********************************************************************************************************/
void AFE_Enable_Write ()        //Permitt writing to registers
{
  byte configData[3];
  configData[0] = 0x00;
  configData[1] = 0x00;
  configData[2] = 0x00; //0x00
  I2C_write (AFE_ADDR, AFE_CONTROL0, configData, 3);
}

/**********************************************************************************************************/
/*                  RESETZ des AFE4404 wird Initialisiert                                                 */
/**********************************************************************************************************/
void AFE_RESETZ_Init()
{
  digitalWrite(RESETZ, HIGH);
  delayMicroseconds(30);
}

/**********************************************************************************************************/
/*                  Reset internal registers by setting RESETZ = LOW for 25 - 50 us                       */
/**********************************************************************************************************/
void AFE_Trigger_HWReset()
{
  digitalWrite(RESETZ, LOW);              //Sets Arduino pins 22-29 LOW
  delayMicroseconds(30); //30
  digitalWrite(RESETZ, HIGH);              //Sets Arduino pins 22-29 HIGH
  delay(10); // 10
}

/**********************************************************************************************************/
/*                             AFE4404 Power Down                                                         */
/**********************************************************************************************************/
void  AFE_Enable_HWPDN()
{
  digitalWrite(RESETZ, LOW);                  //Power Down by setting the RESETZ pin to LOW for more than 200 us
  delay(10);
}

/**********************************************************************************************************/
/*                                AFE4404 Power Up                                                        */
/**********************************************************************************************************/
void  AFE_Disable_HWPDN()
{
  digitalWrite(RESETZ, HIGH);                  //Power Up the AFE by setting the RESETZ pin to HIGH
  delay(10);
}

/**********************************************************************************************************/
/*                                AFE4404 Set Clock Mode to Internal                                      */
/**********************************************************************************************************/

void AFE_CLK_Init()
{
  AFE_Reg_Write(35, 0x104218);        //Set CLK Mode to internal clock (default Wert: 124218 mit interner CLK)
  AFE_Reg_Write(41, 0x2);             //Don´t set the internal clock to the CLK pin for outside usage
  AFE_Reg_Write(49, 0x000021);        //Division ratio for external clock mode set to fit the Arduino Mega 16MHz
  AFE_Reg_Write(57, 0);               //Set the lowes sampling rate to 61Hz (~17 ms)
}

/*********************************************************************************************************/
/*                                   AFE4404_Reg_Write                                                   */
/*********************************************************************************************************/
void AFE_Reg_Write (int reg_address, unsigned long data)
{
  byte configData[3];
  configData[0] = (byte)(data >> 16);
  configData[1] = (byte)(((data & 0x00FFFF) >> 8));
  configData[2] = (byte)(((data & 0x0000FF)));
  I2C_write(AFE_ADDR, reg_address, configData, 3);
}

/*********************************************************************************************************/
/*                                   AFE4404_Reg_Read                                                    */
/*********************************************************************************************************/
signed long AFE_Reg_Read(int reg_address)
{
  byte configData[3];
  signed long retVal;
  I2C_read (AFE_ADDR, reg_address, configData, 3);
  retVal = configData[0];
  retVal = (retVal << 8) | configData[1];
  retVal = (retVal << 8) | configData[2];
  if (reg_address >= 0x2A && reg_address <= 0x2F)
  {
    if (retVal & 0x00200000)  // check if the ADC value is positive or negative
    {
      retVal &= 0x003FFFFF;   // convert it to a 22 bit value
      return (retVal ^ 0xFFC00000);
    }
  }
  return retVal;
}

/**********************************************************************************************************/
/*                              Write to AFE on I2C                                                       */
/**********************************************************************************************************/
char I2C_write (int slave_address, int reg_address, byte configData[], int byteCount)
{
  int trans_end = 0;
  signed long retVal;

  Wire.beginTransmission(slave_address);
  Wire.write(reg_address);
  Serial.print(configData[0]);
  Serial.print(",");
  Serial.print(configData[1]);
  Serial.print(",");
  Serial.println(configData[2]);
  retVal = configData[0];
  retVal = (retVal << 8) | configData[1];
  retVal = (retVal << 8) | configData[2];
  Serial.println(retVal);
  Serial.println(reg_address);
  Wire.write(configData, 3);
  Serial.println("test");
  Wire.endTransmission();
  return (trans_end);

  /* while(1)
    {
     if(byteCount == 0)
     {
       Wire.endTransmission();
       Serial.println("test");
       return (trans_end);
     }else{
       //unsigned int reg_data = (unsigned int) *write_data++;
       Wire.write(configData, 3);
       byteCount--;
     }
    }*/
}

/**********************************************************************************************************/
/*                              Read Data of AFE on I2C                                                   */
/**********************************************************************************************************/
char I2C_read(int slave_address, int reg_address, byte *read_Data, int byteCount)
{
  int trans_end = 0;

  Wire.beginTransmission(slave_address);
  Wire.write(reg_address);
  Wire.endTransmission();
  Wire.requestFrom(slave_address, 3);
  while (Wire.available() && (byteCount != 0))
  {
    *read_Data++ = Wire.read();
    byteCount--;
  }
  return (trans_end);
}

void AFEinitRegisters(void) {

  unsigned char i;
  struct Register reg[NUM_REGISTERS];
  reg[0].addr = 0x01; reg[0].val = 0x000050;
  reg[1].addr = 0x02; reg[1].val = 0x00018F;
  reg[2].addr = 0x03; reg[2].val = 0x000320;
  reg[3].addr = 0x04; reg[3].val = 0x0004AF;
  reg[4].addr = 0x05; reg[4].val = 0x0001E0;
  reg[5].addr = 0x06; reg[5].val = 0x00031F;
  reg[6].addr = 0x07; reg[6].val = 0x000370;
  reg[7].addr = 0x08; reg[7].val = 0x0004AF;
  reg[8].addr = 0x09; reg[8].val = 0x000000;
  reg[9].addr = 0x0A; reg[9].val = 0x00018F;
  reg[10].addr = 0x0B; reg[10].val = 0x0004FF;
  reg[11].addr = 0x0C; reg[11].val = 0x00063E;
  reg[12].addr = 0x0D; reg[12].val = 0x000198;
  reg[13].addr = 0x0E; reg[13].val = 0x0005BB;
  reg[14].addr = 0x0F; reg[14].val = 0x0005C4;
  reg[15].addr = 0x10; reg[15].val = 0x0009E7;
  reg[16].addr = 0x11; reg[16].val = 0x0009F0;
  reg[17].addr = 0x12; reg[17].val = 0x000E13;
  reg[18].addr = 0x13; reg[18].val = 0x000E1C;
  reg[19].addr = 0x14; reg[19].val = 0x00123F;
  reg[20].addr = 0x15; reg[20].val = 0x000191;
  reg[21].addr = 0x16; reg[21].val = 0x000197;
  reg[22].addr = 0x17; reg[22].val = 0x0005BD;
  reg[23].addr = 0x18; reg[23].val = 0x0005C3;
  reg[24].addr = 0x19; reg[24].val = 0x0009E9;
  reg[25].addr = 0x1A; reg[25].val = 0x0009EF;
  reg[26].addr = 0x1B; reg[26].val = 0x000E15;
  reg[27].addr = 0x1C; reg[27].val = 0x000E1B;
  reg[28].addr = 0x1D; reg[28].val = 0x009C3F;
  reg[29].addr = 0x1E; reg[29].val = 0x000103;
  reg[30].addr = 0x20; reg[30].val = 0x008025; //0x008003
  reg[31].addr = 0x21; reg[31].val = 0x000125;//0x000003 //bit8: PROG_TG_EN
  reg[32].addr = 0x22; reg[32].val = 0x000100;//ILED2 = 32
  reg[33].addr = 0x23; reg[33].val = 0x000000;
  reg[34].addr = 0x32; reg[34].val = 0x00155F;
  reg[35].addr = 0x33; reg[35].val = 0x00991F;
  reg[36].addr = 0x36; reg[36].val = 0x000190;
  reg[37].addr = 0x37; reg[37].val = 0x00031F;
  reg[38].addr = 0x34; reg[38].val = 0x001563;
  reg[39].addr = 0x35; reg[39].val = 0x00991F;

  for (i = 0; i < NUM_REGISTERS; i++)
    AFE_Reg_Write(reg[i].addr, reg[i].val);

}
```
I am plotting each of the four sensors on LabView. Any help would be much appreciated!

title: Having trouble with MPU6050 and AFE4404 printing together, potential conflict?

Answers: 1

body:
Troubleshooting I2C issues can be frustrating.  In order to figure out the problem, I recommend you construct the simplest possible Arduino sketch, using just the two sensors that seem to have a problem working together.  You should be able to write a very simple program that does nothing but acquire a simple value from each sensor, say 2 times/second.

Once you have the simplest possible program running, you should be able to figure it out.  Right now all your program complexity is making it harder than it needs to be.

Good luck!

Frank


body:
i have an ultrasonic sensor. The sensor normally works stably. But I have to carry the data cables of this sensor for 50 meters and take reading. When i do this, when I extend the cable, the values I get from the sensor are not read stably.

I need to raise the sensor voltage so I can fix this problem, how can you help me?

title: Arduino Ultrasonic Sensor AnalogRead

Answers: 0


body:
I am trying to initialize the watchdog timer.

I have installed

    arduino-esp32-master.zip

I have

    #include <esp_task_wdt.h>

set but it is not highlighted red indicating the IDE knows about it.

The error indicates that a major function is not present.

full error:

    Arduino: 1.8.13 (Linux), TD: 1.53, Board: "ESP32 Dev Module, Disabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 240MHz (WiFi/BT), QIO, 80MHz, 4MB (32Mb), 115200, None"

    /home/brad/Documents/bradcode/Arduino/esp32s-infrared-ac-wifi-server-v4/esp32s-infrared-ac-wifi-server-v4.ino: In function 'void setup()':
    esp32s-infrared-ac-wifi-server-v4:229:23: error: 'WDT_TIMEOUT' was not declared in this scope
         esp_task_wdt_init(WDT_TIMEOUT, true); //enable panic so ESP32 restarts
                           ^
    Multiple libraries were found for "IRremote.h"
     Used: /home/brad/Documents/bradcode/Arduino/libraries/IRremote
     Not used: /home/brad/Documents/bradcode/Arduino/libraries/Arduino-IRremote-master
     Not used: /home/brad/Documents/bradcode/Arduino/libraries/IRremote-2.8.1
    Multiple libraries were found for "WiFi.h"
     Used: /home/brad/.arduino15/packages/esp32/hardware/esp32/1.0.4/libraries/WiFi
     Not used: /home/brad/Downloads/arduino-1.8.13/libraries/WiFi
     Not used: /home/brad/Documents/bradcode/Arduino/libraries/WiFiEspAT
    exit status 1
    'WDT_TIMEOUT' was not declared in this scope

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

What library did I fail to install to get the watchdog timer initialized?

UPDATE:

My additional boards URLs

    https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json,http://arduino.esp8266.com/stable/package_esp8266com_index.json

After following recommendations for poster, I got past that error and hit another one right away.

    Arduino: 1.8.13 (Linux), TD: 1.53, Board: "ESP32 Dev Module, Disabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 240MHz (WiFi/BT), QIO, 80MHz, 4MB (32Mb), 115200, None"

    In file included from /home/brad/Documents/bradcode/Arduino/esp32s-infrared-ac-wifi-server-v4/esp32s-infrared-ac-wifi-server-v4.ino:24:0:
    /home/brad/.arduino15/packages/esp32/hardware/esp32/1.0.4/libraries/WebServer/src/WebServer.h: In member function 'virtual size_t WebServer::_currentClientWrite_P(const char*, size_t)':
    /home/brad/.arduino15/packages/esp32/hardware/esp32/1.0.4/libraries/WebServer/src/WebServer.h:144:83: error: 'class WiFiClient' has no member named 'write_P'
       virtual size_t _currentClientWrite_P(PGM_P b, size_t l) { return _currentClient.write_P( b, l ); }
                                                                                ^
    /home/brad/Documents/bradcode/Arduino/esp32s-infrared-ac-wifi-server-v4/esp32s-infrared-ac-wifi-server-v4.ino: In function 'void setup()':
    esp32s-infrared-ac-wifi-server-v4:246:10: error: 'class WiFiClass' has no member named 'mode'
         WiFi.mode(WIFI_STA);
              ^
    esp32s-infrared-ac-wifi-server-v4:246:15: error: 'WIFI_STA' was not declared in this scope
         WiFi.mode(WIFI_STA);
                   ^
    esp32s-infrared-ac-wifi-server-v4:251:73: error: no matching function for call to 'WiFiClass::config(IPAddress&, IPAddress&, IPAddress&, IPAddress&, IPAddress&)'
         if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
                                                                             ^
    In file included from /home/brad/Documents/bradcode/Arduino/esp32s-infrared-ac-wifi-server-v4/esp32s-infrared-ac-wifi-server-v4.ino:22:0:
    /home/brad/Documents/bradcode/Arduino/libraries/WiFiEspAT/src/WiFi.h:72:8: note: candidate: bool WiFiClass::config(IPAddress, IPAddress, IPAddress, IPAddress)
       bool config(IPAddress local_ip, IPAddress dns_server = INADDR_NONE, IPAddress gateway = INADDR_NONE, IPAddress subnet = INADDR_NONE);
            ^
    /home/brad/Documents/bradcode/Arduino/libraries/WiFiEspAT/src/WiFi.h:72:8: note:   candidate expects 4 arguments, 5 provided
    Multiple libraries were found for "IRremote.h"
     Used: /home/brad/Documents/bradcode/Arduino/libraries/IRremote
     Not used: /home/brad/Documents/bradcode/Arduino/libraries/IRremote-2.8.1
     Not used: /home/brad/Documents/bradcode/Arduino/libraries/Arduino-IRremote-master
    exit status 1
    'class WiFiClass' has no member named 'mode'

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

I have some library mixed up still

title: esp32s: error: 'WDT_TIMEOUT' was not declared in this scope

Answers: 1

body: There is no such macro in the ESP32 core. That parameter is just the number of seconds before a timeout occurs. Just pick a reasonable value. 5 seconds seems to be a commonly used (and appears to be used in the core) value.


body:
I want to measure current using the MAX471 sensor that outputs voltage proportional to the current (1V/A according to the [datasheet](https://datasheets.maximintegrated.com/en/ds/MAX471-MAX472.pdf)). To test the module, I connected a 330 ohm resistor to the sensor and powered it from 3.3V arduino. Using ohms law, I was expecting an output voltage of around 10 mV (for ~ 10 mA) in my circuit. However, I am getting an output of around 2.17 volts which seems wrong.

Does anyone see any mistake in my circuit or how I am trying to measure the current?

Here is my circuit:

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

My Code:

    #include <Arduino.h>

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

    void loop()
    {
      int adc_val = analogRead(A5);
      float vol = 3.2 / 4095 * adc_val; // using a 12 bit adc

      Serial.println(vol);
      delay(3000);
    }

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

title: MAX471 giving too high current readings

Answers: 2

body:
Do you have the same operating circuit that is shown on page 1 of the datasheet? do you have the 2K resistor they specifically from OUT to ground? Also, it may be worth adding the 1 uF capacitor they recommend from OUT to ground too

The other thing to consider is the actual voltage over the resistor. Check an see if the voltage over the resistor is 3.3 and that there isn't a voltage drop from the chip

If the voltage is fine, there may be a problem with the chip or the arduino

body:
I've got a few MAX471 modules and instead of current readings i get around 90% of input voltage on all of them.

With increasing load the output voltage decreases a bit and the MAX471 chip gets very hot (for example 12V 0mAh = 10V, 12V 200mAh = 9,6V).

I guess we are just "lucky" to get a bad batch or counterfeit chips...


body:
I am driving a bipolar stepper motor with an a4988 driver using the AccelStepper library. My goal is to press a button and the motor moves CW, then another button for CCW.

I have looked at another post with a very similar issue, but the solution does not seem to apply well to the AccelStepper library, which I would really like to use given its versatility.

Currently, whichever button I press, the motor moves CCW. Any help would be greatly appreciated!

```c++
#include <AccelStepper.h>
AccelStepper stepperX(1, 3, 2);

void setup() {
  pinMode(8, INPUT)
  pinMode(9, INPUT);

  stepperX.setMaxSpeed(100.0);
  stepperX.setAcceleration(100.0);
}

int moveRight = 1000;              //arbitrarily high number
int moveLeft = -1000;              //arbitrarily low number

void loop() {
  while (digitalRead(8) == HIGH) { //when d8 button is pressed move left
    stepperX.moveTo(moveLeft);     //set move
    if (digitalRead(8) == LOW) {   //if not pressed, kill loop
      stepperX.stop();
      break;
    }
    stepperX.run();
  }

  while (digitalRead(9) == HIGH) { //when d9 button is pressed move right
    stepperX.moveTo(moveRight);    //set move
    if (digitalRead(9) == LOW) {   //if not pressed, kill loop
      stepperX.stop();
      break;
    }
    stepperX.run();
  }
}
```

title: Stepper motor won't change directions!

Answers: 1

body:
You work with accelleration and absolute positions. Are you aware of that?
This Library is not made for running permanently in the same direction. It let you define a position where the movement should end, an acceleration or speed and the controller moves the motor to that position.

The run method must be called permanently, It triggers the steps. So, I put it directly into the `loop()` method.

The following prog should hopefully move the motor towards position 1000 if you press the 8-button, towards position -1000 if you press the 9-button and stops if both buttons are off. I have not the hardware available at the moment, you it's just blind programming. Use it as an idea.

    #include <AccelStepper.h>
    AccelStepper stepperX(1, 3, 2);

    void setup()
    {
      pinMode(8, INPUT)
      pinMode(9, INPUT);

      stepperX.setMaxSpeed(100.0);
      stepperX.setAcceleration(3.0);
    }

    int positivePosition = 1000;
    int negativePosition = -1000;

    void loop()
    {
      if ( digitalRead(8) == HIGH )
      {
        stepperX.moveTo(positivePosition);
      }
      else if (digitalRead(9) == HIGH)
      {
        stepperX.moveTo(negativePosition);
      }
      else
      {
        stepperX.stop();
      }
      stepperX.run();
    }


body:
I would like to pass a formatted string to a method that accepts a __FlashStringHelper. Here is the method signature:

    void myMethod(const __FlashStringHelper *str);

I have been using snprintf to format my string:

    char cmd[30];
    snprintf(cmd, 30, "There are %d seconds in a minute", 60);
    myMethod(F(&cmd[0]));

Clearly the above doesn't work but how can I format a Flash String?

EDIT: I need to include an integer variable in my flash string. In the example above, '60' is a variable.

    uint8_t nSeconds = 60;
    char cmd[30];
    snprintf(cmd, 30, "There are %d seconds in a minute", nSeconds);
    myMethod(F(&cmd[0]));

title: Convert a char array to Flash string

Answers: 1

body:
Direct answer
-------------

`F()` takes *immutable* string literals, that are known at *compile* time, and places them into flash ("PROGMEM") instead of RAM.  `snprintf()` creates strings at *runtime* and places them into a *mutable* array.  The two things are fundamentally incompatible.

Limited compile-time concatenation
----------------------------------

A *very limited* form of what you're trying to do could probably done like this:

```c++
#define MY_STRINGIZE(x) #x

myMethod(F("There are " MY_STRINGIZE(60) " seconds in a minute"));
```

This expands to:

```c++
myMethod(F("There are " "60" " seconds in a minute"));
```

Adjacent string literals are concatenated together, which makes this:

```c++
myMethod(F("There are 60 seconds in a minute"));
```

All that said, you could just write 60 in there directly.  And there's none of `snprintf`'s formatting capabilities possible here.

There is not a compile-time version of `snprintf` available in Arduino.  And I don't think the features of the C++ (or C) language are there to support the creation of one either.  Odds are there is a better way of achieving what you really want to do.

Working around this altogether
------------------------------

Often it's not necessary to concatenate strings at all, particularly if you're just to turn around and write them to a `Stream`, or more generally `Print` subclass, e.g. `Serial`, `LCD`, `SDFile`, `SoftwareSerial`, etc.  Concatenating things for you is a large part of what these do.  It is not necessarily to do it yourself in advance.

If you have a string literal and constant (or variable) and want to keep as much of it out of RAM as possible, using two separate `.print()`/`.println()` helps you do this:

```c++
printCapableThing.print(F("AT+CIPSTAT="));
printCapableThing.println(index);
```

* `F()` places `"AT+CIPSTAT="` into flash.
* If index is a constant it will also wind not being resident in RAM.

Side note
---------

I realize you're asking about, getting as much into flash as possible, but I also can't help but point out this same basic technique applies to this otherwise awful idea, for somewhat different reasons:
```c++
Serial.println(String(F("Key ")) + keyname + " : " + value);
```
This creates a horrific mess of allocations and deallocations and unnecessary copying, where if you just let the Stream/Print object do its job by calling `print()`/`println()` multiple times.  The result code is more reliable, smaller, and where not I/O-bound, faster when you do.


body:
I am currently trying to connect 3 I2C Devices to an Arduino Mega, as detailed in the fritzing sketch. The Sensors are: Max86150 PPG Sensor on a breakout board (5v), MLX90614 IR Temperature Sensor (3.3V) and a SM9336 Pressure Sensor(3.3V). Essentially I can connect all devices and read off the sensors using individual sketches, but when I combine the sketches the values are not consistent and then the sketch crashes after only a few seconds.

Weirdly enough, when I combine a sketch with either the Temperature sensor and the Pressure sensor or the Temperature Sensor and PPG Sensor, it will work. But Pressure and PPG do not work together.

Does anyone have any idea what could be happening? I did have it working for a small while with some different wires, could this have anything to do with it? But even still some results I was reading from the sensor were the error values (e.g. the value you get when there is nothing connected, but it wasn't crashing). For reference I am using 30 AWG wires and strip board instead of the breadboard in the Fritzing. [![Fritzing Sketch][1]][1]

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

    //PPG
    #include "max86150.h"
    MAX86150 max86150Sensor;
    uint16_t ppgunsigned16;
    uint16_t irdata;

    // Pressure Sensor
    #include <Wire.h>

    #define PressureSensor_Data 0x30 // Pressure Register address
    #define TemperatureSensor_Data 0x2E // Pressure Temp Sensor Address

    int P0,T0,P1,T1;
    int SMD993Address = 0x6C; // Device Address

    //Timing
    #define INTERVAL 10 //10 milliseconds per sample for 100 Hz, change this for different sampling rates.
    uint32_t lastMicros = 0;

    // Temp
    #include <Adafruit_MLX90614.h>
    Adafruit_MLX90614 mlx = Adafruit_MLX90614();

    void ppgsetup()
    {
      max86150Sensor.setup();
    }

    void PPG() {

    while (1){
     if(max86150Sensor.check()>0)
        {
            ppgunsigned16 = (uint16_t) (max86150Sensor.getFIFORed()>>2);

            Serial.println(ppgunsigned16);
      //ppgunsigned16 = (uint16_t) (max86150Sensor.getFIFORed()>>2);
      //Serial.println(ppgunsigned16);

      if (ppgunsigned16 > 7000){

         for (int z = 0; z <= 500; z++){//This takes a reading every 10 milliseconds for 5000 milli seconds which is 5 seconds, 500 readings
           digitalWrite(ledPin,HIGH);//turning LED on
            //if (micros() - lastMicros > INTERVAL) { //This takes a reading every 100th of a second
                //lastMicros = micros(); // do this first or your interval is too long!

                if(max86150Sensor.check()>0)
        {
            ppgunsigned16 = (uint16_t) (max86150Sensor.getFIFORed()>>2);
            irdata = (uint16_t) (max86150Sensor.getFIFOIR()>>2);

            Serial.print(ppgunsigned16);
            Serial.print(",");
            Serial.println(irdata);
                //Serial.print("Check PPG");Serial.println(y);
                //mySerial.write(84);mySerial.print(ppgunsigned16);mySerial.print("/");
                //mySerial.write(83);mySerial.print(irdata);mySerial.print("/");
        }
        }
        digitalWrite(ledPin,LOW);//turning LED off
        break;

    }
    }
    }
    }

    void spirometry() {

        for (int x = 0; x <= 500; x++){
        Wire.beginTransmission(SMD993Address);
        Wire.write(PressureSensor_Data);
        Wire.write(TemperatureSensor_Data);
        Wire.endTransmission();
        Wire.requestFrom(SMD993Address,2);//This takes a reading every 100 milliseconds for 10000 milli seconds which is 10 seconds

        //if (micros() - lastMicros > INTERVAL) { //This takes a reading every 1000th of a second
          //lastMicros = micros(); // do this first or your interval is too long!

        if(Wire.available()<= 2) {
        P0 = Wire.read();
        P1 = Wire.read();
          }

        int Ptotal = P0 + (P1<<8); //The high byte is transmitted second so that

        Serial.println(Ptotal); // Print Ptotal to the serial monitor
        //mySerial.write(81);mySerial.print(Ptotal);mySerial.print("/");// Send PTotal over BLE with flag 81, this will change as sending via bytes is more efficient

        }

      }

    void temperature() {
      for (int y = 0; y <= 10; y++){
          mlx.begin();
          Serial.println(mlx.readObjectTempC());
          mySerial.write(82);mySerial.print(mlx.readObjectTempC());mySerial.print("/");
          delay(10);
    }
    }

    void setup() {

      // BT
      mySerial.begin(9600);
      Serial.begin(9600);//Sets BT Serial Comms to 115200, ensure that BT is allowing for this
      //LED
      pinMode(ledPin, OUTPUT);
      // PPG
        // Initialize sensor
        if (max86150Sensor.begin(Wire, I2C_SPEED_FAST) == false)
        {
            Serial.println("MAX86150 was not found. Please check wiring/power. ");
            while (1);
        }
        Serial.println(max86150Sensor.readPartID());
        ppgsetup();

      //Pressure Sensor

      //Temp

      //Sleep
      sleep();

    }

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

       PPG();
       delay(10000);
       spirometry();
       delay(1000);
       temperature();

    }

title: I2C Devices Interference

Answers: 2

body: I had a similar problem sometime ago, where I attached 2 servo driver boards and a battery hat (that used I2C for reading power levels) to a Raspberry Pi. The battery board worked alone and the servo boards worked alone, but when all three were present, the battery board stopped working. And all had unique addresses. After a few hours of going nuts, I realised that there were pullup resistors on the pi and all three boards attached. The total resistance of all 4 parallel pullup resistors were out of spec for I2C. I removed the resistors from the servo boards and everything started working together. So maybe you could disable the pullups on all baords except the Arduino and see if that is the problem.

body:
As pointed out by @peterpaulkeifer; Here

```
// Initialize sensor
    if (max86150Sensor.begin(Wire, I2C_SPEED_FAST) == false)
    {
        Serial.println("MAX86150 was not found. Please check wiring/power. ");
        while (1);
    }
```

I was setting the I2C Speed of the I2C Interface bus to fast and it seems that the pressure sensor was not able to handle this and would therefore give error answers and then crash.


body:
I ran into this while trying to make a battery monitor and wondered where I went wrong. Using `RTClib` available in the Arduino IDE or from [adafruit github][1], I ran into problems when trying to call `now` within a `while` loop inside of `loop`.  Here is a simple example:

    #include "RTClib.h"

    #define ledPIN 13

    RTC_PCF8523 rtc;

    void setup() {
      // put your setup code here, to run once:
      pinMode(ledPIN, OUTPUT);
      digitalWrite(ledPIN, LOW);
      Serial.begin(9600);
      while(!Serial) {/* wait for Serial */}
      rtc.begin();
      rtc.start();
      digitalWrite(ledPIN, HIGH);
     }

    void loop() {
      // put your main code here, to run repeatedly:
      char fmt[] = "YYYY/MM/DD-hh:mm:ss\n";
      while (millis() < 60000){
        Serial.println((rtc.now()).toString(fmt));
        delay(5000);
      }
      Serial.println("Finished");
      digitalWrite(ledPIN, LOW);
      while(1) { /* do nothing forever */ }
    }

 The output of this little test will be the same time repeated every 5ish seconds.  If it matters I am using a Feather M0 with the FeatherLogger that has an RTC on it.  Changing this `loop` function to this:

    void loop() {
      // put your main code here, to run repeatedly:
      char fmt[] = "YYYY/MM/DD-hh:mm:ss\n";
      if (millis() < 60000){
        Serial.println((rtc.now()).toString(fmt));
        delay(5000);
      } else {
        Serial.println("Finished");
        digitalWrite(ledPIN, LOW);
        while(1) { /* do nothing forever */ }
      }
    }

shows that `now` does in fact update the time every 5ish seconds.  I looked at the code for `now` and it appears to do very basic i2c commands to get the time and report it back.  The only thing I can think of is that the compiler created a (not so) temporary `DateTime` object for me within the `while` loop and the RTC library does not provide a convenient constructor or operator to overwrite the existing object.

I tested my theory with this

    void loop() {
      // put your main code here, to run repeatedly:
      char fmt[] = "YYYY/MM/DD-hh:mm:ss\n";
      while (millis() < 60000){
        DateTime t1 = rtc.now();
        Serial.println(t1.toString(fmt));
        delay(5000);
      }
      Serial.println("Finished");
      digitalWrite(ledPIN, LOW);
      while(1) { /* do nothing forever */ }
    }

But again, the time did not change so clearly I don't understand what's happening here.  Why doesn't the rtc `now` function work as intended within a `while` loop inside the `loop` function?

  [1]: https://github.com/adafruit/RTClib

title: RTClib now() within while loop does not update

Answers: 1

body:
See the [documentation of `DateTime::toString()`][toString]:

> The _buffer_ parameter should be initialized by the caller with a
> string specifying the requested format. This format string may contain
> any of the following specifiers: [...] The specifiers within _buffer_
> will be overwritten with the appropriate values from the `DateTime`.
> Any characters not belonging to one of the above specifiers are left
> as-is.

The important thing to realize is that the `buffer` parameter is used
**both** as input (for the format description) and as output (for the
formatted date and time). You initialize it with a format description
(`"YYYY/MM/DD-hh:mm:ss\n"`). Then, after the first call to `toString()`,
the same buffer contains the formatted date and time. It does **not**
contain the format description anymore. On the second call to
`toString()`, as per the rule “_Any characters not belonging to one of
the above specifiers are left as-is_”, the buffer is not modified.

**Solution**: Put the buffer initialization within the same `while` loop
as the call to `toString()`.

[toString]: https://adafruit.github.io/RTClib/html/class_date_time.html#a3753bf2ae254315a56f7ee38ff0b188b


body: I am looking to make a baby cry detection module that is a part of a bigger project i.e. IOT based baby monitoring system. Using AI, i have a dataset (of baby crying and not crying) to train model using binary classification through logistic regression. The problem is that the dataset has a 10kbps sample rate. and arduino records audio on 192kbps probably. so i need the arduino recorded audio to be 10kbps. secondly i need 100 weights or samples from the arduino recorded audio. so lets say the audio is of 5 seconds, so i need a sample after every 50ms so that the total samples would be 100. the main problem is i don't know how to take samples from an audio being recorded or a prerecorded audio using arduino. The 100 samples would then be multiplied by the 100 samples from the trained model and then added and then sigmoid function will be used so that at the end we can know whether the baby is crying or not. All the deployment of the model will be done in arduino. Any help regarding taking the samples or bitrate, would be much appreciated. Thanks in advance! :)

title: changing bitrate of audio recording and taking samples from audio in arduino

Answers: 1

body:
First of all, I am pretty sure your idea of using discrete ADC samples
as predictors for your model is hopelessly naive. As explained by
Majenko, you cannot expect anything meaningful from a sound recording
taken at 20 samples per second. You may have more luck using
spectral intensities as predictors. I suggest you start by doing some
time–frequency analysis on your training data, just to get some ideas on
what predictors may be worth trying. In any case, I strongly suggest you
train **and test** your model on your computer, before committing any
code to the Arduino.

That being said, sampling a signal at 20 Hz is quite easy: wait for
50 ms (or 50,000 µs for better accuracy), take one sample,
repeat. The only caveat is that you have to use `millis()` or `micros()`
rather than `delay()` or `delayMicroseconds()`, otherwise the sampling
period will be longer than expected because of the time needed to
execute the code.

Applying the sigmoid function just to compare the result to 0.5 makes
little sense. You know the sigmoid is larger than 0.5 only when its
argument is positive, so you can trivially save yourself expensive
floating point operations.

Here is a tentative implementation of (my understanding of) the idea you
suggest:

```c++
const uint8_t mic_pin = A0;
const size_t sample_count = 100;
const uint32_t sample_period = 50000;  // 50,000 us = 50 ms
const int weights[sample_count] = { 12, -42, 23 /* etc... */};

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

void loop() {
    // Record the samples.
    int samples[sample_count];
    uint32_t last_sample = micros();
    for (size_t i = 0; i < sample_count; i++) {
        while (micros() - last_sample < sample_period) { /* wait */ }
        samples[i] = analogRead(mic_pin);
        last_sample += sample_period;
    }

    // Compute the weighted sum.
    long sum = 0;
    for (size_t i = 0; i < sample_count; i++) {
        sum += (long) samples[i] * weights[i];
    }

    // Predict.
    if (sum >= 0) {
        Serial.println("The baby is crying!");
    }
}
```


body:
I need cnc machine to run as smooth as possible.

It receives commands like this "M_XY 10.233 20.123".

If i send command by command there is a slight delay between commands and its noticeable.
I set serial timeout to 5 ms.

I tried to send n commands and store them on arduino, but arduino cant store much in ram. There is a huge delay while sending n commands.

I was thinking about converting letters (machine writes letters) to bezier and sending arc by arc or letter by letter in arcs. Can atmega328p interpolate bezier fast enough?

Would it be faster if i send numbers in bytes instead of strings?
That would be 4 bytes per float and merge with union on arduino.

Is there any better way of doing this i don't know of?

Edit:
This is how string commands are processed.

    void addCommByte(const byte b){
      if(commID == MAX_COMM+1){
        commID = 0;
        Serial.println("TOO LONG COMMAND");
        Serial.flush();
        return;
      }

      if(b == '\n'){
        comm[commID] = '\n';
        commID = 0;

        processCommand();
      }
      else if(b == '\r')
      {
        commID = 0;
      }
      else
      {
        comm[commID++] = b;
      }
    }

    void loop() {
      Serial.flush();
      while(Serial.available() > 0) {
        addCommByte(Serial.read());
      }
    }

Edit. Way better way.

C# side. Check for endianness in c#. Arduino is little endian.

            public void MOV_X(float mm)
                {
                    SendCharAsByte("q"[0]);
                    SendFloatAsBytes(mm);
                }
            public void SendFloatAsBytes(float f)
            {
                byte[] vOut = BitConverter.GetBytes(f);
                serialPort.Write(vOut, 0, 4);
            }

            public void SendShortAsBytes(short f)
            {
                byte[] vOut = BitConverter.GetBytes(f);
                serialPort.Write(vOut, 0, 2);
            }

            public void SendCharAsByte(char c)
            {
                byte[] aaa = new byte[1];
                aaa[0] = (byte)c;
                serialPort.Write(aaa, 0, 1);
            }

Arduino side.

    void loop() {
      while(Serial.available() > 0) {
        processV2(Serial.read());
      }
    }
    // from processV2
    if(byt == 'q'){   // mov x
        float mm = readFloat();
        if(X_DIR == 1) mm *= -1.0;

        stepperXY.moveXForMMSync(mm);
        Serial.println("p");
        return;
      }
    // merge bytes
    union u_tag {
       byte b[4];
       float fval;
    } u;

    float readFloat(){
      Serial.readBytes(u.b, 4);
      return u.fval;
    }

There is no need to flush serial.

title: Arduino send commands fast

Answers: 1

body: If you have an existing CNC, you may have to abide by its comm protocol.  Otherwise, if the Arduino is part of a CNC you are building, and it is supposed to accept commands from a host computer, the first thing to do is make sure your baud rate is set higher than the default.  I have found 115200 to be a good choice for stability.  Next, you should avoid sending TTY-type text strings, and send binary values instead. You'd send an initial byte or word to specify the command type, followed by the data.  In my open-source DaqPort sketch for high-speed data acquisition <https://www.daqarta.com/dw_rraa.htm> I use the high nybble of the command to specify the general type, and the low nybble to specify more detail like channel number.  The sketch uses a big loop with if(Serial.available() > 0) to read the first byte, and a switch/case to determine what to do.  The the specific command reads the proper number of bytes and does whatever.  This is *way* faster than having to parse text and convert to binary.


body:
I'm getting a bit tripped up on const char pointers lately.

I'm getting a message from a server that comes through as either a c style string, a standard library string, or a WString:

[![return types][1]][1]

[![underlying types][2]][2]

I'm sending down a buffer of 32bit values from my server that aren't ascii or utf text, they're just bit values I want to parse and read on the esp32 side:

[![example data from the server][3]][3]

I thought "oh, I'll just mask the bit values 32 bits at a time and right shift the data to get the message (in reverse order, but still I can work with that). The problem that I'm running into is that I can shift numbers but not strings or byte arrays.

I wrote out a function to allow me to grab a piece of the string 32 bits at a time and convert that into a number while using an offset:

```
uint_fast32_t get32BitInt(const char *data, int offset = 0)
{

  uint32_t payload = 0;
  for (uint8_t i = 0; i < 8; i++)
  {
    payload <<= 0;
    payload += data[i + offset];
  }
  return payload;
}
```

But when I try to grab the first couple of 32 bit chunks the data isn't what I expected:

```
void handleGameFrame(const char *data, uint32_t length)
{

  uint8_t phaseAndColission = get32BitInt(data, 32);
  uint8_t player = getByte(data, 32 * 2);

  Serial.print("data: ");
  Serial.println(data);
  Serial.print("phaseAndColission: ");
  Serial.println(phaseAndColission, DEC);
  Serial.print("player: ");
  Serial.println(player, DEC);

}
```

yields:

[![enter image description here][4]][4]

I know the `Serial.println(data);` isn't going to output anything b/c it's a c-string of non-printable values, but the other chunk grabbing isn't giving me the same output from my server. It's hard to verify everything without being able to see all of the bits in the overall `data` pointer and I think I tied myself in (another) knot.

Is there a good way to parse 32 bit values out of a const c-string?

  [1]: https://i.stack.imgur.com/yaBmn.png
  [2]: https://i.stack.imgur.com/n0iXM.png
  [3]: https://i.stack.imgur.com/kKuDh.png
  [4]: https://i.stack.imgur.com/2vy86.png

title: Reading bits from a const char pointer

Answers: 1

body:
You wrote:
> I wrote out a function to allow me to grab a piece of the string 32
> bits at a time and convert that into a number while using an offset

This function is almost correct. Try this:

```c++
uint_fast32_t get32BitInt(const char *data, int offset = 0)
{

  uint32_t payload = 0;
  for (uint8_t i = 0; i < 4; i++)
  {
    payload <<= 8;
    payload |= data[i + offset];
  }
  return payload;
}
```

Compared to your version, the differences are:

* It reads 4 bytes instead of 8, as 32 bits are four bytes.

* For each byte being read, it shifts the payload by 8 bits (i.e. one
  byte) instead of zero. Shifting by zero has no effect.

* It uses `|=` instead of `+=`: just a micro-optimization for the sake
  of 8-bit MCUs. It shouldn't make much if a difference on a 32-bit
  micro.


body:
So let's say I use a store-bought TENS unit for liability. I want to make a challenge where you need to hold on to the TENS unit for 10 seconds before it activates a solenoid. How can I have an Arduino detect if someone is touching some metal posts connected to the unit? Would I need to measure the current for the tens unit or something? Any ideas/suggestions? Thanks!

Edit- Not sure if this should be in Arduino or Electrical Engineering, feel free to move it.

title: Sense person connected to TENS unit

Answers: 1

body: I think the main problem here is that you want to measure in the presence of high voltage from the TENS. Not having experience with TENS circuits, I would suppose that their contact pins are connected to the high voltage source through resistors to limit the current. (Or some equivalent current-limiting scheme.)  If so, the voltage between the contacts should drop when there is a person connected. You should be able to detect that drop with the Arduino.  The "obvious" approach would be to use voltage dividers to reduce the no-load voltage to less than 5V so the Arduino ADCs can handle it. You'd need high-value resistors in the dividers so they don't load the TENS... maybe 1 Megohm or more for each divider.  One problem with this simplistic approach is that the TENS is putting out its stimulus using brief pulses, which may be too quick to catch with the ADCs.  To get around that, you'd feed the output of each divider through a diode to an R-C filter.  (Note that you need the diode anyway, since the TENS output is probably AC and the Arduino ADCS only want DC.)  This may take a fair amount of experimentation to get the values right, which you should do *without* the Arduino... just a DVM or scope that you can start at a high-voltage range until you sure you have everything worked out to 0-5V.


body:
First of all, we connected our usb plug to arduino board (starter kit). After that, we completed Project 1 successfully (circuit with led and switch.) We tried unplug the usb cable, but it was very difficult, we had to pull very hard, but we couldn't unplug it. Finally, I managed to take it away with the help of my partner. I was pulling the usb and my partner was keeping the arduino board stable. The result wasn't very nice, we probably broke the usb cable. You can see what I mean in these images, the metallic coating part of the cable is still stuck on the board.

https://ibb.co/6wtf02J

https://ibb.co/4pZg2w0

https://ibb.co/WPchtgN

https://ibb.co/gPHZYnt

Nevertheless, we put the remaining cable back where it was, and the board seems to be working normally.

My question is if it safe to use it. Is there any chance of electrical damage or something like that?

Thank you!

P.S. In addition, we are planning to buy a new arduino starter kit. How can we avoid this problem with the new board?

title: Problem with my usb plug

Answers: 1

body:
Without the center part of the USB plug, it should be possible to make some deformations of that shield without damaging rest of the usb connector and pull it out. Aim for the weakest spot - seam (usually in the middle of bottom).

But even if you damage on board connector, it can be replaced (but it might be better to give it to someone with soldering experience - at least for unsoldering it)

And as noted in comments, even without working usb connector it can be programmed either by connecting USB-TTL serial converter to D0/D1 (but without auto-reset, unless you provide 100nF capacitor between reset and RTS), or it can be programmed by another Arduino as SPI (it needs bit more wires, and by default it doesn't burn bootloader, so if you fix USB, you'll have to burn bootloader).
Easier might be swapping Atmega328p between boards, however it needs some practice, so you won't bend or rip pins)


body:
I've noodled around with Arduino a bit, worked some tutorials.  I have an engineering & programming background, but electronics isn't my first language.  So apologies if this is a dumb question.

Here's the problem.  I've swapped a 2007 GM engine into an older Toyota Land Cruiser.  I need to make it compliant with the emissions equipment that was originally on the 2007 vehicle.  Most of that is pretty straight forward - catalytic converters, O2 sensors, charcoal canister, purge & vent solenoid valves, a pressure sensor.  The one bit I haven't figured out yet is fuel level.  The evaporative emissions system requires a fuel level input to the PCM (Powertrain Control Module) so it can figure out when & how to run the fuel system pressure test - the one that turns on your check engine light if your gas cap isn't on tight enough.

One solution would be to put in a GM fuel level sender ... but that involves draining the tank, dropping it, maybe cutting new holes, more wiring, etc.  I'm hoping I can fix this in software :)

The GM fuel level sending unit reads 0 ohms empty and 90 ohms full.  The existing Toyota sending unit should be 110 ohm empty and 3 ohm full.

So ... is it a feasible thing to build an Arduino based project that reads the resistance from the Toyota sender (without interfering with the Toyota gauge) and translates that to the range expected by the GM PCM?

I'm thinking something like this is the core of it: https://www.arduino.cc/en/Tutorial/LibraryExamples/DigitalPotControl  But I don't know what I don't know.

Thanks folks - additional information based on responses:

The Toyota sender is definitely a 12V two terminal unit.  Car electrical systems are nominally 12V, but typically are about 13.3V in operation.

The GM sensor is two terminal also.  According to the wiring diagram, one terminal goes to a low reference pin on the PCM and the other goes to a pin on the PCM labeled fuel level signal.

But it doesn't tell you the voltage they're applying on that pin - could be just 5V, other stuff coming out of the PCM is.  I couldn't find a test procedure either.  I'll pin that connector and see what I can measure next time I'm out there.

The fuel level signal is used for two things in the evaporative emissions (evap) system.

1. The evap vacuum test can only run when the tank is between approximately 1/3 to 2/3 full.
2. The vacuum test is calibrated against how full the tank is - lower fuel level means more air space in the tank means the pressure will change more slowly then compared to a fuller tank.

title: Convert fuel level sender resistance ranges - good Arduino project?

Answers: 1

body:
The Toyota sensor may be using 12V instead of 5V, which would mean you'd need to use a voltage divider to get it down to the range that the Arduino analog inputs can read.

You will need to find a digital potentiometer that can handle the voltage range that the
GM controller wants to see.  This may be 0-12V, which would be a problem since the AD5206 is only good for 5V.

However, as dandavis implies with his RC filter comment, you may be able to simulate the full 0-12V range with PWM, where the Arduino pin drives a transistor to chop up the 12V, and an RC filter smooths the result for the GM control unit.  That's probably your best approach.

Alternatively, if the GM controller is only looking for a go/no-go level, you can use the
transistor to switch in a simple voltage divider to get the right voltage from 12V.

The sensors are (presumably) just variable resistors (2-terminal) not full 3-terminal potentioneters.  They will most likely be using a series resistor to make a voltage divider, and the control unit (or gage in the Toyota) will reading the resulting voltage. You will want to either find out the value of the series resistor or measure the voltage that the gage sees.  It might already be in the 0-5V range.  The GM control unit may have the series resistor built in (or be using a current source), in which case you should measure the voltage its sensor input sees when you give it the max and min resistance.  This will be good to know when you are trying to drive it with your own circuit,


body:
Hi my USB to UART bridge (CP2102) seems to be broken on one of my NodeMCU Dev Boards with ESP8266.

It seems to be just that specific board since all other boards that I have can be flashed without problems.
I have a FTDI Programmer like this one:
[FTDI Programmer][1]

Now I would like to flash the Nodemcu using the FTDI programmer but I'm not sure how to wire it up.
I know that those programmers cant power up the ESP8266 by itself thats why I would use a micro USB cable that doesnt have a data wire to power up the nodemcu.

This is how I would wire everything up:
[![enter image description here][2]][2]

  [1]: https://ae01.alicdn.com/kf/H20e215e2865f48678845010232b87464E/FT232RL-FTDI-USB-3-3-V-5-5-V-zu-TTL-Serielle-Adapter-Modul-f-r.jpg
  [2]: https://i.stack.imgur.com/LDazU.png

Is this the correct way to wire up the programmer with the nodemcu? I want to be sure that nothing is going to mess up with the nodemcu or the programmer.

NodeMCU       FTDI
GND    ---->  GND
RX     ---->  TX
TX     ---->  RX

title: How to flash a NodeMCU (ESP8266) with an external FTDI programmer?

Answers: 1

body:
Assuming your FTDI Basic is the 3.3V version, then yeah that will work fine provided you that manually reset the board yourself and enter the boot-loader using the buttons.

If you're independently powering the boards you may want to insert some series resistance in the RX and TX connections in case your signal receiving end is not powered while the sending side is.  In short you don't want the TX signal from one of your devices (boards) trying to power the receiving device (board) through its protection/clamp diodes.

In regard to comment about resistor value:
The value of the resistor depends on what you can get away with in terms of its effect on the signal and how much current is allowed through the clamp diodes on the other board.  A couple of Kbyte is probably sufficient, better than nothing in any case. Use a bit more if you can and still get a reliable signal through.  If you have the boards both powered before you connect them and you're careful about connecting them, then there's no opportunity for that.  It may also just be that they're robust enough that you don't need them at all.  I usually put some in though.  The second reason which I didn't state above is just that it protects you from being outright stupid and accidentally connecting them to the wrong thing; wrong signal, or to VCC or GND on the other side.


body:
I am making a project where I use standalone atmega2560. I used arduino mega schematic to put all necessary components so atmega2560 would be working. I tried to burn bootloader into it using arduino mega as ISP, but failed. I get this error:

    C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avrdude -CC:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf -v -patmega2560 -cstk500v1 -PCOM4 -b19200 -e -Ulock:w:0x3F:m -Uefuse:w:0xFD:m -Uhfuse:w:0xD9:m -Ulfuse:w:0xFF:m

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

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

             Using Port                    : COM4
             Using Programmer              : stk500v1
             Overriding Baud Rate          : 19200
    avrdude: stk500_recv(): programmer is not responding
    avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x03
             AVR Part                      : ATmega2560
             Chip Erase delay              : 9000 us
             PAGEL                         : PD7
             BS2                           : PA0
             RESET disposition             : dedicated
             RETRY pulse                   : SCK
             serial program mode           : yes
             parallel program mode         : yes
             Timeout                       : 200
             StabDelay                     : 100
             CmdexeDelay                   : 25
             SyncLoops                     : 32
             ByteDelay                     : 0
             PollIndex                     : 3
             PollValue                     : 0x53
             Memory Detail                 :

                                      Block Poll               Page                       Polled
               Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               eeprom        65    10     8    0 no       4096    8      0  9000  9000 0x00 0x00
               flash         65    10   256    0 yes    262144  256   1024  4500  4500 0x00 0x00
               lfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
               hfuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
               efuse          0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
               lock           0     0     0    0 no          1    0      0  9000  9000 0x00 0x00
               calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
               signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

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

    avrdude: AVR device initialized and ready to accept instructions

    Reading | ################################################## | 100% 0.02s

    avrdude: Device signature = 0x000000 (retrying)

    Reading | ################################################## | 100% 0.02s

    avrdude: Device signature = 0x000000 (retrying)

    Error while burning bootloader.
    Reading | ################################################## | 100% 0.02s

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

    avrdude done.  Thank you.

I use schematic which I attached.

At first I uploaded arduinoISP example code to my arduino mega and then used it to program several arduino megas to be sure that it is working and then I connected cables to arduino mega ISCP connector which is master and then put them into my PCB board X3 connector which also has SPI connected to it. After trying to burn bootloader I got an error above.

Things I already did:
Made sure that all VCC pins are connected. And AVCC is connected to VCC
Made sure that all GND pins have ground and my PCB has same GND level as arduino mega (programmer)
Made sure that I connected SPI correctly.
Made sure that arduino as ISP is working.
Made sure that VCC level is high (it is about 4.7 V)
I also tried to put external voltage, but it also did not help.
I tried putting capacitor between Reset and GND pins on arduino mega (programmer)

What could go wrong? After all my struggles I came to the conclusion that it is probaby hardware problem, but I cannot find it.
Also I read that atmega2560 by default use 8 MHZ internal clock, can it be a problem?
[![enter image description here][1]][1]

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

title: Fail to burn bootloader into standalone atmega2560

Answers: 0


body:
I'm using a SIM A9G.  When I send HTTP GET command from the serial monitor, it responds. But, it doesn't work when included in the code.

```c++
#include <SoftwareSerial.h>
SoftwareSerial myserial(8, 7); // RX: 8, TX:7

void setup()
{
//  Wire.begin(I2C_SLAVE_ADDRESS);
  Serial.begin(19200);
  myserial.begin(19200);    // 9600, 19200, 38400, 57600, 74880, 115200

//  ET.begin(details(mydata), &Wire);
  Serial.println("JSON Initializing...");
  Serial.println("GPRS Starting..........");

//  myserial.listen();
  myserial.println("AT");
  delay(500);

  myserial.println("AT+CREG=?");     //Check Network regiistration, wait a while
  delay(1000);
  ShowSerialData();

  myserial.println("AT+CCID");  //Specify the connection type
  delay(1000);
  ShowSerialData();

  myserial.println("AT+CGATT=1");
  delay(2000);
  ShowSerialData();

  myserial.println("AT+CGDCONT=1,\"IP\",\"web.gprs.mtnnigeria.net\"");//Specify the APN
  delay(2000);
  ShowSerialData();

  delay(2000);
}

void loop()
{
  myserial.println("AT+CGATT=1");
  delay(2000);
  ShowSerialData();

  myserial.println("AT+CGACT=1,1");
  delay(2000);
  ShowSerialData();

  myserial.println("AT+HTTPGET=\"https://postman-echo.com/get?foo1=bar1&foo2=bar2\"");
  delay(5000);
  ShowSerialData();

  myserial.println("AT+CCLK?");
  delay(1000);
  ShowSerialData();

  delay(3000);
}

void ShowSerialData()
{
  while (myserial.available() != 0)
  {
    Serial.write(myserial.read());
    //delay(50);
  }
}
```

The output at the serial monitor is the following:
```None
+CGATT:1

OK
AT+CGACT=1,1

OK
E⸮⸮T⸮OZ⸮y:/⸮͵*⸮⸮⸮m/⸮⸮⸮⸮⸮=bar1&foo2=bar2"

+CME ERROR: 53
failure, pelase check your network or certificate!

AT+CCLK?

+CCLK: "21/02/22,18:19:43+01"

OK
```

title: SIM A9G: +CME ERROR: 53 failure

Answers: 1

body:
You must use this sequence.

AT+CREG=?
AT+CCID
AT+CGATT=1
AT+CGDCONT=1,"IP","ba.amx"
AT+CGACT=1,1


body:
> Depending on usage frequency, may get the occasional collision where
> both test for availability at the same time - if occurring too
> frequently, maybe add something simple like one arduino only does time
> updates on even seconds, the other on odd seconds.

https://forum.arduino.cc/index.php?topic=64049.0

I need events executed in the multiple receiving Arduino's to occur in sync (simultaneously). Is there a library or something, probably using the ESP32's RTC, to ensure events occur in sync?

Example system:
 - ESP32 sender/master
 - Arduino1 receiver controlling LEDs (Christmas lights)
 - Arduino2 receiver controlling stepper motors (Mary figure)
 - Arduino3 receiver controlling stepper motors (Joseph figure)

The issue is that they are sent data at different times by the user.

Say, the user selects settings for Mary. That data is sent to the ESP32, and then that data is sent to all the Arduinos, but only "gets into" the MaryArduino.

Then, the user selects settings for the lights. That data is sent to the ESP32, and then data is sent to all the Arduinos, but only "gets into the LightsAruino.

Etc.

However, I need everything to start at the same time.

The data is not simultaneously sent. It is sent one after the other, as slow as the user selects their settings. However, the sequence of events must simultaneously occur.

title: Connect multiple Arduinos to ESP32's RTC?

Answers: 1

body:
Give the master a single signal wire that is connected to all of the slaves and that signal LOW while the master sends commands to each slave. Let each of the slave Arduinos simply store its message but not act on it while the signal wire is LOW.

When the slaves are supposed to start, raise the signal level to HIGH. Each slave Arduino now executes whatever command it had been sent. The RTC now only needs to be connected to the Master, which controls all of the timing.


body:
Greetings to all members of the Forum. I would like to express my deepest gratitude, with respect to the title of this post.
The last week I am trying to capture and decode a PPM Signal from an RC transmitter. Although I have seen many different approaches and codes online, using methods like Input Capture Mode and Pin Change Interrupts I would like to seek some help on my approach.
Most of the codes I have found online present glitches and instabilities while trying to read the time between the rising pulses.
I have tried to read and understand how to set up the Input Capture registers on the Atmega 32u4 chip, aka Arduino Pro Micro / Lepnardo, but I cannot find a proper way of defining the registers as well as the ISR (_vec) function.
In the next few lines I will try to explain the code I have written so far, but I will need some help with respect to the initialization of registers.
Please bare with me, as any help will be much appreciated. Without further ado, let me introduce you to the following lines.
```

#define STICK_CENTER 1500
#define STICK_HALFWAY 500
#define THRESHOLD 15

#define MIN_PULSE_WIDTH (STICK_CENTER - STICK_HALFWAY - 15)
#define MAX_PULSE_WIDTH (STICK_CENTER + STICK_HALFWAY + 15)

#define RC_CHANNELS_COUNT 8

#define PPM_CAPTURE_PIN 4
#define NEWFRAME_PULSE_WIDTH 2000
#define TIMER_COUNT_DIVIDER 2

void rc_setup_ppm() {
  setupPins();
  initTimer();
}

void setupPins(void) {
  // Set up the Input Capture pin
  pinMode(PPM_CAPTURE_PIN, INPUT);
  digitalWrite(PPM_CAPTURE_PIN, 1); // enable the pullup
}

void initTimer(void) {
  cli();

  TIFR = (1 << ICF1); //Clear any Interrupt flags
  PRR |= (0 << PRTIM1); //Enable Timer1
  TCCR1A = 0; //Clear TCCR1A
  TCCR1B = 0; //Clear TCCR1B
  TCCR1C = 0; //Clear TCCR1C
  TCCR1B = (1 << ICNC1) | (1 << ICES1) | (1 << WGM13) | (1 << WGM12) | (0 << CS12) | (1 << CS11) | (0 << CS10);
  TIMSK1 |= (1 << ICIE1); //Enable input capture
  TIFR1 = (1 << ICF1); //Clear interrupt flag

 sei();
}

uint16_t adjust(uint16_t diff, uint8_t chan) {

  return diff / TIMER_COUNT_DIVIDER;
}

ISR(TIMER1_CAPT_vect) {
  union twoBytes {
    uint16_t word;
    uint8_t  byte[2];
  } timeValue;

  uint16_t now, diff;
  static uint16_t last = 0;
  static uint8_t chan = 0;

  timeValue.byte[0] = ICR1L;    // grab captured timer value (low byte)
  timeValue.byte[1] = ICR1H;    // grab captured timer value (high byte)

  now = timeValue.word;
  diff = now - last;
  last = now;

  //all numbers are microseconds multiplied by TIMER_COUNT_DIVIDER (as prescaler is set to 1/8 of 16 MHz)
  if (diff > (NEWFRAME_PULSE_WIDTH * TIMER_COUNT_DIVIDER)) {
    chan = 0;  // new data frame detected, start again
  }
  else {
    if (diff > (MIN_PULSE_WIDTH * TIMER_COUNT_DIVIDER - THRESHOLD)
        && diff < (MAX_PULSE_WIDTH * TIMER_COUNT_DIVIDER + THRESHOLD)
        && chan < RC_CHANNELS_COUNT)
    {
      rc_values[chan] = adjust(diff, chan); //store detected value
    }
    chan++; //no value detected within expected range, move to next channel
  }
}
```
**Given the above I would like to help setting the initialization routine of the registers. Some information about my signal:**

 *PPM includes 8 different channels as a summed signal. In total 9 pulses while each one, has a time duration from 998 - 2012 microsecs.*

*The time frame of each pulse is easy to be changed though the transmitter settings. Also the total period of the frame can be changed. By the first I mean the HIGH time of each pulse, and by the second I mean the total frame period after the 8 channels have been scanned. Given these, the time periods are 26.5 mills and 350 microsecs.*

Enough with these. Going back to the actual code you will see the cli(); and sei(); functions. Do I really have to set these during that part of the code?
Also do I need to reset or delete any active flags? Should I include any flags (e.g. Overflow flag after the counter has reached its peack value)

At this point I would also like to mention that I am using a prescaler of 1/8, which results to a tick period of apx. 0.5 microsecs.
Also, I am capturing only the rising part of the pulses. And I am using an Input canceler, but given the datasheet specifications I have seen that the cancel frame is 4 periods long. Is there any possible way to use a low latency filtering scheme?

Please take some time to read this post, as I am confident enough that any responses will help others too clarify these topics.
I know that I have included many different aspects and I feel sorry for this.

Many thanks,
Koutsoukos Theodosios

title: Input Capture Mode PPM signal

Answers: 1

body:
> Do I really have to set these during that part of the code?

No, you don't. I would, however, change the order of the last
initializations:

* Update `TIFR1` right before `TIMSK1` in order to avoid an interrupt to
  be triggered immediately.

* Set `TCCR1B` last in order for the timer to start only when it has
  been fully configured.

> Also do I need to reset or delete any active flags?

AFAIK the Arduino core does not use the Timer 1 interrupts. You can take
control of all the bits in the registers (e.g. `TIMSK1 = (1 << ICIE1);`)
instead of only some selected bits. It shouldn't make a difference
though.

> Should I include any flags (e.g. Overflow flag after the counter has
> reached its peak value)

Do not worry about overflows. The computation `diff = now - last` is
done modulo 216 and, owing to the rules of modular
arithmetics, gives the correct result even across an overflow.

> And I am using an Input canceler, but given the datasheet
> specifications I have seen that the cancel frame is 4 periods long.

This creates a delay of “four system clock cycles”, or 0.25 µs. Do
you really care about such a small latency? Please note that, since all
edges suffer the same latency, it doesn't affect the calculated
differences.

Now, if I may, a couple of comments about your code:

```c++
  pinMode(PPM_CAPTURE_PIN, INPUT);
  digitalWrite(PPM_CAPTURE_PIN, 1); // enable the pullup
```

This can be simplified an made more explicit:

```c++
  pinMode(PPM_CAPTURE_PIN, INPUT_PULLUP);
```

Then,

```c++
  union twoBytes {
    uint16_t word;
    uint8_t  byte[2];
  } timeValue;
  timeValue.byte[0] = ICR1L;    // grab captured timer value (low byte)
  timeValue.byte[1] = ICR1H;    // grab captured timer value (high byte)
  now = timeValue.word;
```

This used to be the way to read 16-bit registers a long time ago. Since
many years now, the C compiler knows how to do it, you just have to
issue:

```c++
  now = ICR1;
```


body:
I’m starting on a project about monitoring the soil in the agriculture field and also to visualise the data remotely. The aim of this project is collect the atmospheric data as well as the soil related parameters and then send them to cloud where they’ll be presented on the dashboard. I decide to use Arduino as my development board and Arduino MKR GMS 1400 would be perfect for this project. However this board is quite expensive. So just wondering that are there any alternative I can use for this project

Thank you

title: Arduino MKR GMS alternative

Answers: 1

body:
There are multiple options for this project as you just want to send/ upload data on the cloud server rather than using Arduino MKR 1400 you can use any of the following.
1. Arduino UNO with GSM module: As per your requirement you can use Arduino UNO to read the data from the sensor and the GSM module will be used to upload the same on the cloud server. There are various GSM modules available in the market which are cheap also and good. You can also use [SIM800][1] one of the GSM module.

Other GSM modules which you could use can be,

[SIM900][2], [Quectel EC-20][3], [Quectel M95][4]. You can also visit [SIMCONN website][5] where you can find multiple GSM module options.

2. You can also use ESP8266 or ESP32 which are Wi-Fi modules but in this case you will require a internet/ Wi-Fi connection near the controller. ESP8266/ ESP32 will read data from the sensors and can also upload the same to the cloud servers. But as you said you are using them to monitor agriculture field it won't be possible to have a Wi-Fi which will cover such long range.

3. One of the possible solutions to the problem is to use RF-link to transmit data and collect it at a base-station and from the base station you can upload/ send them to the server.

4. You can also make use of the [LoRa][6] Network to communicate along the fields and then receive data from the whole field at a base station and then upload them to the server. But this could be a more expensive solution.

  [1]: https://simcom.ee/modules/gsm-gprs/sim800/
  [2]: https://simcom.ee/modules/gsm-gprs/sim900/
  [3]: https://www.quectel.com/product/ec20r21.htm
  [4]: https://www.quectel.com/product/m95.htm
  [5]: https://simcom.ee/?gsm-gprs
  [6]: https://www.semtech.com/lora/what-is-lora


body:
My question is: how can I use an ISR and store the data I get from my analog inputs into an array for easier data analysis.

More specifically, I want to collect my data using an ISR function (internal timer interrupt), then store the collected data into an array. This way I can analyze the data more easily.

I have posted the code below. I have posted code showing how I implemented my ISR *without* storing the data into an array. I was wondering I anyone could help me out with this (how to store that data into an array). Thank you.

```c++
const int A0_pin = PC0;
const int A1_pin = PC1;

const uint16_t t1_load = 0;
const uint16_t t1_comp = 3173;

float count = 0;
float num = 0;

void setup() {

  //Set A0 and A1 pins as inputs
  DDRC &= ~(1 << A0_pin);
  DDRC &= ~(1 << A1_pin);

  //Reset Timer1 Control Reg A
  TCCR1A = 0;

  //Set CTC mode
  TCCR1B &= ~(1 << WGM13);
  TCCR1B |= (1 << WGM12);

  //Set to prescaler of 256
  TCCR1B |= (1 << CS12);
  TCCR1B &= ~(1 << CS11);
  TCCR1B &= ~(1 << CS10);

  //Reset Timer1 and set compare value
  TCNT1 = t1_load;
  OCR1A = t1_comp;

  //Enable Timer1 compare interrupt
  TIMSK1 = (1 << OCIE1A);

  //Enable global interrupt
  sei();

  Serial.begin(9600);
  Serial.println("CLEARDATA"); //clears up any data left from previous projects
  Serial.println("LABEL,TIME,TIMER,AVG,GAUGE0, GUAGE1"); //always write LABEL, so excel knows the next things will be the names of the columns
  Serial.println("RESETTIMER"); //resets timer to 0
}

void loop() {
}

ISR(TIMER1_COMPA_vect) {
  TCNT1 = t1_load;
  float Gauge0 = analogRead(A0_pin);
  float Gauge1 = analogRead(A1_pin); //44

  //conversion of read data, to voltage range (0-100 percentVolts)
  float gauge0 = Gauge0 * (100.0 / 1023.0);
  float gauge1 = Gauge1 * (100.0 / 1023.0);
  float add = gauge0 + gauge1;
  float AVG = ((gauge0 + gauge1) / 2);

  Serial.print("DATA,TIME,TIMER,");
  Serial.print(add);
  Serial.print(",");
  Serial.print(gauge0);
  Serial.print(",");
  Serial.println(gauge1);
}
```

In the code, I want to store the `gauge1` and the `gauge0` values into an array essentially.

title: Collecting data from a timer interrupt and storing it into an array

Answers: 3

body:
You can create two arrays, e.g.:

    #define MAX_LENGTH 20

    volatile float _gauge0[MAX_LENGTH];
    volatile float _gauge1[MAX_LENGTH];

    volatile int _filled = 0;

The _filled value shows that `_gauge0` is filled from 0 upto (excluding) `_filled`.

So when adding two values you use:

    _gauge0[_filled] = some value;
    _gauge1[_filled] = some_other_value;
    _filled++;

After processing, you reset `_filled` to 0 to refill both arrays again.

Because the Arduino has a limited amount of SRAM it's best to use a fixed array size (20 in this case). You have to make it `volatile` as it's used from within the ISR.

I'm not sure what you want to do with the data. If you want to gather like 20 (or a fixed amount of values), you can use the above.

If you need a continuous amount of memory and get the last x results, you can better use a so-called ring buffer (search for this, there are many articles about it).

Note that because of the limited amount of SRAM, it might be best not to store calculated values (like average and sum), unless you need the highest performance. This is a tradeoff which I cannot make as I don't know your requirements.

While processing, you use `noInterrupts()` before and `interrupts` after the processing of the data, otherwise interrupts will continue during processing. Make sure the handling of the processing takes as less time as possible as you might miss interrupts. Preferably only do the calculations and switch on interrupts before sending results via serial for example.

body:
Storing the data into arrays is not an end in itself. The question is:
what do you want to do with these arrays? The way to proceed depends on
that purpose.

If you want the data acquisition (`analogRead()`) and the processing
(computation and printing) to proceed _in parallel_, then you will need
the arrays for buffering the data between those two processes. As
mentioned by Michel Keijzers in his answer, you will have to research
the concept of [ring buffer][].

There is a ring buffer implementation in the Arduino core you can use as
inspiration: when reading data from the Serial port, the incoming bytes
are [received by an ISR][rx_complete] and stored in a ring buffer. [The
`Serial.read()` method][read] can then be used to retrieve these bytes
and process them outside the interrupt context.

Another option is to alternate between an acquisition phase and a
processing phase. This can be an interesting approach if the acquisition
rate is too fast for the processing to be performed in real time. In
this case, you do not need a ring buffer. Instead, you have the ISR fill
the arrays and, when they are full, the main program can take on and
start the processing. For coordinating these jobs, you just need a
boolean to keep track of whether you are performing the acquisition
phase or the processing phase. Note that, since accessing a boolean is
an atomic operation, you do not need to disable interrupts for this.

Here is an example implementation of this strategy. The variable
`sampling_done` is used to coordinate the two processes:

```c++
const size_t sample_count = 256;

volatile int gauge0[sample_count];
volatile int gauge1[sample_count];
volatile bool sampling_done = false;

ISR(TIMER1_COMPA_vect) {
    if (sampling_done) return;  // nothing to do

    static size_t sample_idx = 0;
    gauge0[sample_idx] = analogRead(A0);
    gauge1[sample_idx] = analogRead(A1);
    if (++sample_idx >= sample_count) {
        sample_idx = 0;  // prepare for next round
        sampling_done = true;
    }
}

void process_samples(int Gauge0, int Gauge1) {
    // Whatever needs to be done with the samples:
    // computation, printing...
}

void loop() {
    if (sampling_done) {
        for (size_t i = 0; i < sample_count; i++) {
            process_samples(gauge0[i], gauge1[i]);
        }
        sampling_done = false;  // start next sampling round
    }
}
```

Now some random remarks:

* There is no need to `sei()` in `setup()`: interrupts have already been
  enabled by the Arduino core initialization.

* Do not reset `TCNT1` within the ISR: this is handled automatically by
  the CTC mode. If you do this in software, you risk missing timer
  ticks.

* Do not store the readings in `float` variables: they take twice the
  memory of an `int` and all operations on floats are incredibly slow
  compared to the equivalent operations on ints.

* The scale factor for converting the readings to percent scale is
  `100.0/1024`: the maximum possible analog reading (1023) is one ADC
  step below the reference voltage: see the datasheet.

* You should remove unused variables as soon as they become unused
  (`count`, `num`, `AVG`). Once you do that you should notice you do not
  need floats at all.

[ring buffer]: https://en.wikipedia.org/wiki/Circular_buffer
[rx_complete]: https://github.com/arduino/ArduinoCore-avr/blob/1.8.3/cores/arduino/HardwareSerial_private.h#L101-L121
[read]: https://github.com/arduino/ArduinoCore-avr/blob/1.8.3/cores/arduino/HardwareSerial.cpp#L180-L190

body: My DaquinOscope <https://www.daqarta.com/dw_rroo.htm>  uses the open-source DaqPort sketch <https://www.daqarta.com/dw_rraa.htm> to sample in batches, then transfer the data to the host in one high-speed blast.  It takes 1024 total samples, which in your case of 2 channels would be 512 per channel. It stores only the raw data, unscaled... the host is the place for that. The host processes and displays the results in real time. Since this uses a UNO with only 2K RAM, tricky array storage was required to fit in 1024 samples.  In 8-bit mode this is just a 1024-byte array, but for 10-bit it uses a supplemental array of 256 bytes.  On each sample the low byte is stored in the 1024-byte array, and the upper 2 bits are shifted into a 4-sample byte of the 256-byte array.  Feel free to download and use Daqarta for this... no charge for Arduino use. You may want to do this just to work out other issues even if you plan to later use your own host software.  Or you can use Daqarta macros to do whatever you ultimately want.


body:
Is there any way to know the resolution of micros() for the Arduino Portenta H7. I have checked for other boards e.g. Nano which is mentioned as 4 uS. However, I couldn't find one for Portenta H7.

Is there any way to measure or look for that

title: micros() resolution for Portenta H7

Answers: 1

body:
The **micros()** [language reference][1] states that, "[The micros() function] returns the number of microseconds since the Arduino board began running the current program. This number will overflow (go back to zero), after approximately 70 minutes. **On the boards from the Arduino Portenta family this function has a resolution of one microsecond on all cores.** On 16 MHz Arduino boards (e.g. Duemilanove and Nano), this function has a resolution of four microseconds (i.e. the value returned is always a multiple of four). On 8 MHz Arduino boards (e.g. the LilyPad), this function has a resolution of eight microseconds.

It seems likely that the doco was updated some time after the OP posted the question.

  [1]: https://www.arduino.cc/reference/en/language/functions/time/micros/


body:
I build a macro keyboard and one thing I do alot is add a set amount to numbers mostly in 3d modeling programs. I add and remove 0.25 and 0.125 all the time. I want to make a macro that copies selected text, adds or subtracts a value then pastes it back.

I known the simple copy and paste commands but how do I get my arduino program to grab that copied value?

Can this even be done?

title: Save highlighted text as int variable

Answers: 1

body:
You have to write an application for your PC that

* reads a number from the clipboard
* adds some constant
* puts the result back in the clipboard
* quits

Then you have to configure you desktop environment in order to have this
application launched from a keyboard shortcut.

Once you have done that, you can do the whole operation from a regular
keyboard: Ctrl-C + Launcher shortcut + Ctrl-V.

If you can do it from a regular keyboard, you can do it from the Arduino
emulating a regular keyboard.

**Edit**: The way you do the first two steps is very dependent on the OS
running on your PC. On Linux, for example, the mentioned “application”
can be a minimal shell script:

```sh
#!/bin/bash

x=$(xclip -o -selection clipboard)
xclip -i -selection clipboard <<< $(bc <<< "$x + 0.25")
```

These steps are, however, outside the scope of this site.


body:
One ESP32's 3v3 is connected to GPIO 26 of another ESP32.
The program is uploaded. The built-in LED lights for two seconds as expected. Then, it turns off. No matter what GPIO pin the 3v3 is connected to (besides 2), the LED remains off.

    /*
     * ON Board LED GPIO 2
     */

    #define LED 2
    #define inPin 26

    void setup()
    {
      Serial.begin(9600);
      // Pins 34, 35, 36, 39 are input only
      pinMode(LED, OUTPUT);

      // Sanity check LED works
      digitalWrite(LED, HIGH);
      delay(2000);
    }

    void loop()
    {
      Serial.println(digitalRead(inPin));
      digitalWrite(LED, digitalRead(inPin));
    }

Any reason this is happening? Grounds are connected. Simply trying to turn LED on/off if external voltage occurs at any GPIO pin (e.g., 26).

title: Simple ESP to ESP reading blink program not reading input voltage

Answers: 1

body:
Arduino GPIO automatically set as inputs, so I assumed the same for ESP32. Once the `pinMode` of the input pin was set, it worked:

    #define LED 2 // ON Board LED GPIO 2
    #define inPin 26

    void setup()
    {
      Serial.begin(9600);
      // Pins 34, 35, 36, 39 are input only
      pinMode(LED, OUTPUT);
      pinMode(inPin, INPUT); // <----------
    }

    void loop()
    {
      Serial.println(digitalRead(inPin));
      digitalWrite(LED, digitalRead(inPin));
    }


body:
I have been trying to get the Arduino bootloader to compile into my firmware binary in Atmel Studio. I got the bootloader project to link and compile. I use ArduinoCore and the bootloader as a dependencies to my main code. The dependency tree looks like:

 1. ArduinoCore
 2. bootloader
 3. Main firmware

**The Bootloader**

It took me a bit to get the bootloader to accept the rest of ArduinoCore as a dependency but it compiles into a static library. I use the bootloader linker to specify the memory location of the bootloader binary. It should start at 0x0 and provide a jump to the main firmware, located at 0x2000.

Bootloader linker flags:

    -Tbootloader_samd21x18.ld -Wl

And here are the contents of the linker script:

      FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x2000 /* First 8KB used by bootloader */
      RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000-0x0004 /* 4 bytes used by bootloader to keep data between resets */

This is based off of the .cProj file that comes with the linker. It is compiled as a static library so I can include it into my final binary.

**Main Firmware**

My code has both the ArduinoCore and the bootloader static libraries as dependencies:

    libm
    libArduinoCore
    libbootloader

And I am using these linker flags:

    -Tflash_with_bootloader.ld -Wl,--cref -Os -Wl,--check-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align

The contents of this linker script are moved out by 8KB in order to accommodate the bootloader at the start of the binary:

     FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000  /* First 8KB used by bootloader */
        RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000

And yet, my entry point does not appear to ever hit the bootloader. It jumps straight to "main.cpp" from ArduinoCore. The firmware runs as expected, but the bootloader does not appear to have been included.

Is this some kind of dependency issue? Am I misusing the linkers?

Any help with getting this to compile under a single binary would be very much appreciated. Thank you very much!

title: Linking the Arduino Bootloader In Atmel Studio

Answers: 1

body:
This isn't exactly 100% the answer I was looking for, because I still want to know how I can use a static library build, as I mention in my post, and compile everything as a single binary. This method is essentially gluing two binaries together.

I found this great and informative post over here:
https://www.avrfreaks.net/forum/can-you-combine-appbootloader-using-as7

It uses srec_cat to concatenate two binaries after building them:
https://www.keil.com/support/docs/2666.htm

I use the offset specified from the '.ld' file using

```srec_cat <firmware1.bin> -Binary <firmware2.bin> -Binary -offset 0x2000 -o <firmwareOut.bin>```

As the post suggests, I set this up as a post-build event and set my build dependencies accordingly so that a full clean and make will produce a consolidated binary including the bootloader.

If anyone tries this, make sure you only use the non-bootloader binary generated by your main project build. The bootloader places new firmware at location 0x2000 and your firmware will break if it finds a bootloader at the location where the firmware is supposed to be. When uploading firmware to the bootloader, it does not overwrite the bootloader.


body:
I have a code here where I collect an array of data and do some data analysis with the data. The only thing I'm struggle with is how to exit the ISR after I am done running my code. I am using a pre-scalar of 256 and running the ISR once (1Hz)

```
const signed int numReadings = 21;
volatile int gauge0[numReadings];
volatile int gauge1[numReadings];
volatile int add[numReadings];
volatile int deltaGAUGE;
volatile int slopeADD;
volatile int mean;

const int A0_pin = PC0;
const int A1_pin = PC1;

const uint16_t t1_load = 0;
const uint16_t t1_comp = 62500;

void setup() {

  //Set A0 and A1 pins as inputs
  DDRC &= ~(1 << A0_pin);
  DDRC &= ~(1 << A1_pin);

  //Reset Timer1 Control Reg A
  TCCR1A = 0;

  //Set CTC mode
  TCCR1B &= ~(1 << WGM13);
  TCCR1B |= (1 << WGM12);

  //Set to prescaler of 1024
  TCCR1B |= (1 << CS12);
  TCCR1B &= ~(1 << CS11);
  TCCR1B &= ~(1 << CS10);

  //Reset Timer1 and set compare value
  TCNT1 = t1_load;
  OCR1A = t1_comp;

  //Enable Timer1 compare interrupt
  TIMSK1 = (1 << OCIE1A);

  //Enable global interrupt
  sei();

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

}

ISR(TIMER1_COMPA_vect){

       Serial.println(" ");
        for (unsigned int i=0; i<numReadings; i++)
            {
                        gauge0[i] = (analogRead(A0_pin))*(100.00/1024.0);
                        gauge1[i] = (analogRead(A1_pin))*(100.00/1024.0);
                        add[i] = ((gauge0[i]+gauge1[i]));

                        deltaGAUGE = abs(add[20] - add[0]);
                        slopeADD = abs((add[20]-add[0])/(20-0));
                        mean = (add[1]+add[2]+add[3]+add[4]+add[5]+add[6]+add[7]+add[8]+add[9]+add[10]+

                     add[11]+add[12]+add[13]+add[14]+add[15]+add[16]+add[17]+add[18]+add[19]+add[20])/20;

                        if(i == 20)
                {
                      Serial.print("This of the delta AVG reading: ");
                      Serial.println(deltaGAUGE);
                      Serial.println(" ");
                      Serial.print("This of the slope reading: ");
                      Serial.println(slopeADD);
                      Serial.println(" ");
                      Serial.print("This of the mean reading: ");
                      Serial.println(mean);
                      Serial.println(" ");
                      Serial.println("END");
              }

                        delay(50); //wait .05 sec

          }

}

void loop()
{

}

```

When I run the circuit, the interrupt keep executing every seconds for an infinite amount of time, while I just want it to run once and exit.

I have tried the ```exit(0)``` command but I get an output that looks like this
```
START

This of the delta AVG reading: 0

This of t

```

As you can see, The program does not execute completely. Anyone have any idea how I can fix this, or anyhow I can better my code? thank you.

title: How to exit out of a timer interrupt (ISR(TIMER1_COMPA_vect))

Answers: 2

body:
As some of the comments have suggested, I would either get rid of the ISR or reduce the size significantly. When using ISRs, it is recommended that you keep the code as small as possible. Use it to set variables, for example

    //these two variables are global
    ISR(TIMER1_COMPA_vect){
        someValue = true;
        numberOfValues++;
    }

you should also never use any Serial functions inside an ISR as these use interrupts themselves which can cause all kinds of problems

After using the ISR to update global variables, you can then use if() or while() statements within the loop() function to execute your serial print functions and such

P.S. on a side note, I would recommend changing your code where you calculated mean from

        mean = (add[1]+add[2]+add[3]+add[4]+add[5]+add[6]+add[7]+add[8]+add[9]+add[10]+
    add[11]+add[12]+add[13]+add[14]+add[15]+add[16]+add[17]+add[18]+add[19]+add[20])/20;
to

    for(uint8_t i = 1;i<=20;i++){
        mean += add[i];
    }
    mean /= 20;

body: Use ```cli();``` to completely disable interrupt. Then use ```sei();``` to re-enable the interrupt if you need it later.


body:
I have this script where I have connected an ESP-01 to an SSD1306 OLED screen. However, the script I'm using needs adaption for ESP-01 as this module requires the I2C pins to be defined.

So basically I need to add a line that says `Wire.begin(2, 0);` so make the screen work with the ESP-01.

Whoever, I would love to have a check that is wrapped in a `#ifdef` so the code will work out of the box with multiple ESP modules without changing the source code.

Is there some way I can check if the module in use is an ESP-01?

title: Checking what ESP8266 module that is in use

Answers: 0