text:
Arduino pin erratic behavior?
I've built a switch key matrix (thus the diode, contextually useful schematics below) and me being me, I realised after that I misunderstood a few things about how button really works, to say the least...  So anyway, I want to save it so I plan on a solution which, to my surprise, is half-working: When I remake the entier circuit on a breadboard (mistake & solution), it's working but when I do it with my PCB, it doesn't...
The 5V+ is from a digital pin set to HIGH and I've mesured w/ an oscilloscope the tension between the ground and a digital pin ("Arduino INPUT") on the breadboard and on the PCB, with the input pin connected and not connected:

Connected
Not Connected

BreadBoard
2.5V+
5V+

PCB
0V+
5V+

So it's seems like the pin is becoming one with the ground but I can't find anything that could explain this.
I've been testing and trying to understand what the hell was going on for multiple hours now and I runned out of ideas... Does anyone here have an idea of whats might happening ?

this may help ... https://electronics.stackexchange.com/questions/562412/4x4-keyboard-matrix-why-no-pull-down-resistors

Well, that is helpful ! I still need to really understand it but this link seems to help a lot:
https://www.gammon.com.au/forum/?id=14175

look at the "initial case" circuit ... change arduino input to arduino output .... add arduino input to switch pin 1

Yup, I got it but I still would like to understand why it "sinks" the tension...

Are you supplying the breadboard from a 5v power source, other than the one that is supplying the Arduino?
Is there any reason why you are using a diode between the button and the arduino pin?
Arduino can sink and source current and with the 10k resistor that diode is just "dropping" some voltage, i would remove it if you really don't have any other use for it.
If you are supplying the PCB with a different power source than the arduino, you have to "join" the 2 grounds, connect the groud from the power source of the PCB to any ground pin of the arduino. if you could take a photo that could help.
Something like this :

There's a diode because it's a part of a key matrix. The 5V+ is from a digital pin set to HIGH so the breadboard is fed with that.
Regarding the 10k resistor, I know it's a mistake and I'm trying to fix it. The thing is, the fix is acting strangely...
What are you using for your schematics btw ?

But can't you bypass the diode? can you post a picture of how you have the thing connected?
I'm using an old software called Circuit Wizard

It«s really important that you connect the ground of the pcb power supply (if there is a different one) to the arduino ground

@O'Schell the info about the diode belongs in the question ... please edit your question and add the info

Diode info added and the ground on the PCB isn't used in the circuit: I only use the arduino one


text:
Pin outping 1V instead of expected 5V, not hardware related
Heyo everyone !
I'm in a project where I need to send a signal if I detect vaccuum.
I'm sending the signal on PIN 9 but I soon realized that I was only getting 1V.
Tought I was alternating between signal/no_signal but the log provided me with constant and consistent values.
Then I started doubting about my board so I made PIN 10 always output. Under the same load as PIN 9 (I switch the cable connecting from PIN 9 to the circuit, to PIN 10 to the circuit ), I get a good 5V. Thus, I exclude any load problem.
Regarding the PIN output issue, you can all see that it's not missing.
My last hypothesis is that there's some sort of sorcery with my code that I don't know and couln't find on the internet...
Any idea on what might be going on ?
// Constant
const int BL1 = 9;// BINARY LED 1 pin
const int TEST = 10;// BINARY LED 1 pin
const int AP = A0;// ANALOG PRESSOSTAT pin
const int P = 85;// TRIGGER PRESSURE value

// Variables
int LS1 = LOW;  // LED 1 STATE
float RPV = 1; // Raw Pressostat Voltage (0-1024)
float PV = 1; // Pressostat Voltage (V)
float PDP = 20; // Pressostat Deduced Pressure (kPa)

// Initialization of pins at startup
void setup() {
  pinMode(AP, INPUT); // ANALOG PRESSOSTAT pin set as INPUT
  pinMode(BL1, OUTPUT);// BINARY LED 1 pin set as OUTPUT
  pinMode(TEST, OUTPUT);// BINARY LED 1 pin set as OUTPUT
  pinMode(LED_BUILTIN, OUTPUT);// LED_BUILTIN pin set as OUTPUT
  Serial.begin(9600);
}

void loop() {
    digitalWrite(TEST, HIGH);
    RPV = analogRead(AP);
    PV = (RPV/1024)*5;
    PDP = (-1)*(PV-1)*(-101/4);
    Serial.print("Pression: ");
    Serial.print(PDP);
    if ( PDP > P ){
      int LS1 = HIGH;  // LED 1 STATE
      digitalWrite(BL1, HIGH);
      digitalWrite(LED_BUILTIN, HIGH);
      Serial.print(" | LED: 1");
      }
    else {
      int LS1 = LOW;  // LED 1 STATE
      digitalWrite(BL1, LOW);
      digitalWrite(LED_BUILTIN, LOW);
      Serial.print(" | LED: 0");
    }
    digitalWrite(BL1, LS1);
    Serial.print(" | Trigger: ");
    Serial.println(P);

  }

What device is connected to the output pin? How much current does it draw from the pin?

How are you measuring the voltage on pin 9 ? A digital multimeter will tend to integrate and give you an average reading so say 5 volts at a 20% duty cycle will be measured as 1 volt. An oscilloscope, on the other hand, will show a true voltage for the complete waveform.

@6v6gt That's what I (think I) eliminated with my second paragraph. Due to the size of the entiere project (it's only a small part of it), I can't use an oscilloscope...

I don't know but the "always on" pin can hold it... So that's not the issue

@6v6gt UPDATE: I found an oscilloscope that I can use, I'll update you ASAP. Anyway, how, with my code, could I send a HIGH signal 20% of the cycle ?

It is the 20% per cycle thing happening: How does that is happening ?!

Local variable declarations -- See @kiiv's answer: https://arduino.stackexchange.com/a/93195/6628

add a delay(999) to the loop and re-check your multimeter, might not be the steady HIGH you expect.

Here's a working script (I went back to PWM pin, if that matter at all)
void loop() {
  ...// unrelated code
  if (PDP > P) {
    LS1 = HIGH;                               // LED 1 HIGH
    digitalWrite(BL1, LS1);
    digitalWrite(LED_BUILTIN, LS1);
    Serial.print(LS1);
  }
  else {
    LS1 = LOW;                                // LED 1 STATE
    digitalWrite(BL1, LS1);
    digitalWrite(LED_BUILTIN, LS1);
    Serial.print(LS1);
  }
  ...// more unrelated code
}

I'll reduce it a little
void loop() {
    // ... doesn't matter
    if ( PDP > P ){
      int LS1 = HIGH;            // shadows global variable (creates local variable that won't exist after })
      digitalWrite(BL1, HIGH);
    } else {
      int LS1 = LOW;             // again shadows global variable
      digitalWrite(BL1, LOW);
    }
    digitalWrite(BL1, LS1);      // LS1 is still LOW

  }

Mistery solved

Yep, the local variables don't persist outside their scope {}, so the global variable with the same name remains unchanged outside of those scopes.  It could seem like PWM because the internal variables could toggle the pin.

Oh god, how didn't I realized that ?!
Thank you for you enlightening answer ! That's why even my own answer (which was to change to a non PWM pin) revealed itself to not work...

source: Stack Exchange

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/

sort: votes


text:
Arduino UNO stuck at 'uploading' with base sketch, nothing wired
This question has been asked before and I have carefully read the other questions, but the solutions have not worked in my case, and the details are not the same as mine.
Description
The Arduino Uno is stuck at uploading with the error avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x00, with the base sketch.
Details

I am trying with the base empty sketch.
Nothing is wired, nothing connected

Important Remarks

A second Arduino UNO works perfectly fine with the same setup
Loopback test worked - Loopback test instructions
Cable and drivers work fine
Correct port is selected
Rebooting, resetting, upgrading the Arduino IDE have not solved the problem

Important details

The TX LED is slightly but constantly on, and measuring the value of the TX Pin (Digital 1) outputs a value of 2.0 V. This also happens when feeding the Arduino with a 12 V supply, without USB. EDIT Got rid of this part by burning the bootloader via ISP with another Arduino - Bootloader burn instructions
Checking the COM devices via powershell mode outputs something different between the two Arduinos: a locked value of Baud: 115200 for the one not working, while for the one that works it displays Baud: None.

A second Arduino UNO works perfectly fine with the same setup

Sounds like your Uno is faulty. You could read my post here:
Have I bricked my Arduino Uno? Problems with uploading to board
Also What happens when code is uploaded using the bootloader?
The Unos should be simply replaceable. That is, if your setup works on one, then unless you have done something weird to the other one (such as changing the fuses) then that should work too.
Is it a genuine one? Or a cheap knock-off? If it's cheap, well you got what you paid for. Get another.
I have a post on my forum which lets you detect chip signatures and fuses (use your working Uno to run that). It may shed some light on what is happening.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/4.0/


text:
Arduino Uno not interfacing with GSM SIM900A Module
I am using an Arduino Uno with a SIM900A module. I want to send a simple SMS but it is not working, as it either has no response in Serial monitor or there are reversed question marks. I have attached a picture of my setup.

My module didn't work on day, then worked for a day and then now has stopped working, but it is not a hardware issue, as the board switches on and when I try to call the connected SIM, a ring is heard, meaning it has been connected.
I am using a 12V 2A power supply for the board, but I have previously tried with a 12V 1.5A power supply as well, and at the beginning even tried with the Arduino 5V pin. So I do not believe it is a power supply issue either.
Next, I checked the wiring. I confirmed the wires were working by testing them on another sensor, and then used them for this module. I also checked the connections. I have connected the GND pin of the SIM900A to the GND of the Arduino, connected the RX to D9 and then connected the TX to D10. This worked at first, but now shows no response in Serial monitor, so then I tried to reverse the pins (RX to D10 and TX to D9) while keeping the code the same, which produced reversed question marks. But then, upon trying again, this also produced no response.
One of the common online answers was a mismatch in baud rates, so I tried changing the GSM's baud rate from 9600 to everything up to 115200. When the reversed question marks were produced, changing the baud rate just produced weirder characters, and now, as there is no response at all, changing the baud rate has no impact.
I have also tried using pins 2 & 3 and 7 & 8 instead of 9 & 10, but there is no difference.
The code I am currently using is as follows, and is copied directly from here, but I have tried multiple other codes from different solutions to no avail:

SoftwareSerial mySerial(9, 10);

void setup()
{
  mySerial.begin(9600);   // Setting the baud rate of GSM Module
  Serial.begin(9600);    // Setting the baud rate of Serial Monitor (Arduino)
  delay(100);
}

void loop()
{
  if (Serial.available()>0)
   switch(Serial.read())
  {
    case 's':
      mySerial.println("AT+CMGF=1");    //Sets the GSM Module in Text Mode
     delay(1000);  // Delay of 1 second
     mySerial.println("AT+CMGS=\"+91xxxxxxxxxx\"\r"); // Replace x with mobile number
     delay(1000);
     mySerial.println("Technolab creation");// The SMS text you want to send
     delay(100);
     mySerial.println((char)26);// ASCII code of CTRL+Z for saying the end of sms to  the module
      delay(1000);
      break;

    case 'r':
      mySerial.println("AT+CNMI=2,2,0,0,0"); // AT Command to receive a live SMS
      delay(1000);
      break;
  }

 if (mySerial.available()>0)
   Serial.write(mySerial.read());
}

Please help me out, I've tried everything I can think of.

On the Arduino serial monitor - have you set it to "Both NL & CR" ?

the picture is not useful ... it shows two boards and some wires, but it does not show where the connections are

@DrG yes I have set it to Both NL & CR

@jsotola sorry, but the connections are the same as mentioned above.


text:
conflict with different i2c devices
I am trying to communicate with two i2c components using an arduino nano - some ADS1115s and some i2c flow sensors each connected to a different i2c multiplexer, but they seem to be conflicting.
Some of the ADS1115s are 0x49 addresses, the same as all the flow sensors. The full code works, including constructing and initialising the ads1115s, but if I then try to read from them also, I don't get almost any data from the flow sensors (they just read 0 or close to when they should be reading around 8192 for zero flowrate). Any help or suggestions much appreciated!
I've put the full code at the bottom as its quite long and I keep changing it anyway but the important parts are here:
ADS1115:
Adafruit_ADS1115();  //Construct an instance of an ADS1115 with the default address (0x48)
ads1115.begin();  // Initialize ads1115
int16_t readADC_Differential_0_1(void);  //Perform a differential analog to digital conversion on the voltage between channels 0 and 1.

tca9548a multiplexer:
#define TCAADDR 0x70

void tcaselect(uint8_t i) {
  if (i > 7) return;

  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission();
}

tcaselect(i);

Zephyr flow sensors:
void getflows (int sensor, float range, float flowreading) {
Wire.requestFrom(0x49, 2);
while (Wire.available())   // slave may send less than requested
  {
    int flowdata = Wire.read();    // receive a byte as character
    //Serial.println(flowdata);
    flowdata = flowdata << 8;
    flowdata |= Wire.read();    // receive a byte as character
    //Serial.println(flowdata);
    flowreading = range * ((flowdata / 16384.0) - 0.5) / 0.4;
    //Serial.print("sensor 3 flow = "); Serial.println(flow3);
    //Serial.println();         // print the character
    //Serial.println();
  }
  delay(20);

}
The full code:
#include <ModbusRtu.h>
#include <Wire.h>
#include <Adafruit_ADS1015.h>
#include <SPI.h>
#include <PID_v1.h>
#include <math.h>

//modbus
#define ID          1
#define TXEN        2

//valve TTL and DAC CS pins - nos correspond to valve driver numberings in rig box
//Current connections - O2high = 1 = A, CO2 = 2 = B, O2low = 3 = C
#define ATTL       5
#define CTTL       4
#define BTTL       3

#define BCS         7
#define CCS         8
#define ACS         9

#define tempfreq    5
#define tempnum     3
///////////////////////////////////////////
//Sensor ranges - USER DEFINED
float DACrange = 3500.0; //ml/min

int POutrange = 2000; //mbar abs
int PInrange = 2000; //mbar abs
///////////////////////////////////////////

//ADC multiplexer
#define TCAADDR      0x70
#define TCA2ADDR      0x77

//Input resistor values
float         T1R2  =  2320.0;
float         FPR1  =  3090.0;
float         FPR2  =  12010.0;

//max variation from setpoint before PID cycle
int maxdif    =  5;
//max variation from setpoint at end of PID cycle
int PIDdif    =  1;

///////////////////////////////////////////
//MATHS
//scale factor
long FPscale = 10000000;
long flowscale = 10000000;
//vrefs - with scale factors applied
float vref   = 2.5; //tscaled
float Tref   = 1.0; //tscaled
long FPref  = 20000000; //FPscaled
//divisions - integrated to sensor range in long format for calculations
float FPdiv = (FPR1 + FPR2) / FPR2;
int Vmax = 5;

int Poutfac = (int)((POutrange / Vmax) * FPdiv);
int Pinfac = (int)((PInrange / Vmax) * FPdiv);

//ADC mv/bit
float Tbit = 0.00003125;
long FPbit = 625; //- with scale factor of 10,000,000

//temp sensor steinhart constants
double sA = 0.001462146;
double sB = 0.0002393355;
double sC = 0.0000000963049;

//declare holding constants
int16_t hT1 = 0;
int16_t hT2 = 0;
int16_t hT3 = 0;
int16_t hT4 = 0;
int16_t hT5 = 0;
int16_t hT6 = 0;
int16_t hT7 = 0;
int16_t hT8 = 0;

int16_t hFP1 = 0;
int16_t hFP2 = 0;
int16_t hFP3 = 0;
int16_t hFP4 = 0;
int16_t hFP5 = 0;
int16_t hFP6 = 0;
int16_t hFP7 = 0;
int16_t hFP8 = 0;

//intermediates
int i = 0;
int j = 0;
int b[3];
int loopnum = tempfreq;
float tres = 0.0;
double treslog = 0.0;
long lconv = 0;
int16_t O2dif = 0;
int16_t CO2dif = 0;
int16_t N2dif = 0;
int16_t gasdif = 0;
int gasreading = 0;
int hFP = 0;
uint16_t val = 0;
bool truePID;
bool trueAPID = false;
bool trueBPID = false;
bool trueCPID = false;
int (*gasreadfunc)();

int flowdata = 0;
float flow3 = 0.0;
float flow2 = 0.0;
float flow4 = 0.0;
float flow5 = 0.0;
long reading = 0;

uint16_t Setpt;
int CS;
int TTL;

//initialise nested functions
//void eachPID(int16_t (*)(), int16_t, int, bool);

enum
{
  Error1,    //CHANNEL 0  //0
  Error2,    //CHANNEL 1
  FP2a,      //CHANNEL 2  //1
  FP2b,      //CHANNEL 3
  T1a,       //CHANNEL 4  //2
  T1b,       //CHANNEL 5
  T2a,       //CHANNEL 6  //3
  T2b,       //CHANNEL 7
  T3a,       //CHANNEL 8  //4
  T3b,       //CHANNEL 9
  T4a,       //CHANNEL 10 //5
  T4b,       //CHANNEL 11
  Flow2a,    //CHANNEL 12 //6
  Flow2b,    //CHANNEL 13
  Flow3a,    //CHANNEL 14 //7
  Flow3b,    //CHANNEL 15
  Flow4a,    //CHANNEL 16 //8
  Flow4b,    //CHANNEL 17
  Flow5a,    //CHANNEL 18 //9
  Flow5b,    //CHANNEL 19
  A_set,     //CHANNEL 20
  B_set,     //CHANNEL 21
  C_set,     //CHANNEL 22
  HOLDING_REGS_SIZE
};

unsigned int holdingRegs[HOLDING_REGS_SIZE];

/**
    Modbus object declaration
    u8id : node id = 0 for master, = 1..247 for slave
    u8serno : serial port (use 0 for Serial)
    u8txenpin : 0 for RS-232 and USB-FTDI
                 or any pin number > 1 for RS-485
*/
Modbus slave(1, 0, TXEN); // this is slave @1 and RS-485

//Construct ADCs at addresses
Adafruit_ADS1115 adcOne(0x48);
Adafruit_ADS1115 adcTwo(0x49);
Adafruit_ADS1115 adcThree(0x4B);
Adafruit_ADS1115 adcFour(0x4A);

// SPI - set up the speed, data order and data mode
SPISettings settings(4000000, MSBFIRST, SPI_MODE0);

//PID
//Define Variables we'll be connecting to
double Output, Setpoint, Input;

//Define the aggressive and conservative Tuning Parameters
double aggKp = 4, aggKi = 0.2, aggKd = 1;
double consKp = 1, consKi = 0.05, consKd = 0.25;

//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint, aggKp, aggKi, aggKd, DIRECT);

///////////////////////////////////////////////////////////////////////////////////////////////
void tcaselect(uint8_t i, int address) {
  if (i > 7) return;

  Wire.beginTransmission(address);
  Wire.write(1 << i);
  Wire.endTransmission();
}

void setup() {
  ///////////////////////////////////////////////////////////////////////////////////////////////
  //DAC
  pinMode (BCS, OUTPUT);
  digitalWrite(BCS, HIGH);
  pinMode (CCS, OUTPUT);
  digitalWrite(CCS, HIGH);
  pinMode (ACS, OUTPUT);
  digitalWrite(ACS, HIGH);

  pinMode (ATTL, OUTPUT);
  digitalWrite(ATTL, LOW);
  pinMode (CTTL, OUTPUT);
  digitalWrite(CTTL, LOW);
  pinMode (BTTL, OUTPUT);
  digitalWrite(BTTL, LOW);
  ///////////////////////////////////////////////////////////////////////////////////////////////
  //ADC
  adcOne.begin();
  adcTwo.begin();
  adcThree.begin();
  adcFour.begin();

  // 2/3x gain +/- 6.144V  1 bit = 0.1875mV (default)
  // ads1015.setGain(GAIN_ONE);     // 1x gain   +/- 4.096V  1 bit = 0.125mV
  // ads1015.setGain(GAIN_TWO);     // 2x gain   +/- 2.048V  1 bit = 0.0625mV
  // ads1015.setGain(GAIN_FOUR);    // 4x gain   +/- 1.024V  1 bit = 0.03125mV
  // ads1015.setGain(GAIN_EIGHT);   // 8x gain   +/- 0.512V  1 bit = 0.015625mV
  // ads1015.setGain(GAIN_SIXTEEN); // 16x gain  +/- 0.256V  1 bit = 0.0078125mV

  //////////////////////////////////////////////////////////////////////////////////////////////
  //Flow sensor serial number readouts
  getflows(2, 750.0, flow2);
  getflows(3, 400.0, flow3);
  getflows(4, 50.0, flow4);
  getflows(5, 400.0, flow5);

  //////////////////////////////////////////////////////////////////////////////////////////////
  //PID
  //initialize the variables we're linked to
  Input = 0;
  Setpoint = 0;

  //Define the aggressive and conservative Tuning Parameters
  float aggKp = 4, aggKi = 0.2, aggKd = 1;
  float consKp = 1, consKi = 0.05, consKd = 0.25;

  //turn the PID on
  myPID.SetMode(AUTOMATIC);
  //////////////////////////////////////////////////////////////////////////////////////////////
  // start modbus communication
  slave.begin(115200);

  // initialize SPI:
  SPI.begin();

  //Serial.begin(115200);
  gettemperatures();

  holdingRegs[Error2] = 0;
}

void loop() {
  //each tempfreq no of loops, it reads the temp sensors also
  loopnum++;
  if (loopnum > tempfreq) {
    gettemperatures();
    loopnum = 0;
  }

  holdingRegs[Error1] = 0;//set to 0 for normal operation, 65535 = PID control
  //Serial.print("Holding Regs Error1 "); Serial.print(holdingRegs[Error1]); Serial.print(", holdingRegs[Error2]"); Serial.println(holdingRegs[Error2]);

  //flow and pressure sensors
  tcaselect(0, TCAADDR);
  adcOne.setGain(GAIN_TWO);
  //adcTwo.setGain(GAIN_TWO);
  //adcThree.setGain(GAIN_TWO);
  //adcFour.setGain(GAIN_TWO);

  //hFP1 = adcOne.readADC_Differential_0_1();
  hFP2 = adcOne.readADC_Differential_2_3();
  //hFP3 = adcTwo.readADC_Differential_0_1();
  //hFP4 = adcTwo.readADC_Differential_2_3();
  //hFP5 = adcThree.readADC_Differential_0_1();
  //hFP6 = adcThree.readADC_Differential_2_3();
  //hFP7 = adcFour.readADC_Differential_0_1();
  //hFP8 = adcFour.readADC_Differential_2_3();

  //FPconv(hFP1, &holdingRegs[FP1a], &holdingRegs[FP1b], Pinfac);
  //Serial.print("hFP1: "); Serial.println(hFP1);
  FPconv(hFP2, &holdingRegs[FP2a], &holdingRegs[FP2b], Poutfac);
  //Serial.print("hFP2: "); Serial.println(hFP2);
  //FPconv(hFP3, &holdingRegs[FP3a], &holdingRegs[FP3b], CO2fac);
  //Serial.print("hFP3: "); Serial.println(hFP3);
  //FPconv(hFP4, &holdingRegs[FP4a], &holdingRegs[FP4b], O2fac);
  //Serial.print("hFP4: "); Serial.println(hFP4);
  //FPconv(hFP5, &holdingRegs[FP5a], &holdingRegs[FP5b], Finfac);
  //Serial.print("hFP5: "); Serial.println(hFP5);
  //FPconv(hFP6, &holdingRegs[FP6a], &holdingRegs[FP6b], N2fac);
  //Serial.print("hFP6: "); Serial.println(hFP6);
  //FPconv(hFP7, &holdingRegs[FP7a], &holdingRegs[FP7b], Finfac);
  //Serial.print("hFP7: "); Serial.println(hFP7);
  //FPconv(hFP8, &holdingRegs[FP8a], &holdingRegs[FP8b], Finfac);
  //Serial.print("hFP8: "); Serial.println(hFP8);
  //Serial.println("");

  getflows(2, 750.0, flow2);
  getflows(3, 400.0, flow3);
  getflows(4, 50.0, flow4);
  getflows(5, 400.0, flow5);

  flowconvert();

  //modbus communication
  slave.poll( holdingRegs, HOLDING_REGS_SIZE );

  checkgasflow(1);
  checkgasflow(2);
  checkgasflow(3);

  //delay(1000);
}

void gasread(int gastoread) {
  switch (gastoread) {
    case 1: //O2high
      getflows(3, 400.0, flow3);
      gasreading = flow2;
      Setpt = A_set;
      CS = ACS;
      TTL = ATTL;
      truePID = trueAPID;
      //return gasreading;
      break;
    case 2: //CO2
      getflows(4, 50.0, flow4);
      Setpt = B_set;
      CS = BCS;
      TTL = BTTL;
      truePID = trueBPID;
      //return gasreading;
      break;
    case 3: //O2low
      getflows(5, 400.0, flow5);
      Setpt = C_set;
      CS = CCS;
      TTL = CTTL;
      truePID = trueCPID;
      //return gasreading;
      break;
  }
}

void checkgasflow(int gastoread) {
  gasread(gastoread);
  Input = (double)gasreading;
  Setpoint = (double)Setpt;
  gasdif = Input - Setpoint;
  if (abs(gasdif) < PIDdif) {
    truePID = 1;
    return;
  }
  else {
    GasPID();
  }
}

void GasPID() {
  holdingRegs[Error1] = 65535; //set to 0 for normal operation, 65535 = PID control

  //modbus communication
  slave.poll( holdingRegs, HOLDING_REGS_SIZE );

  do {
    eachPID(1);
    eachPID(2);
    eachPID(3);
  } while (!trueAPID || !trueBPID || !trueCPID);

  holdingRegs[Error1] = 0;
}

void eachPID(int gastoread) {
  gasread(gastoread);
  Input = (double)gasreading;
  Setpoint = (double)Setpt;
  gasdif = Input - Setpoint;
  if (abs(gasdif) < PIDdif) {
    truePID = 1;
    return;
  }
  else if (abs(gasdif) < 10)
  { //we're close to setpoint, use conservative tuning parameters
    truePID = 0;
    myPID.SetTunings(consKp, consKi, consKd);
  }
  else
  {
    //we're far from setpoint, use aggressive tuning parameters
    truePID = 0;
    myPID.SetTunings(aggKp, aggKi, aggKd);
  }
  myPID.Compute();
  val = (uint16_t)Output;
  DACspi(CS, val, TTL);
}

void FPconv (int16_t FPin, uint16_t *hRega, uint16_t *hRegb, int FPfac) {
  lconv = (FPfac * (FPref + (long)(FPbit * FPin)));
  memcpy((uint8_t *)hRega, (uint8_t *)&lconv, 2);
  memcpy((uint8_t *)hRegb, (uint8_t *)&lconv + 2, 2);
}

void Flowconv (float FPin, uint16_t *hRega, uint16_t *hRegb) {
  lconv = (long)(FPin*flowscale);
  memcpy((uint8_t *)hRega, (uint8_t *)&lconv, 2);
  memcpy((uint8_t *)hRegb, (uint8_t *)&lconv + 2, 2);
}

void Tconv (int16_t Tin, uint16_t *hRega, uint16_t *hRegb) {
  tres = T1R2 * ((vref / (Tref + (Tbit * Tin))) - 1.0);
  treslog = log(tres);
  lconv = lround(10000000.0 * ((1.0 / (sA + sB * treslog + sC * (pow(treslog, 3.0)))) - 273.15));
  memcpy((uint8_t *)hRega, (uint8_t *)&lconv, 2);
  memcpy((uint8_t *)hRegb, (uint8_t *)&lconv + 2, 2);
}

void DACspi(uint16_t CS, uint16_t val, int TTL) {
  digitalWrite(CS, LOW);
  if (val > 0) {
    digitalWrite(TTL, HIGH);
  }
  else {
    digitalWrite(TTL, LOW);
  }
  SPI.transfer16(val);
  digitalWrite(CS, HIGH);
}

void gettemperatures() {
  tcaselect(6, TCAADDR);
  adcOne.setGain(GAIN_FOUR);
  adcTwo.setGain(GAIN_FOUR);
  adcThree.setGain(GAIN_FOUR);
  adcFour.setGain(GAIN_FOUR);
  //temp sensors - 2 consecutive readings to allow pins to warm up first
  for (i = 0; i < tempnum; i++) {
    hT1 = adcOne.readADC_Differential_0_1();
  }
  for (i = 0; i < tempnum; i++) {
    hT2 = adcOne.readADC_Differential_2_3();;
  }
  for (i = 0; i < tempnum; i++) {
    hT3 = adcTwo.readADC_Differential_0_1();
  }
  for (i = 0; i < tempnum; i++) {
    hT4 = adcTwo.readADC_Differential_2_3();
  }
  //for (i = 0; i < tempnum; i++) {
  //  hT5 = adcThree.readADC_Differential_0_1();
 // }
  //for (i = 0; i < tempnum; i++) {
  //  hT6 = adcThree.readADC_Differential_2_3();
  //}
  //for (i = 0; i < tempnum; i++) {
  //  hT7 = adcFour.readADC_Differential_0_1();
  //}
  //for (i = 0; i < tempnum; i++) {
  //  hT8 = adcFour.readADC_Differential_2_3();
  //}

  Tconv(hT1, &holdingRegs[T1a], &holdingRegs[T1b]);
  //Serial.print("hT1: "); Serial.println(hT1);
  Tconv(hT2, &holdingRegs[T2a], &holdingRegs[T2b]);
  //Serial.print("hT2: "); Serial.println(hT2);
  Tconv(hT3, &holdingRegs[T3a], &holdingRegs[T3b]);
  //Serial.print("hT3: "); Serial.println(hT3);
  Tconv(hT4, &holdingRegs[T4a], &holdingRegs[T4b]);
  //Serial.print("hT4: "); Serial.println(hT4);
  //Tconv(hT5, &holdingRegs[T5a], &holdingRegs[T5b]);
  //Serial.print("hT5: "); Serial.println(hT5);
  //Tconv(hT6, &holdingRegs[T6a], &holdingRegs[T6b]);
  //Serial.print("hT6: "); Serial.println(hT6);
  //Tconv(hT7, &holdingRegs[T7a], &holdingRegs[T7b]);
  //Serial.print("hT7: "); Serial.println(hT7);
  //Tconv(hT8, &holdingRegs[T8a], &holdingRegs[T8b]);
  //Serial.print("hT8: "); Serial.println(hT8);
}

void getflows (int sensor, float range, float flowreading) {
  tcaselect(sensor, TCA2ADDR);
  Wire.requestFrom(0x49, 2);

  while (Wire.available())   // slave may send less than requested
  {
    int flowdata = Wire.read();    // receive a byte as character
    //Serial.println(flowdata);
    flowdata = flowdata << 8;
    flowdata |= Wire.read();    // receive a byte as character
    //Serial.println(flowdata);
    flowreading = range * ((flowdata / 16384.0) - 0.5) / 0.4;
    //Serial.print("sensor 3 flow = "); Serial.println(flow3);
    //Serial.println();         // print the character
    //Serial.println();
  }
  delay(20);
}

void flowconvert (){

  Flowconv(flow2, &holdingRegs[Flow2a], &holdingRegs[Flow2b]);
  //Serial.print("hFP1: "); Serial.println(hFP1);
  Flowconv(flow3, &holdingRegs[Flow3a], &holdingRegs[Flow3b]);
  //Serial.print("hFP1: "); Serial.println(hFP1);
  Flowconv(flow4, &holdingRegs[Flow4a], &holdingRegs[Flow4b]);
  //Serial.print("hFP1: "); Serial.println(hFP1);
  Flowconv(flow5, &holdingRegs[Flow5a], &holdingRegs[Flow5b]);
  //Serial.print("hFP1: "); Serial.println(hFP1);
}

/*void FPconv (int16_t FPin, uint16_t *hRega, uint16_t *hRegb, int FPfac, long FPcal) {
  lconv = (FPfac * (FPcal + FPref + (long)(FPbit * FPin)));
  memcpy((uint8_t *)hRega, (uint8_t *)&lconv, 2);
  memcpy((uint8_t *)hRegb, (uint8_t *)&lconv + 2, 2);
  }*/

/*void GasPID() {
  holdingRegs[Error1] = 65535; //set to 0 for normal operation, 65535 = PID control

  //modbus communication
  slave.poll( holdingRegs, HOLDING_REGS_SIZE );

  tcaselect(0);

  do {
    eachPID(O2read, O2_set, BCS, trueAPID);
    eachPID(CO2read, CO2_set, CCS, trueBPID);
    eachPID(N2read, N2_set, ACS, trueCPID);
  } while (!trueAPID || !trueBPID || !trueCPID);

  trueAPID = !trueAPID;
  trueBPID = !trueBPID;
  trueCPID = !trueCPID;
  }*/

/*
  void eachPID(int16_t gasReadfunc(), int16_t Setpt, int CS, bool truePID, int TTL) {
  Setpoint = (double)Setpt;

  for (i = 0; i < 3; i++) {
    hFP = (*gasreadfunc)();
  }
  Input = (double)hFP;
  gasdif = Input - Setpoint;
  if (abs(gasdif) < PIDdif) {
    truePID = 1;
    return;
  }
  else if (abs(gasdif) < 10)
  { //we're close to setpoint, use conservative tuning parameters
    myPID.SetTunings(consKp, consKi, consKd);
  }
  else
  {
    //we're far from setpoint, use aggressive tuning parameters
    myPID.SetTunings(aggKp, aggKi, aggKd);
  }
  myPID.Compute();
  val = (uint16_t)Output;
  DACspi(CS, val, TTL);
  }*/

/*//Connections
  int16_t O2read() {
  gasread = adcOne.readADC_Differential_0_1();
  return gasread;
  }
  int16_t CO2read() {
  gasread = adcOne.readADC_Differential_2_3();
  return gasread;
  }
  int16_t N2read() {
  gasread = adcTwo.readADC_Differential_0_1();
  return gasread;
  }*/

/*// SPI communication with DAC
  DACspi(BCS, holdingRegs[CO2_set], BTTL); //CO2 controller
  DACspi(CCS, holdingRegs[N2_set], CTTL); //N2 controller
  DACspi(ACS, holdingRegs[O2_set], ATTL); //O2 controller*/

did you run the I2CScanner sketch?

@juraj no, just did! That's it! I'm opening the first multiplexer then opening the second and not closing the first - many thanks

@OliverWalters Please write an answer to your question, so that other can profit from this.

You have another question on that topic, this is solved now as well, I guess?

@SimSon The other topic is different, relating to one multiplexer which isn't functioning

You pass flowreading to void getflows (int sensor, float range, float flowreading) as a value and therefore changing flowreading has no effect on the variable you pass to that function.
Instead, you need to do void getflows (int sensor, float range, float *flowreading).

I had not realised that once opened, the tca9548a channels stay open until either POR or the RESET pin is brought low. Hence when using two multiplexers I just needed to use an extra wire to the RESET pin on each from the nano.


text:
Grounding analogue signals through ads1115
Quick question - I have some pretty expensive gas flow sensors outputting a 0-5V signal, which need at least 2.5 KOhms minimum load. Can I connect them to the Adafruit ADS1115 breakout (ADS1115 chip, Adafruit breakout board circuit, adafruit ferrite bead input impedance (or I think it is, pls correct me if I'm wrong))? If I put a 2KOhm resistor (for example) from the ADS1115 GND to the arduino ground, will that solve this issue, if it exists?
Many thanks for your help
EDIT: The flowmeter manual is here. It states the impedance of the 0-5V receiver should be greater than 2.5KOhms.

It is unclear if the 2500Ω "minimum load" is the minimum resistance value of a load it can have before the voltage starts to droop, or if it's the maximum allowed resistance to create the minimum required current flow.  The "load strength" is generally taken to be the inverse of the resistance (a "stronger" load has a lower resistance). A proper datasheet is needed.

the product webpage that you provided contains a link to customer service for asking questions ... i suggest that you contact them

OK, will do that and get back to you, cheers

@Majenko and jsotola, Hi I got it - it states the receiver impedance should be greater than 2.5KOhms.

@OliverWalters Ok, so since an ADC is typically hundreds of kΩ or even MΩ, that's not a problem.


text:
i2c code hanging - tried all connections
I'm trying to connect a TCA9548a breakout to my nano (also tried using an uno), but it can't recognise it - using the i2c scanner it just hangs on 'scanning...'
I've tried everything suggested in similar posts - checking connections, adding/not adding pullups (this nano I think already has them) and checking other i2c devices using same setup (which work fine). If I connect another i2c device, without the TCA, and have the i2c scanner working well and finding it, then connect SCL from the TCA (whether or not SDA is also connected) the scanner hangs.
When I was checking connections with the tca connected, it did work just once, finding it. Haven't been able to repeat that though since, I can't remember exactly what I was doing at the time.
Any help please?
Thanks in advance
i2c scanner:
// --------------------------------------
// i2c_scanner
//
// Version 1
//    This program (or code that looks like it)
//    can be found in many places.
//    For example on the Arduino.cc forum.
//    The original author is not know.
// Version 2, Juni 2012, Using Arduino 1.0.1
//     Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26  2013
//    V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
//    by Arduino.cc user Krodal.
//    Changes by louarnold removed.
//    Scanning addresses changed from 0...127 to 1...119,
//    according to the i2c scanner by Nick Gammon
//    http://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
//    As version 4, but address scans now to 127.
//    A sensor seems to use address 120.
// Version 6, November 27, 2015.
//    Added waiting for the Leonardo serial communication.
//
//
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
//

#include <Wire.h>

void setup()
{
  Wire.begin();

  Serial.begin(115200);
  while (!Serial);             // Leonardo: wait for serial monitor
  Serial.println("\nI2C Scanner");
}

void loop()
{
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");

      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknown error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(1000);           // wait 5 seconds for next scan
}

tca9548a scanner:
#include "Wire.h"
extern "C" {
#include "utility/twi.h"  // from Wire library, so we can do bus scanning
}

#define TCAADDR 0x74

void tcaselect(uint8_t i) {
  if (i > 7) return;

  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << i);
  Wire.endTransmission();
}

// standard Arduino setup()
void setup()
{
    while (!Serial);
    delay(1000);

    Wire.begin();

    Serial.begin(115200);
    Serial.println("\nTCAScanner ready!");

    for (uint8_t t=0; t<8; t++) {
      Serial.println("selecting");
      tcaselect(t);
      Serial.println("selected");
      Serial.print("TCA Port #"); Serial.println(t);

      for (uint8_t addr = 0; addr<=127; addr++) {
        if (addr == TCAADDR) continue;

        uint8_t data;
        if (! twi_writeTo(addr, &data, 0, 1, 1)) {
           Serial.print("Found I2C 0x");  Serial.println(addr,HEX);
        }
      }
    }
    Serial.println("\ndone");
}

void loop()
{
}

The arduino wire library has the bad habit to hang when the hardware i2c bus is wrong. If you use for example a cable instead of short seperate wires, or if the scl is connected to gnd or when pullup resistors are missing. The arduino nano has no pullup resistors, but the Wire library enables the internal pullup resistors, and that should work for short wires. Do you have a voltage meter to measure the scl and sda? They should be near 5v when the i2c bus is not used.

Use the first scanner sketch to detect the tca multiplexer. Please forget that second sketch that calls twi_writeTo directly. That is an example from adafruit and I thing they made a terrible mistake by using the Wire library like that. Once the tca chip is working, then you can use the function tcaselect and scan each bus from the tca multiplexer.

@Jot Neither sketch detects it. I've just got it connected with the simple blink sketch running on the nano, and a 2K87 pullup from SCL to the Nano +5v, and finding it's only at 1.4V. Is the tca broken perhaps?

It might be broken. Does the tca VIN pin have 5v? On the backside of the tca module are solder pads with tiny connections for the pullup resistors for sda and scl. They are 10k and are default enabled. If you have the tca module on its own (nothing connected) and apply 5v to it, then you can measure the sda and scl pins. If they are low, then it is broken.

OK. I've stupidly already soldered it and can't get to that side anymore. Is there a connection the other side to definitively tell me the same thing? Thanks

Do you have the possibillity to monitor the scl line with an oscilloscope?

@Sim Son no unfortunately not - what would that tell me if I did though?

Detecting the kind of an i2c failure with the software itself is nearly impossible in most cases (e.g. considering the error codes returned by the interface in your code barely help finding a solution). Monitoring the signals externaly can exhibit several problems and help identify the device that causes a problem. Some classics with I2C: SCL keeps low -> likely a clock-stretching slave (does the master support clock-stretching?); bad signal -> capacitance/bus-length/fequency too high; SD remains high -> wrong master configuration (?!)...

so, there are several observations that reliably can only be done with an oscilloscope. I for myself can't remember to ever have found the root of a i2c-related problem without an oscilloscope or a logic analyzer

@SimSon OK many thanks for the info. If you put that as an answer I will mark it correct


text:
Value declared but not coming up as declared
void setup() {
// put your setup code here, to run once:
const int buttonPin2= 2;
const int buttonPin3= 3;
const int buttonPin4= 4;
const int buttonPin5= 5;
int total=0;
int wait=0;
int buttonState = 0;
pinMode(buttonPin2, INPUT);
pinMode(buttonPin3, INPUT);
pinMode(buttonPin4, INPUT);
pinMode(buttonPin5, INPUT);
}
void loop() {
int wait=5000;
while(wait>1)
  buttonState = digitalRead(buttonPin2);
  if(buttonState == HIGH){
    total=total+1
    wait=0
  }else{
    int wait=wait-1
  }
int wait=5000
int buttonState = 0;
while(wait>1)
  buttonState = digitalRead(buttonPin3);
  if(buttonState == HIGH){
     total=total+2
    wait=0
  }else{
    wait=wait-1
  }
int wait=5000
int buttonState = 0;
while(wait>1)
  buttonState = digitalRead(buttonPin4);
  if(buttonState == HIGH){
    total=total+4
    wait=0
  }else{
    wait=wait-1
  }
int wait=5000
int buttonState = 0;
while(wait>1)
  buttonState = digitalRead(buttonPin5);
  if(buttonState == HIGH){
    total=total+8
    wait=0
  }else{
    wait=wait-1
  }
int wait=5000
Serial.begin(9600)
while(0=0)
  Serial.println(total)
}

How about the part where you declare it? Can we see that?

Please, edit the question with the relevant code instead of posting it as a comment.

added the code to the top

You should post the whole code. The buttonState will work as is here. However there is the infinite loop (in while (wait > 1) command;

I'm voting to close this question as off-topic because we cannot work with just snippets of code - you must show your whole code.

Learn the meaning of "Scope".

We can easily make that code compile, but whether it works (does what you want) is a different matter. What are you trying to do?

There are many errors in this code. Below I have high-lighted some of them. Please check your C/C++ language reference(s).
void setup() {
// put your setup code here, to run once:
const int buttonPin2= 2;
const int buttonPin3= 3;
const int buttonPin4= 4;
const int buttonPin5= 5;
int total=0;                        <--- not used in setup()
int wait=0;                         <--- dito
int buttonState = 0;                <--- dito
pinMode(buttonPin2, INPUT);
pinMode(buttonPin3, INPUT);
pinMode(buttonPin4, INPUT);
pinMode(buttonPin5, INPUT);
}
void loop() {
int wait=5000;
while(wait>1)                             <--- missing block { ??
  buttonState = digitalRead(buttonPin2);
  if(buttonState == HIGH){
    total=total+1                         <--- missing semi-colon ;
    wait=0                                <--- dito
  }else{
    int wait=wait-1                       <--- local declare not used
  }
int wait=5000                             <--- illegal redeclare + semicolon
int buttonState = 0;                      <--- illegal redeclare
while(wait>1)                             <--- missing block ;
  buttonState = digitalRead(buttonPin3);
  if(buttonState == HIGH){
     total=total+2                        <--- missing ;
    wait=0                                <--- and so on.
  }else{
    wait=wait-1
  }
int wait=5000
int buttonState = 0;
while(wait>1)
  buttonState = digitalRead(buttonPin4);
  if(buttonState == HIGH){
    total=total+4
    wait=0
  }else{
    wait=wait-1
  }
int wait=5000
int buttonState = 0;
while(wait>1)
  buttonState = digitalRead(buttonPin5);
  if(buttonState == HIGH){
    total=total+8
    wait=0
  }else{
    wait=wait-1
  }
int wait=5000
Serial.begin(9600)
while(0=0)
  Serial.println(total)
}

Start with something much simpler and learn to master the language. Cut-and-paste programming will not help achieve any goals you might have with this sketch. You are simply wasting your time *<:)#

license: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
How can I get the serial monitor in vs code to automatically connect and disconnect when uploading to my arduino?
I am using an Arudino Nano with VS Code and PlatformIO.
When developing. I want to streamline the process so that when I press 1 hotkey.
It will automatically disconnect the Serial Monitor. Build. Upload. Then reconnect the Serial Monitor.
I can partially do it with the "Upload and Monitor" project task:

However, it connects to the serial via the Terminal which means I can't send commands like I do with the serial monitor:

If I connect the serial monitor manually. It does not automatically disconnect so that it can do the upload.
How can I set up vs code with platform io to build, upload, and reconnect the serial monitor with a single hotkey?
Edit:
I managed to get the terminal to allow sending input by adding:
monitor_echo = on

monitor_filters = send_on_enter

To platformio.ini, but it messes up if you try to edit the message with backspace and it does not repeat the last message by pressing the up arrow key like the Serial Monitor tab does.


text:
ESP32 CAM : How to send good quality images via MQTT
Has anyone here ever used a ESP32 CAM to send an image via MQTT? I'd like to know what are the parameters to initialize the camera with (resolution, jpeg quality, etc.), because once I receive the camera on the other side, it's highly compressed and to be frank really ugly.
I'm using FRAMESIZE_SVGA with jpeg quality of 12. I want the best of both worlds actually: I want a good quality image and I don't want to overload the MQTT packet as I want to be able to receive the image faster. If resolution is high, it usually takes a few minutes to receive anything.
Here's my camera's config:
void initCamera()
{
  // https://github.com/botabotlab/ESP32CAM-MQTT/blob/master/ESP32_Cam_MQTT/ESP32_Cam_MQTT.ino (initCamera and capturePicture)
  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer   = LEDC_TIMER_0;
  config.pin_d0       = 5;
  config.pin_d1       = 18;
  config.pin_d2       = 19;
  config.pin_d3       = 21;
  config.pin_d4       = 36;
  config.pin_d5       = 39;
  config.pin_d6       = 34;
  config.pin_d7       = 35;
  config.pin_xclk     = 0;
  config.pin_pclk     = 22;
  config.pin_vsync    = 25;
  config.pin_href     = 23;
  config.pin_sscb_sda = 26;
  config.pin_sscb_scl = 27;
  config.pin_pwdn     = 32;
  config.pin_reset    = -1;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;

  // QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
  // Change resolution of image here
  config.frame_size = FRAMESIZE_SVGA;
  config.jpeg_quality = 10;
  config.fb_count     = 1;

  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  }
}

This question is not really answerable without knowing what is an acceptable compression and resolution. This is really up to you and what you will be using the images for, the update frequency of the images and what bandwidth you have available. As an example, some of my ESP32 cameras are controlled with MQTT but upload via HTTPS at 1280x1024 with quality 8, at around 150KB per uploaded image. But YMMV.

@StarCat Thank you. When you say you upload your images via HTTPS and you send MQTT commands. Do you mean you have a webserver running on the esp32 that posts the image and the MQTT commands are to activate that post?

Good question. I’m using MQTT for controlling the camera (resolution, quality, brightness, contrast, timing of the images etc) and I run a HTTPS client on the ESP32 that uploads each image to my web server that runs a PHP script to receive, store and show the images.

Interesting! Thank you!


text:
POST ESP32 image buffer using HTTPClient to Node.JS API
I'm trying to post the buffer generated by the ESP32 camera to my personal API service I have built with Node.JS. The post gets sent successfully. I have yet to test it on large image (higher resolution).
I'm using a FRAMESIZE_HQVGA,    // 240x176 for my images
void postImage(uint8_t* buf, size_t len)
{
  // prepare JSON document
  DynamicJsonDocument doc(len);
  doc["buffer"] = buf;

  HTTPClient http;

  // Serialize JSON document
  String json;
  serializeJson(doc, json);

  http.begin("http://192.168.0.147:3001/api/pictures");
  http.addHeader("Content-Type", "application/json");

  int httpResponseCode = http.POST(json);

  if (httpResponseCode > 0) {
    // response
    String response = http.getString();
    Serial.println(httpResponseCode);
    Serial.println(response);
  } else {
    Serial.print("Error sending POST: ");
    Serial.println(httpResponseCode);
  }

  // disconnect
  http.end();
}

In my Node.JSside, I receive the buffer but I'm unable to de serialize it to an image. This i smy body:
{ buffer: '����' }

I'm wondering what I'm doing wrong here. Should the image buffer be sent in base64, and if so, how? I want to be able to transform the image buffer into a proper image on the API side.
Here's my how I try to transform the image buffer to a proper image (in my API controller):
    const imageBuffer = Buffer.from(req.body.buffer);
    const filename = `./resources/pictures/image_${Date.now()}.jpg`;

    fs.writeFile(filename, imageBuffer,function(err) {
        if (err) {
            console.log(err);
        } else {
            console.log(`Writing ${filename}`);
        }
    });

is there a specific reason to use JSON?

@Juraj No specific reason. Am I better off without it?

for JSON you would have to encode it as text (base64 is common). but you can upload it as any other classic file upload in the history of the www

JSON is a poor choice for large binary blobs. You would be better off just sending the raw buffer, with appropriate Content-Type (application/octet-stream if no other type is suitable) and Content-Length (the len parameter of postImage()).

@EdgarBonet Tried what you said. The body is empty when I receive the request in the API :/

@Johnnyboy: In that case you should debug the problem. Is the body sent? Did you look at it with a packet sniffer? Is the Node.js server discarding that body?

I'm currently looking at it with a packet sniffer, thank you for the idea! The request does get sent (I console log the request when i receive it, but the body is empty). So it's safe to say the api does see the request

@EdgarBonet Just to confirm. In wireshark, I do see the buffer in the body. For some reason the express API only accepts JSON

@EdgarBonet It works now. Thank you very much for the help! Really appreciate it!

would be better to send it to nodejs as a form file upload to avoid all the extra encoding.

@dandavis, but we are already talking about a binary upload


text:
Keyestudio KS5009 ESP32WROOM32 Smart Home
I'm encountering persistent errors with the sample code provided for my smart home kit project. Despite conducting extensive research and troubleshooting efforts, I haven't been able to find a solution. It's becoming increasingly frustrating as each problem I fix seems to be replaced by another. I'd greatly appreciate any assistance in resolving this ongoing issue.
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiClient.h>
#include <Adafruit_NeoPixel.h>
#define LED_PIN    26
// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 4
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

String item = "0";
const char* ssid = "Temp_Wifi"; //Wifi Name
const char* password = "Temp4"; //Wifif Password
WiFiServer server(80);

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C mylcd(0x27,16,2);
#include <analogWrite.h>
#include "xht11.h"
xht11 xht(17);
//#include <ESP32_Servo.h>
//Servo Wservo;
//Servo Dservo;
#include <ESP32Tone.h>
#define buzzer_pin 25
//#define windowServo 5
//#define doorServo 13
#define waterPin 34
#define fanPin1 19
#define fanPin2 18
#define led_y 12  //Define the yellow led pin to 12

#define waterPin 34
#define gasPin 23
#define pyroelectric 14

unsigned char dht[4] = {0, 0, 0, 0};//Only the first 32 bits of data are received, not the parity bits

//Servo channel
int channel_PWM = 13;
int channel_PWM2 = 10;
int freq_PWM = 50;
int resolution_PWM = 10;
const int PWM_Pin1 = 5;
const int PWM_Pin2 = 13;

void setup() {
  Serial.begin(115200);
  mylcd.init();
  mylcd.backlight();
  pinMode(led_y, OUTPUT);
  pinMode(fanPin1, OUTPUT);
  pinMode(fanPin2, OUTPUT);
  ledcSetup(5, 1200, 8);//Set the frequency of LEDC channel 1 to 1200 and PWM resolution to 8, that is duty cycle to 256.
  ledcAttachPin(fanPin2, 5);  //Bind the LEDC channel 1 to the specified left motor pin GPIO26 for output.
  pinMode(waterPin, INPUT);
  pinMode(buzzer_pin, OUTPUT);
  pinMode(gasPin, INPUT);
  pinMode(pyroelectric, INPUT);
  ledcSetup(channel_PWM, freq_PWM, resolution_PWM); //Set servo channel and frequency as well as PWM resolution.
  ledcSetup(channel_PWM2, freq_PWM, resolution_PWM);
  ledcAttachPin(PWM_Pin1, channel_PWM);  //Binds the LEDC channel to the specified IO port for output
  ledcAttachPin(PWM_Pin2, channel_PWM2);  //Binds the LEDC channel to the specified IO port for output
//  Wservo.attach(windowServo);
//  Dservo.attach(doorServo);
//  #if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
//    clock_prescale_set(clock_div_1);
//  #endif
//    // END of Trinket-specific code.
//  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
//  strip.show();            // Turn OFF all pixels ASAP
//  strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
  Serial.println("TCP server started");
  MDNS.addService("http", "tcp", 80);
  mylcd.setCursor(0, 0);
  mylcd.print("ip:");
  mylcd.setCursor(0, 1);
  mylcd.print(WiFi.localIP());  //LCD displays ip adress
}

void loop() {
  WiFiClient client = server.available();
  if (!client) {
      return;
  }
  while(client.connected() && !client.available()){
      delay(1);
  }
  String req = client.readStringUntil('\r');
  int addr_start = req.indexOf(' ');
  int addr_end = req.indexOf(' ', addr_start + 1);
  if (addr_start == -1 || addr_end == -1) {
      Serial.print("Invalid request: ");
      Serial.println(req);
      return;
  }
  req = req.substring(addr_start + 1, addr_end);
  item=req;
  Serial.println(item);
  String s;
  if (req == "/")  //Browser accesses address can read the information sent by the client.println(s);
  {
      IPAddress ip = WiFi.localIP();
      String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);
      s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n<!DOCTYPE HTML>\r\n<html>ESP32 ip:";
      s += ipStr;
      s += "</html>\r\n\r\n";
      Serial.println("Sending 200");
      client.println(s);  //Send the string S, then you can read the information when visiting the address of E smart home using the browser.
  }
  if(req == "/led/on") //Browser accesses address ip address/led/on
  {
    client.println("turn on the LED");
    digitalWrite(led_y, HIGH);
  }
  if(req == "/led/off") //Browser accesses address ip address/led/off
  {
    client.println("turn off the LED");
    digitalWrite(led_y, LOW);
  }
  if(req == "/window/on")
  {
    client.println("open the window");
    ledcWrite(channel_PWM, 100);  //The high level of 20ms is about 2.5ms, that is, 2.5/20*1024, at this time, the servo angle is 180°.
    //Wservo.write(175);
  }
  if(req == "/window/off")
  {
    client.println("close the window");
    ledcWrite(channel_PWM, 60);  //The high level of 20ms is about 0.5ms，that is, 0.5/20*1024，at this time, the servo angle is 0°.
    //Wservo.write(0);
  }
  if(req == "/music/on")
  {
    //client.println("play music");
  }
  if(req == "/music/off")
  {
    client.println("play music");
    birthday();
    noTone(buzzer_pin,0);
  }
  if(req == "/buz/on")
  {
    client.println("buzzer");
    tone(buzzer_pin,392,250,0);
    Serial.println("1");
  }
  if(req == "/buz/off")
  {
    client.println("off");
    noTone(buzzer_pin,0);
  }
  if(req == "/door/on")
  {
    client.println("open the door");
    ledcWrite(channel_PWM2, 120);
//    Dservo.write(180);
  }
  if(req == "/door/off")
  {
    client.println("close the door");
     ledcWrite(channel_PWM2, 20);
//    Dservo.write(0);
  }
  if(req == "/fan/on")
  {
    client.println("turn on the fan");
    digitalWrite(fanPin1, LOW); //pwm = 0
    ledcWrite(5, 100); //The LEDC channel 1 is bound to the specified left motor output PWM value of 100.
  }
  if(req == "/fan/off")
  {
    client.println("turn off the fan");
    digitalWrite(fanPin1, LOW); //pwm = 0
    ledcWrite(5, 0); //The LEDC channel 1 is bound to the specified left motor output PWM value of 0.
  }
  if(req == "/red/on")
  {
    client.println("red on");
    colorWipe(strip.Color(255,   0,   0), 50);
  }
  if(req == "/red/off")
  {
    client.println("red off");
    colorWipe(strip.Color(0,   0,   0), 50);
  }
  if(req == "/oringe/on")
  {
    client.println("oringe on");
    colorWipe(strip.Color(200,   100,   0), 50);
  }
  if(req == "/oringe/off")
  {
    client.println("oringe off");
    colorWipe(strip.Color(0,   0,   0), 50);
  }
  if(req == "/yellow/on")
  {
    client.println("yellow on");
    colorWipe(strip.Color(200,   200,   0), 50);
  }
  if(req == "/yellow/off")
  {
    client.println("yellow off");
    colorWipe(strip.Color(0,   0,   0), 50);
  }
  if(req == "/green/on")
  {
    client.println("green on");
    colorWipe(strip.Color(0,   255,   0), 50);
  }
  if(req == "/green/off")
  {
    client.println("green off");
    colorWipe(strip.Color(0,   0,   0), 50);
  }
  if(req == "/cyan/on")
  {
    client.println("cyan on");
    colorWipe(strip.Color(0,   100,   255), 50);
  }
  if(req == "/cyan/off")
  {
    client.println("cyan off");
    colorWipe(strip.Color(0,   0,   0), 50);
  }
  if(req == "/blue/on")
  {
    client.println("blue on");
    colorWipe(strip.Color(0,   0,   255), 50);
  }
  if(req == "/blue/off")
  {
    client.println("blue off");
    colorWipe(strip.Color(0,   0,   0), 50);
  }
  if(req == "/purple/on")
  {
    client.println("purple on");
    colorWipe(strip.Color(100,   0,   255), 50);
  }
  if(req == "/purple/off")
  {
    client.println("purple off");
    colorWipe(strip.Color(0,   0,   0), 50);
  }
  if(req == "/white/on")
  {
    client.println("white on");
    colorWipe(strip.Color(255,   255,   255), 50);
  }
  if(req == "/white/off")
  {
    client.println("white off");
    colorWipe(strip.Color(0,   0,   0), 50);
  }
  if(req == "/sfx1/on")
  {
    client.println("sfx1 on");
    rainbow(10);
  }
  if(req == "/sfx1/off")
  {
    client.println("sfx1 off");
    colorWipe(strip.Color(0,   0,   0), 50);
  }
  if(req == "/sfx2/on")
  {
    client.println("sfx2 on");
    theaterChaseRainbow(50);
  }
  if(req == "/sfx2/off")
  {
    client.println("sfx2 off");
    colorWipe(strip.Color(0,   0,   0), 50);
  }

  if(req == "/rain/on")
  {
    int rainVal = analogRead(waterPin);
    client.println(rainVal);
  }
  if(req == "/rain/off")
  {
    client.println("off");
  }
  if(req == "/gas/on")
  {
    boolean gasVal = analogRead(gasPin);
    if(gasVal == 0)
    {
      client.println("safety");
    }
    else
    {
      client.println("dangerous");
    }
  }
  if(req == "/gas/off")
  {
    client.println("off");
  }
  if(req == "/body/on")
  {
    boolean pyroelectric_val = digitalRead(pyroelectric);
    if(pyroelectric_val == 1)
    {
      client.println("someone");
    }
    else
    {
      client.println("no one");
    }
  }
  if(req == "/body/off")
  {
    client.println("off");
  }
  if(req == "/temp/on")
  {
    if (xht.receive(dht)) { //Returns true when checked correctly
      Serial.print("Temp:");
      Serial.print(dht[2]); //The integral part of temperature, DHT [3] is the fractional part
      Serial.println("C");
      delay(200);
    } else {    //Read error
      Serial.println("sensor error");
    }
    client.println(dht[2]);
    delay(1000);  //It takes 1000ms to wait for the device to read
  }
  if(req == "/temp/off")
  {
    client.println("off");
  }
  if(req == "/humidity/on")
  {
    if (xht.receive(dht)) { //Returns true when checked correctly
      Serial.print("Temp:");
      Serial.print(dht[0]); //The integral part of temperature, DHT [3] is the fractional part
      Serial.println("%");
      delay(200);
    } else {    //Read error
      Serial.println("sensor error");
    }
    client.println(dht[0]);
    delay(1000);  //It takes 1000ms to wait for the device to read
  }
  if(req == "/humidity/off")
  {
    client.println("off");
  }

  //client.stop();
}

void birthday()
{
  tone(buzzer_pin,294,250,0);  //The four parameters are pin, frequency, delay and channel
  tone(buzzer_pin,440,250,0);
  tone(buzzer_pin,392,250,0);
  tone(buzzer_pin,532,250,0);
  tone(buzzer_pin,494,250,0);
  tone(buzzer_pin,392,250,0);
  tone(buzzer_pin,440,250,0);
  tone(buzzer_pin,392,250,0);
  tone(buzzer_pin,587,250,0);
  tone(buzzer_pin,532,250,0);
  tone(buzzer_pin,392,250,0);
  tone(buzzer_pin,784,250,0);
  tone(buzzer_pin,659,250,0);
  tone(buzzer_pin,532,250,0);
  tone(buzzer_pin,494,250,0);
  tone(buzzer_pin,440,250,0);
  tone(buzzer_pin,698,250,0);
  tone(buzzer_pin,659,250,0);
  tone(buzzer_pin,532,250,0);
  tone(buzzer_pin,587,250,0);
  tone(buzzer_pin,532,500,0);
  noTone(buzzer_pin,0);  //关闭
}

void colorWipe(uint32_t color, int wait) {
  for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
    strip.setPixelColor(i, color);         //  Set pixel's color (in RAM)
    strip.show();                          //  Update strip to match
    delay(wait);                           //  Pause for a moment
  }
}

// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait) {
  for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) {
    for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
      int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
      strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
    }
    strip.show(); // Update strip with new contents
    delay(wait);  // Pause for a moment
  }
}

// Rainbow-enhanced theater marquee. Pass delay time (in ms) between frames.
void theaterChaseRainbow(int wait) {
  int firstPixelHue = 0;     // First pixel starts at red (hue 0)
  for(int a=0; a<30; a++) {  // Repeat 30 times...
    for(int b=0; b<3; b++) { //  'b' counts from 0 to 2...
      strip.clear();         //   Set all pixels in RAM to 0 (off)
      // 'c' counts up from 'b' to end of strip in increments of 3...
      for(int c=b; c<strip.numPixels(); c += 3) {
        int      hue   = firstPixelHue + c * 65536L / strip.numPixels();
        uint32_t color = strip.gamma32(strip.ColorHSV(hue)); // hue -> RGB
        strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
      }
      strip.show();                // Update strip with new contents
      delay(wait);                 // Pause for a moment
      firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames
    }
  }
}

The current error code I'm encountering during compilation is as follows:
WARNING: library LiquidCrystal_I2C claims to run on avr architecture(s) and may be incompatible with your current board which runs on esp32 architecture(s).
In file included from C:\Users\temp\Downloads\KS5009 Keyestudio Smart Home Kit for ESP32\3. Arduino Tutorials\arduino Code\pj13_2_IoT_smart_home\pj13_2_IoT_smart_home.ino:16:
c:\Users\temp\OneDrive\Documents\Arduino\libraries\Wire\src/Wire.h:44:5: error: 'i2c_t' does not name a type; did you mean 'ino_t'?
     i2c_t * i2c;
     ^~~~~
     ino_t
c:\Users\temp\OneDrive\Documents\Arduino\libraries\Wire\src/Wire.h:64:5: error: 'i2c_err_t' does not name a type; did you mean 'esp_err_t'?
     i2c_err_t last_error; // @stickBreaker from esp32-hal-i2c.h
     ^~~~~~~~~
     esp_err_t
c:\Users\temp\OneDrive\Documents\Arduino\libraries\Wire\src/Wire.h:87:5: error: 'i2c_err_t' does not name a type; did you mean 'esp_err_t'?
     i2c_err_t writeTransmission(uint16_t address, uint8_t* buff, uint16_t size, bool sendStop=true);
     ^~~~~~~~~
     esp_err_t
c:\Users\temp\OneDrive\Documents\Arduino\libraries\Wire\src/Wire.h:88:5: error: 'i2c_err_t' does not name a type; did you mean 'esp_err_t'?
     i2c_err_t readTransmission(uint16_t address, uint8_t* buff, uint16_t size, bool sendStop=true, uint32_t *readCount=NULL);
     ^~~~~~~~~
     esp_err_t
Multiple libraries were found for "Wire.h"
  Used: C:\Users\temp\OneDrive\Documents\Arduino\libraries\Wire
  Not used: C:\Users\temp\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.13\libraries\Wire
exit status 1

Compilation error: exit status 1

Why do you have a second Wire library in your libraries folder? May it be, that this library version does not support the ESP32? Try removing that Wire library from your libraries foldern so that the IDE will use the version that comes with your ESP core

I deleted the Wire library, but I'm still receiving error codes like the ones above with addition to wire.h not being declared error.

It seems there is a lot wrong with the code. The first project supplied to users worked like a charm. The second project had a missing opening curly brace at the second for loop AND the #include <analogWrite.h> has compile issues (but commenting out the #include tag allows the project's library to load and work). This is a treasure trove for troubleshooting fanatics, but a nightmare for beginners.


text:
How do I turn on 3 LEDs in a repetitive sequence where all three LEDs would then turn OFF when the push button used is released?
Basically, how do I modify my code listed below to turn ON each of the three LEDs one at a time in a repetitive sequence while keeping the push-button pressed?

Red (3 sec),
Yellow (1 sec), and
Green (3 sec).

I'm trying to get all three LEDs to turn OFF when the push button is released.
The code I wrote that doesn't allow me to achieve what I'm trying to do (I'm not sure where I went wrong):
#define Button_Pin 2  //Push Button Pin
#define LED_Pin_1 11 //Red LED
#define LED_Pin_2 10 //Yellow LED
#define LED_Pin_3 9  //Green LED

byte Button_State;

void setup() {
  pinMode(Button_Pin, INPUT);
  pinMode(LED_Pin_1,  OUTPUT);
  pinMode(LED_Pin_2,  OUTPUT);
  pinMode(LED_Pin_3,  OUTPUT);

  Serial.begin(9600);
  Serial.println("Design Part B - Digital I-O Control");
  delay(1000);
}

void loop() {
  Button_State = digitalRead(Button_Pin);
  Serial.print("Button State: ");
  Serial.print(Button_State);

  if (Button_State == 1){
    digitalWrite(LED_Pin_1, HIGH);
    delay(3000); //Wait for 3 Secs
    digitalWrite(LED_Pin_2, HIGH);
    delay(1000); //Waits for 1 Sec
    digitalWrite(LED_Pin_3, HIGH);
    delay(3000);
    Serial.println(" --> Button Pressed --> LED ON");
  }
  else{
    digitalWrite(LED_Pin_1, LOW);
    digitalWrite(LED_Pin_2, LOW);
    digitalWrite(LED_Pin_3, LOW);
    Serial.println(" Button is Released --> LED OFF");
  }
}

look carefully at the code inside the if (Button_State == 1){ block .... think about what it does and how long it takes to do it ... then examine the blinkWithoutDelay example sketch in the Arfuino IDE

When you turn yellow on, should red be turned off? Or does it stay on?

I guess that the button pin is wired with an external pull down resistor say 10k.

I've attached what the circuit looks like if that helps clear up anything. I will examine the example sketch you suggested and think more carefully about what that block does and so forth

The clue here is that once your LED sequence has started, it must run to completion - 7 seconds worth - before the button can be detected. Even if you hold the button for, say 3 seconds, starting shortly after the sequence starts, you may give up and release it before the sequence completes, and the code will never have tested it.

here is some code I wrote that uses several timers ... it may give you some ideas ... https://wokwi.com/projects/362275278547275777

Having examined several sample sketches, including the recommended one, and watching instructional YouTube videos to grasp the fundamentals of Arduino programming, I am delighted to announce that my understanding of programming the Arduino and comprehending its functions has significantly improved, considering my novice status.
I can confidently assert that this question has been resolved, and I have enclosed the code that fulfills the initial requirements that was asked of me.
#define pushButton_pin 2
#define grn_LED_pin 9
#define yel_LED_pin 10
#define red_LED_pin 11

bool pushButton_state;

void setup() {
pinMode(pushButton_pin, INPUT);
pinMode(grn_LED_pin, OUTPUT);
pinMode(yel_LED_pin, OUTPUT);
pinMode(red_LED_pin, OUTPUT);

Serial.begin(115200);

Serial.println("Use push button (digital input) to control 3 LEDs (digital
output)");
delay(1000);
}

void loop() {
pushButton_state = digitalRead(pushButton_pin);
Serial.println(pushButton_state);
if (pushButton_state == 1) {
digitalWrite(grn_LED_pin, LOW);
digitalWrite(yel_LED_pin, LOW);
digitalWrite(red_LED_pin, HIGH);
Serial.println(" :push button state is 1, red LED is ON");
delay(2000);
digitalWrite(grn_LED_pin, LOW);
digitalWrite(yel_LED_pin, HIGH);
digitalWrite(red_LED_pin, LOW);
Serial.println(" :push button state is 1, yel LED is ON");
delay(1000);
digitalWrite(grn_LED_pin, HIGH);
digitalWrite(yel_LED_pin, LOW);
digitalWrite(red_LED_pin, LOW);
Serial.println(" :push button state is 1, grn LED is ON");
delay(2000);
} else {
digitalWrite(grn_LED_pin, LOW);
digitalWrite(yel_LED_pin, LOW);
digitalWrite(red_LED_pin, LOW);
Serial.println(" :push button state is 0, all LEDs OFF");
}
delay(500);
}

But it appears that releasing the button has no immediate effect. It must still wait until the full cycle has completed before all leds are switched off. To improve this, you must use a "state machine" type solution as has already been suggested. Using delay() statements is very inflexible. Everything is blocked until these terminate.

I stated that I wanted to get all three LEDs to turn OFF when the push button is released. I should've been clearer about exactly what I wanted to achieve so apologies for the confusion there, however I still wanted it to still run the full cycle when pressed before turning off.

You need a state machine (to remember which LED is currently on) and use millis() to find the current time, in a loop, which is testing whether the switch is closed or not.
If the switch is closed you compare the time now (with millis()) to the time you turned that particular LED on. When the time is up you advance the "state" (eg. a counter) to the next one, and remember the new time that this state change happened.


text:
Connecting pressure sensor to Arduino to collect pressure and time data
I'm trying to build a pressure data logger using an Arduino and Mindman MP47P-03-F1 (https://www.mindman.com.tw/proimages/pdf/E_MP47_S.pdf) pressure sensor, the sensor is connected to an outer 12-24 VDC power source.
I've connected the analog wire to the the Arduino's A0 and added another wire from the GND to the sensor. I get a stable voltage (~1V) reading but the pressure is wrong and it doesn't respond to pressure changes.
Can someone tell me what I'm doing wrong?
this is the sample code:
const int analogPin = A0;
const float slope = -0.1;
const float intercept = 0.6;
const unsigned long startTime = millis();

void setup() {
  Serial.begin(9600);
  Serial.println("Time (s)\t\tPressure (MPa)");
}

void loop() {
  unsigned long elapsedTime = millis() - startTime;
  int sensorValue = analogRead(analogPin);
  float voltage = sensorValue * (5.0 / 1023.0);
  float pressure = slope * (voltage - intercept);

  Serial.println(sensorValue);
  Serial.print(elapsedTime / 1000.0);
  Serial.print("\t\t");
  Serial.println(pressure);

  delay(1000);
}

edit: i've changed the code to as suggested by some on the arduino forum:
const int sensorPin = A0;
const int offset = 201; // zero pressure adjust
const int fullScale = 1023; // max pressure adjust
float sensorType = 1000.0; // kPa
float pressure; // final pressure
const unsigned long startTime = millis();

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

void loop() {
  unsigned long elapsedTime = millis() - startTime;
  pressure = (analogRead(sensorPin) - offset) * sensorType / (fullScale - offset);

  Serial.print(analogRead(sensorPin));
  Serial.print("\t\t");
  Serial.print(elapsedTime / 1000.0);
  Serial.print("\t\t");
  Serial.println(pressure, 4);
  delay(1000);
}

the pressure is 0 but i keep getting jumps in the readings of the pressure when no pressure is applied. here is the picture of the wiring.

the program should be responding to pressure changes ... disconnect the arduino and check the sensor output with a voltmeter

@NickS. - That's a nice comment your wrote! The "Also, your equation is wrong..." part is brilliant, and would be part of a great answer. Perhaps you are not aware that answers in the comments on Arduino SE are frowned upon.

@NickS. - Why not put your "I just gave pointers" part of your comment into an answer? I am certain that the long term members of this stack will agree that  answers and partial answers are not welcome in the question's comment section :) NG

As jsotola mentions in the comments, you should definitely verify that the pressure sensor works with a multimeter first, preferably on a bench that has a variable power supply from which you can power your sensor. Make sure that you can measure the pressure you are putting into the sensor by some other means; a simple pressure gauge could work.
Then, you'll have to correct your equation - it is flipped, since the graphs show the pressure as an input and an output as a voltage, but when you're converting a voltage to a pressure, the process is flipped, so we calculate the slope as follows: take the pressure range (output) and divide it by the voltage range (input) -> 1.1 MPA / 4.4 V = 0.25 V_in. Now, we know that at 0.6V, the pressure output is -0.1 MPA, so we set up a linear equation of the form that you did -> y = mx + b and plug in the values: -0.1 MPA = 0.25 MPA/V * (0.6V) + b. If you solve for b, you'll get -0.25.
Therefore, pressure = 0.25X - 0.25 should be the equation that you check the pressure you're putting into the sensor against the voltage that you are measuring.
If you discover that with this equation you're measuring the right pressure, but once you re-implement your Arduino program you still have no luck, I'd check that the grounds are wired together correctly - it's crucial to have all of the involved grounds at the same 'level'. As a bonus, depending on the Arduino, you could utilize the chip's differential ADC channels, but as far I know, you'd have to write directly to registers to do that.

from where i need to measure the sensor voltage? it has a LCD screen where i can see the pressure changes but the Arduino doesn't see these changes, from 0MPa to 0.008MPa for example

also, from time to time i get voltage spikes that change the pressure reading

You'd measure the voltage from the white wire to the blue wire (from analog out to DC-). Do you actually have a bigger pressure source than that minuscule (probably ambient) value? It's so small, it's less than 1% of the full scale, which is below reasonable SNR based on the +/- 2.5% FS value - it might as well be noise. Do you have a spare bicycle hand pump that you can attach the correct fitting to and try it out? Maybe with a pass-thru gauge? Either way, 1V sounds reasonable for ~0 MPA, so if you aren't applying any pressure that's bigger than ambient that looks ok. What kind of spikes?

How large are the spikes? Do you have a cap on the input to the PS (I only see a hose)? Did you try measuring the output without the Arduino in place, preferably with  a scope? Do you have a second PS you can test (for the future - you should get two next time, so you don't have to try and figure out if you're troubleshooting your connection or the sensor itself)? Did you decouple the power supply from the PS? Why do you need an extra probe to connect the analog output wire to the Arduino itself? Again, ideally you'd have a known non-zero pressure source which you can apply to the PS.


text:
Arduino UNO R3 as flight control plus brushless motor driver
I am trying to build an RC plane using an arduino UNO as the flight control board.
I found a code on the arduino forum for driving a 3 phase AC motor with an arduino.
http://forum.arduino.cc/index.php?topic=8642.0
I believe it will also work for brushless motors commonly used in RC airplanes.This will eliminate the need for an ESC (Electronic Speed Controller) which are pretty expensive.
Now I plan to use a single arduino board to communicate with the nrf2l01 rf receiver , control the servos as well as drive the brushless motor(mentioned above).
In each cycle of the code the arduino will be fetching data from the receiver,sending a pwm signal to the servos and setting which two phases of the brushless motor will be high and which one will be low.
Since so many things are being done in each cycle the phase change of the brushless motor might not be fast enough and this might hamper the motor speed? Or is the arduino  fast enough to handle all this and it won't affect the speed noticeably.

Since so many things are being done in each cycle the phase change of the brushless motor might not be fast enough and this might hamper the motor speed? Or is the arduino fast enough to handle all this and it won't affect the speed noticeably.

This is very much an engineering question. How would one go about answering this?
One method is do a worst-case execution time measurement. Another method is to use control theory and estimate the minimum control frequency for the system (or sub-systems).
Let us assume (for this argument) that the required update frequency is 50 Hz (20 ms cycle time). That gives approx. 320.000 instructions (AVR @ 16 Hz) per control cycle.
The algorithm sketch above in your question is basically dominated by the time to receive the message. This depends on a number of factors; PLL start up, write message from AVR to NRF, transmission frequency, coding, etc, but also message loss and retransmission/acknowledgement. With 2Mbps and 5 byte address, 32 byte payload, and 2 byte checksum the transmission time is at least 300-400 us plus approx 100-200 us for the AVR/SPI to NRF communication. A total of 400-600 us which is well under the 20 ms.
What other design considerations are there? Motor interference on the communication, antenna design, range, protocol design, etc.
Cheers!

Awesome, your answer gave me the insight I was missing. So i  did some calculations to find the maximum time available for each phase change ( If i run a 1000kv motor at 11v, worst case ) which turns out to be ~1818 uS. Thank You.

all_licenses: Creative Commons - Attribution Share-Alike - https://creativecommons.org/licenses/by-sa/3.0/


text:
Win10 PCs won't see ATtiny boards
I bought some ATtiny boards on ebay but I can't get my computers to see them.  When I plug them in I get the USB connected sound then a couple of seconds later it gives the USB unplugged sound.
The power light stays on and the LED blinks, I assume it has the blink sketch already loaded.
I have added the drivers to the IDE but I reckon the problem is before that, something to do with the Win10 PC even seeing it.  I have two versions of the board, one with a USB socket and one with a USB plug, neither work.  [UPDATE] Should have mentioned that the board doesn't show up as being connected to a port
I've looked around for solutions with no joy, I have tried everything I can think of.
Does anyone have a suggestion on where to start troubleshooting this?

Did you try reloading Micronucleus onto them?

Isn't that normal? The board pretends to have a USB interface for a couple of seconds, and then runs the sketch.

@NickGammon  seriously????   I had no idea, I thought it was an error...let me test...

@NickGammon ahhh...but the board doesn't show up as a port...forgot to mention that.  Other boards show up as COM3

YOU GUYS!!!  Between Ignazio and Nick I have solved it.
I wasn't using Micronucleus, I started to.  I thought that no port meant the IDE wouldn't see it but after compiling, and then plugging in the board when prompted it works.  I'll update this as an answer when I can

There were a couple of comments that both led to the solution.
For me the most important was Nick's that the board pretends to have a USB interface for a couple of seconds, and then runs the sketch.  It stopped me tearing my hair out over why the board didn't show up as a port.
Ignacio suggested using Micronucleus.  I did this having installed the Digistump drivers and selecting them.
After compiling I was prompted to plug in the board, voila, it uploaded.
Thanks Stack Exchange!

It's amazing that such a small chip can even simulate USB. There have to be some restrictions on the way it works. Anyway, glad we were able to help.

@NickGammon: The ATtiny85 actually does better than the ATmega328P with V-USB due to the fact that its internal oscillator can be tuned all the way up to 16.5MHz, which opens up almost all Low-Speed USB capabilities.

@IgnacioVazquez-Abrams - yes I suppose, but the Atmega328P can run at 20 MHz. Anyway I was really thinking of squeezing it all into quite a small amount of program memory and RAM.

And THAT @IgnacioVazquez-Abrams is going to be my next question.  512 bytes too big, how to squeeze space.  But I will make it a real question :o)

I have no such luck. The Micronuleous just sits there waiting. After inserting the device. Still nothing. These boards do run the blinky program so it must have got on there somehow.


text:
How do I squeeze code to fit onto an ATTiny
I am using an ATTiny85 for the first time and at compile I receive the following errors
Arduino: 1.6.11 (Windows 10), Board: "Digispark (Default - 16.5mhz)"

C:\Users\Steve\AppData\Local\Temp\build129e80c0e73568918bca55047472d138.tmp/Smoke_Auto-ATtiny.ino.ino.elf section `.text' will not fit in region `text'

c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.9.2/../../../../avr/bin/ld.exe: region `text' overflowed by 562 bytes

collect2.exe: error: ld returned 1 exit status

exit status 1
Error compiling for board Digispark (Default - 16.5mhz).

The chip is
Atmel 1344
Tiny85
20SF

I think what is happening is that my code is too big for the board.  Am I right?
Assuming so, ignoring any obvious programming errors (I can't debug for this board until I can upload :P ) how can I squeeze code like this onto an ATTiny?  I am not looking for someone to rewrite it for me, I am more interested in learning where there is any obvious bloat - I suspect the IR library (IRremote Version 2.0.1 June, 2015 by Ken Shirriff : 11Kb)
FWIW this is a project to convert a manually operated smoke machine into an automatic one and be able to manipulate the smoke time and delay via a remote. It works on a Mega, proof of concept complete, I want to shrink the board to fit into the mouse-sized controller if that is possible.
#include <IRremote.h>

long smokeTimeInit = 5000;  // initial smoke time
long smokeWaitInit = 60000;  // initial interval between smoke

long smokeIncrement = 1000; // timer increment value
long delayIncrement = 5000; // timer increment value

unsigned long previousMillis = 0; // this is our stored time
unsigned long currentMillis;  //where we keep count of time

const int smokeOnPin = 2;  // output to relay
int smokeStopped = false; // flag to stop smoke
const int LED = 0;
const long RECV_PIN = 1;  // input from IR receiver

IRrecv irrecv(RECV_PIN);

decode_results results;

long  smokeTime = smokeTimeInit;
long  smokeWait = smokeWaitInit;

void setup() {
  pinMode(smokeOnPin, OUTPUT);
  pinMode(LED, OUTPUT);

  irrecv.enableIRIn(); // Start the receiver

  digitalWrite(smokeOnPin, LOW);  // start with the smoke on
  digitalWrite(LED, HIGH);

}

void loop() {
  if (irrecv.decode(&results)) {

    switch(results.value){
      case 284157975 :
      //more smoke time
        smokeTime = smokeTime + smokeIncrement;
        smokeStopped = false; // smoke on

      break;
      case 284104935 :
      //less smoke time
        if(smokeTime > smokeIncrement){ // don't let the smoke time become less than the increment value i.e. negative
          smokeTime = smokeTime - smokeIncrement;
        }
        else{
          smokeTime = 1000;
        }
        smokeStopped = false;

      break;
      case 284125335 :
      //reduce interval
        if(smokeWait > delayIncrement){
          smokeWait = smokeWait - delayIncrement;
        }
        else{
          smokeWait = 1000;
        }
        smokeStopped = false;  // smoke on

      break;
      case 284141655 :
      // increase interval
        smokeWait = smokeWait + delayIncrement;
        smokeStopped = false;  // smoke on

      break;
      case 284140125 :
      // reset to initial time values
        smokeTime = smokeTimeInit;
        smokeWait = smokeWaitInit;
        smokeStopped = false;  // smoke on

      break;
      case 284148285 :
      // reset but with shorter smoke time
        smokeTime = 1000;
        smokeWait = 60000;
        smokeStopped = false;  // smoke on

      break;
      case 284123805 :
      // reset with short smoke and shorter interval
        smokeTime = 2000;
        smokeWait = 30000;
        smokeStopped = false;  // smoke on

      break;
      case 284131965 :
      // stop
        smokeStopped = true;
      break;

    }

    irrecv.resume();
  }
currentMillis = millis();

if(smokeStopped){  // don't even do this if smoke stopped
    if (currentMillis - previousMillis >= smokeTime && digitalRead(smokeOnPin)==0) {
      digitalWrite(smokeOnPin, HIGH); // turn the smoke on
      digitalWrite(LED, LOW);
      previousMillis = currentMillis;
    }
    else if (currentMillis - previousMillis >= smokeWait && digitalRead(smokeOnPin)==1 ) {
      digitalWrite(smokeOnPin, LOW); // turn the smoke off
      digitalWrite(LED, HIGH);
      previousMillis = currentMillis;
    }
}

}

Please edit your question to include which ATtiny -- memory sizes vary a lot, eg ATtiny13 at 1K Flash, vs 4K and 8K in ATtiny48 and 88.  Also say which IRremote.h library you have -- some on my system are 2670 bytes of source, vs  2844 and  4381 in other versions.

@jwpat7 thanks for that.  I have added that it is an ATTiny 85 and some info about the IRRemote library.

If dumping the Arduino libraries isn't viable then you could try using a 16kB tinyAVR instead.

I just compiled it for a Leonardo and this:
Sketch uses 10,562 bytes (36%) of program storage space. Maximum is 28,672 bytes.
Global variables use 401 bytes (15%) of dynamic memory, leaving 2,159 bytes for local variables. Maximum is 2,560 bytes.

Yes, the message “... Smoke_Auto-ATtiny.ino.ino.elf section .text' will not fit in regiontext'” suggests the code is too big to fit in the 8K available on the ATtiny85.
[In a .elf file, the TEXT section contains executable code.]
In IRremote.h from  Ken Shirriff et al, some comments at line 28 say to disable protocols you don't need:
// Supported IR protocols
// Each protocol you include costs memory and, during decode, costs time
// Disable (set to 0) all the protocols you do not need/want!

By default, about 13 protocols are enabled and three disabled.  If you only use one or two kinds of remotes, you can  disable a bunch of the protocols.
Here are a couple of minor things for reducing memory, etc.:
• Instead of switching on  results.value, a long, you could compute an unsigned int equal to results.value-284100000, since all of your case values start with 2841 and the largest is 284157975.
• Instead of having smokeStopped = false; // smoke on seven times within various cases, and smokeStopped = true; in one of them, set smokeStopped to false before the switch, and drop the seven settings-to-false from within the switch.
• Some of your time-related variables would be better as unsigned long instead of just long variables.
Generally, your code looks clean enough except for those items.  Also, the IRremote code doesn't look bloated; but its tables can take a lot of memory.
Edit 1–
Addressing crowie's comment about using #define instead of const int, one can use #define's, but in general the modern thought is that const int is preferable for type safety.  Typically there is no difference in generated code – aside from type checking, the compiler treats a const int the same way as a #define, ie does not allocate memory for it if it isn't used, or if the value is small, may use a load-immediate instead of fetching a value from memory.
My own preference is to use enum { ... } to declare integer constants.  For example, instead of
const int smokeOnPin = 2;  // output to relay
const long RECV_PIN = 1;  // input from IR receiver

I'd write
enum { smokeOnPin=2, IRinPin=1 }; // Pin# for smoke on and IR input

This is great, learned a lot before I even try to implement it.  With the smokeStopped flags, my thinking was that if the smoke was stopped and I then changed one of the values with the remote, the smoke would start.  But perhaps that is a luxury I can't afford and I will have to have a 'start' button.

Wow...each of the IR protocols uses 500 bytes, chopping the ones I don't need reduced the size dramatically.

and another thing if you have a constant dont use const variables instead use #define and put the variable nmae in all caps . This a convention of c programming ie #define SMOKEONPIN 2

@crowie, see edit 1

@jwpat7 yes thats a good point I tend to use define because I like sticking to pure C. Arduino is different because it blurs the line between C++ and C and they are different languages even though they look the same. But with #define you can still add the type tag onto the end ie. 100U or 100UL or 100.0f, if you want to be specific about type

@crowie, yes, that's true (re type tags)

Or you could switch on (uint16_t) results.value, since all the codes have the same two significant bytes. Or, if you do not expect invalid codes, on (uint8_t) results.value, since the LSB is enough to tell all the valid codes apart.

The avr-nm tool is great for figuring out what is using up all your memory.
You need to get to a command-line in the temporary directory where your program is compiled. You can find this directory by looking at the scrolling bottom window when you compile your program.
You run the tool like this...

C:\Users\passp\AppData\Local\Temp\arduino_build_965235>"C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\avr-nm" -S --size-sort blink.ino.elf

...where in my case...
C:\Users\passp\AppData\Local\Temp\arduino_build_965235 is  the temporary directory that the Arduino was using
C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\ and the directory where the Arduino toolchain was installed
blink.ino.elf is the output generated from compiling my blink.ino sketch.
The -S parameter tells the tool to output the sizes of the symbols listed. By looking at these sizes, we can figure out what is using up all the memory and where to focus our reduction efforts.
The --size-sort shorts the symbols in size order so we can easily see which are the biggest.
The output of the tool on my program looks like...

0080010b 00000001 b click
0080008e 00000001 B datLen
00800088 00000001 b IRcount.1978
00800089 00000001 B msgNum
00800086 00000001 b prevVals.1995
0080008f 00000001 B progDir
00800087 00000001 b sendState.1979
00800109 00000001 b state
0080010a 00000001 b sync
00800092 00000001 B wake
00800066 00000002 D buttonCB
00800068 00000002 D clickCB
0080010c 00000002 B comBuf
00800115 00000002 B datBuf
0000006a 00000002 T emptyCB
00800075 00000002 D holdoff
0080008c 00000002 B ledMode
00800062 00000002 D longButtonCB
0080006f 00000002 d longPressTime
00800090 00000002 b longPressTimer
00000068 00000002 T loop
0080006a 00000002 D mode
00000d00 00000002 T setPort
00800064 00000002 D timerCB
0080008a 00000002 B timerCBcount
00800060 00000002 D timerCBtime
0080007d 00000003 D black
0080007a 00000003 D dark
0080006c 00000003 D outColor
00800077 00000003 D wakeColor
00000da6 00000004 T __mulsidi3
00800093 00000004 b powerDownTimer
00800131 00000004 B prevTimer
00800097 00000004 B sleepTimer
0080009b 00000004 b startTime
00800071 00000004 D timeout
00800105 00000004 b timer
00000a7a 00000006 T disAD
00800080 00000006 b pulseCount.1996
0080009f 00000006 b timeBuf
0080010e 00000007 B blinking
00800117 00000007 B pulsing
00000a80 00000008 T enAD
000000d4 0000000c T setColorRGB
00000a88 0000000e T initTimer
0000005a 0000000e T setup
00000044 00000010 T __do_clear_bss
0080011e 00000013 B fading
0000002e 00000016 T __do_copy_data
00000d66 00000018 T __udivmodqi4
00000a5c 0000001e T initIO
00000ce0 00000020 t sendByte
00000d44 00000022 T __mulhi3
00000822 00000022 T __vector_3
0000006c 00000022 T getTimer
00000d7e 00000028 T __udivmodhi4
00000e18 00000036 T __epilogue_restores__
00000daa 00000036 T __umulsidi3
00000de0 00000038 T __prologue_saves__
000003e8 00000038 T updateLed
0000027c 0000003a T blink
00000d02 00000042 T sendColor
0000008e 00000046 T tileSetup
00000e4e 0000005c T __muldi3
008000a5 00000060 b times
0000035e 0000008a T pulsingUpdate
000002b6 000000a8 T blinkUpdate
00000a96 000000d4 T hsv2rgb
00000b6a 00000176 T main
000000e0 0000019c T fadeUpdate
00000844 00000218 T __vector_2
00000420 00000402 T __vector_9

The second column is the amount of space used by the symbol.
So just looking at the bottom of our list, we can see that much of the space is being used by the functions main, fadeUpdate, __vector_2 , and __vector_9.
main and fadeUpdate are obvious, but the __vector_x functions are actualy interrupt service routines. The actual mapping of numbers to interrupt sources can be different for different chips, so probably the easiest way to figure out what a given vector is would be to comment out the ISR in your code and then do the above process and see which vector evaporates in size.
You will have to look at each function carefully and individually to see how to possible reduce its size, but at least with this procedure  you know where too look!

thats neat I didn't know about that tool


text:
Can't read two bytes through Serial.read - Arduino
I'm sending via Bluetooth with an Android App two bytes like this:
private void _sendCommand(byte command, byte arg)
{
    if (CONNECTED)
    {
        try
        {
            os.write(new byte[]{command, arg});
            os.flush();

        } catch (IOException e) {
            Log.e(TAG, "Error sending command: " + e.getMessage());

        }
    }
}

And this is the code I'm using to receive them with Arduino:
byte _instruction;
byte _arg;

void loop()
{
  while(Serial.available() < 2)
  {
    digitalWrite(LED_BUILTIN, HIGH);
  }

  digitalWrite(LED_BUILTIN, LOW);

  _instruction = Serial.read();
  _arg = Serial.read();
  Serial.flush();

  switch (_instruction)
  {

     ...

  }
}

I don't have any problems sending just one byte (modifying the code to receive just one), but I can't do the same with two bytes. It's always stuck in the while. Any idea of what I'm doing wrong?

EDIT: As ST2000 pointed out, there was a problem of syncronization, so this is the code working properly:
void loop()
{
  // Wait until instruction byte has been received.
  while (!Serial.available());
  // Instruction should be read. MSB is set to 1
  _instruction = (short) Serial.read();

  if (_instruction & 0x80)
  {
    // Wait until arg byte has been received.
    while (!Serial.available());
    // Read the argument.
    _arg = (short) Serial.read();

    switch (_instruction)
    {
      ...
    }
  }

  Serial.flush();
}

Thanks,

What test data are you using? Try sending printable bytes (ASCII) first.

@MikaelPatel I'm sending as first byte 0x50 and as second byte a value between 0 and 100.

Your code never gets out of the while loop ?

@AndreCourchesne No, it does not.

How was your source code when sending succesfully only one byte ?

Have tried just with a serial port (not bluetooth), using the serial monitor if it works ? Maybe just maybe it's not the receiving end that does not work but rather the transmit side.

I suggest you always pull data in (for example use: "while(Serial.available() == 0);") then process what you expect to be the command and data bytes.  In your code there is nothing to recover from the receiver going out of synchronization with the transmitter.  For all you know, the transmitter has sent the command byte then the data byte.  However, the receiver may have skipped a byte and thinks the data byte is the command byte and is eternally waiting for what it thinks should be the data byte.  Which, of course, will never come.

@st2000 That makes sense, but, how do I recover if I'm out of sync?

By uniquely identifying commands as opposed to data.  Some protocols sacrifice a bit.  For example you could set the most significant bit for commands and not set the most significant bit for data.  However, that does mean you can only send data in the range of 0 to 127.  And it does restrict you to only 128 commands.  If you need more, and want to stick to this "most significant bit" approach, you could break your data into chunks and only send 7 bits at a time.  The possibilities are many.  Use this one or make one up that fits your needs better.

Let us know if this works & I'll copy these comments to the answer section.

@st2000 Thanks, a range of 0 to 127 will do, and 128 commands are more than enough. I'll give it a try as soon as I can.

@st2000 Yes! It's working.

Thanks for following up.  This will make a good question / answer resource for anyone who is having a similar problem.

There may be a underlying problem with synchronizing the transmitter and receiver.  They both have to agree / know which is a command byte and which is a data byte.
In order to do this, some protocols sacrifice a bit. For example you could set the most significant bit for commands and not set the most significant bit for data. However, that does mean you can only send data in the range of 0 to 127. And it does restrict you to only 128 commands. If you need more, and want to stick to this "most significant bit" approach, you could break your data into chunks and only send 7 bits at a time. The possibilities are many. Use this one or make one up that fits your needs better.
In order to implement this approach, you will need to read and process each byte as it arrives.  You can not wait until you accumulate the expected number of bytes as this assume you are always in sync with the transmitter. Which may not be the case.