text:
How to read wireless doorbell's indicator LED circuit
I have a cheap wireless doorbell. My plan is to include an ESP8266 and power the doorbell from the microcontroller 3.3V output as the doorbell also runs on 3V
I specifically chose a model with a LED, as I thought it should be easy to use the LED as a trigger on the ESP8266 and consume as a digital input.
I've soldered two wires from the LED positive and negative solder points. What I find strange is that I measure 3V between the PCB ground and the positive LED wire when the doorbell is not triggered. If I measure between the negative LED wire and positive LED wire, I see a voltage spike corresponding to each LED flash (it flashes 5 times). I plan to debounce this in software.
I did not expect to measure a voltage when the doorbell is not triggered between the positive LED wire and the PCB ground, and this will definitely not work as I intended.
Disclaimer: I'm not an electronic engineer, and my test equipment consists of a multimeter.
I've included a photo of the PCB. It is labelled "QH-823A-19" but searching for this on the Internet has provided no usable information.
What have I tried?

I've tried to trace the tracks running to the LED solder points, but the tracks run under some components which makes this hard
I've tried to measure different points on the board for a positive 3V spike when the LED flashes, no success

Any advice on how to achieve this? Am I going about this the wrong way?

The LED will be wired so  that the anode is connected to +3V and the cathode is connected to the MCU's output pin. Set to HIGH the LED is off, and set to LOW it's on. This is common since historically microcontrollers have been able to sink more current than they can source, and it may be that this one has a specific current limited pin for driving an LED to reduce the number of external components required.

I measured the voltage between the cathode wire and the PCB ground. It reads as high when the LED is not on, but pulses to LOW when the LED starts flashing
Unless I am misunderstanding you, I don't actually want to switch the LED on from the MCU, but rather, detect from the MCU when the LED is ON. I am thinking then that perhaps I can set the input high and detect when it goes low?

Consider tossing away the store bought door bell kit as the ESP processors normally have build with WIFI radios PCB antennas allowing them to connect to your house network directly.  If battery operated, the WIFI option can be replaced by an ESP-NOW network with a software change to the ESP code.  But you will then need to create some sort of mains powered ESP-NOW to WIFI bridge somewhere in your house.

"I measured the voltage between the cathode wire and the PCB ground. It reads as high when the LED is not on, but pulses to LOW when the LED starts flashing"... so @Majenko is correct.  Actually, it should read 3.3V - the LED diode voltage drop.  So maybe 2.5V when high.

You may want to feed the signal through a comparator to ensure that it gets high enough to register as a HIGH on the ESP. Either that or use an analog input to read the voltage, which won't mind if it's not high enough to be HIGH, since you can define your own threshold in software then.

st2000: Yes, also a viable approach. But this is simple and cheap, you still have a working doorbell, and ESP-NOW brings other complexities. I already have a MQTT broker running, this seemed much simpler

Majenko: hoping I can trigger on LOW then, else, reading the analog input is definitely an option

If you have an MQTT broker already running consider adding NodeRED to the same computer.  This will add a graphical programming interface where you can make complex logical decisions based on any number of inputs.  For instance, you could, upon the door bell ring, check if the sun has set in your part of the world and turn on the porch light for 5 minuts if is has.

You can only trigger on LOW if you also don't trigger on HIGH. LOW is only LOW because it's not HIGH. If your "high" voltage level is not high enough to be an actual HIGH then you can't get it to go from HIGH to LOW. You'll just be stuck in an indeterminate area between HIGH and LOW.

Inputs are generally "Schmitt Triggers". You have two thresholds - a high threshold (VIH) and a low threshold (VIL). You have to get above VIH before it switches the input to HIGH. Then it has to get below VIL to switch to LOW. If it never gets to VIH again it will always be LOW even if it is above VIL.

Thanks Majenko, I've accepted your answer and I need to experiment more. I have much more information now to go on

Your LED is connected between V+ and the GPIO of the microcontroller. This is a common arrangement because historically microcontrollers have been able to sink more current than they can source. It's also easier to make a "low side" constant current source, which this custom chip may have, to reduce the number of external components needed.
To read the state you need to take the voltage at the cathode of the LED referenced to the ground of the doorbell circuit. This will give you a voltage at or near the board supply voltage when the LED is off, and a lower voltage (near zero but probably not zero) when the LED is on.
If the voltages are within the threshold voltages VIH and VIL of the ESP8266 then you can just directly read that level as a logic level. If not then you may need to "condition" the voltage to give proper logic levels.
For example you could use a comparator (an op-amp running in "saturated" mode) to compare that voltage to a single threshold voltage that is roughly half way between the HIGH and LOW voltages. That would then swing the output between the supply and ground voltage levels giving you a much cleaner signal.
Or you may use an analog input (the ESP8266 only has one, and that is quite a crude one with only 1.1V maximum allowed on it, so a voltage divider will be needed) to measure the voltage and do the comparison in software.
Another option would be to remove the LED completely and replace it with an optocoupler, thus making the LED itself an electronically operated button to the ESP8266. This will also keep the ESP8266 ganvalically isolated from  the doorbell.

Some feedback on your suggested solution, Majenko.
It is working fine. I decided to go with the optocoupler route, I added a PC817C, on the input side I use the anode and cathode of the led output from the doorbell circuit with a small resistor of 56E, on the output side I have a small debounce circuit, which feeds into a power latch circuit (P and N channel Mosfet) which powers up the ESP8266, it connects to WiFi and sends an MQTT message, and then sets the latch pin low to switch the circuit off again.

Schmitt Trigger using a Comparator
If you follow @Majenko's advice of using a comparator, you could add some hysteresis to it with a few resistors to create an inverting Schmitt trigger. This will increase the noise immunity and thus reduce the noise going to the ESP8266. The following simulation has a noisy input transformed into square pulses. It also performs a small level shift from an input of 3 V to an output of 3.3 V.

Figure 1 – Schmitt trigger circuit.

Figure 2 – Schmitt trigger simulation.
Hysteresis versus Low-Pass Filtering
There is a subtle difference between hysteresis and low-pass filtering.
The following experimental circuit, Figure 3, demonstrates this difference with an interactive simulation where you can click on the switches to add/remove noise and add/remove filtering.
The low-pass filter has a cut-off frequency of 40 Hz.
I've set the high-going threshold, Vt+, to 2.31 V and the low-going threshold, Vt-, to 1.54 V. I calculated these figures from the 74HC14 datasheet using the thresholds for 3 V at 25°C and scaling them for 3.3 V.

Figure 3 – Circuit showing difference between hysteresis and low-pass filtering.
Hysteresis provides greater noise immunity and reshapes a slowly changing signal into a square wave ready for a digital input. But it can't filter out noise spikes that breach its threshold levels. These spikes would cause the Schmitt trigger to output square pulses. See the orange section of Figure 4.
Low-pass filtering filters out high frequency spikes which could breach the upper and lower thresholds of a Schmitt trigger. See the green section of Figure 4. Note that it also introduces a phase shift. If the noise were created by switch-bounce, then the low-pass filter would be performing debouncing. The blue section represents the ideal world where there is no noise, no need of filtering, and the output is in phase with the input.

Figure 4 – Simulation of hysteresis versus low-pass filtering.

Tim, thanks for the suggestion, I've been trying out a 74HC14 as part of a hardware debounce solution and it seems to work well. As I mentioned, I'm a hobbyist, so no electronics engineering background (I'm a comp sci guy). In your provided circuit diagram, is the input signal coming from the left, where I see the 40Hz? What does the line connect to between the bottom resistor and ground going out to the left?

@Wil777, the 74HC14 is a good choice for cleaning up a slowly changing signal and producing a square wave for a digital input, but it won't perform debouncing. Consider a noise spike that crosses both trigger thresholds - it will output a short square wave. Debouncing is performed by a low-pass filter, either in hardware with an RC filter before the Schmitt trigger, or in software with a debouncing algorithm, or both.

Tim, I do have an RC circuit combined with the 74HC14, but my understanding that the 74HC14 also provides hysteresis was based on an article I read on hackaday called "Embed With Elliot: Debounce Your Noisy Buttons"

@Will777, there is a subtle difference between low-pass filtering for debouncing and hysteresis for signal reshaping. I've updated my post to explain it. I've just looked at Eliot's Hackaday articles. He is saying the same thing: Stage 1 - low-pass filter for debouncing; Stage 2 - hysteresis for signal reshaping; Stage 3 - software debouncing algorithm. BTW, here is my "The Ultimate Debouncer(genuine tm)!" or your money back :-)

Thanks Tim, nice article and I see it caters for a lot of different configurations of software debouncing. Since my MCU is powered down, and I am triggering a power latch to start it up from the doorbell, hardware is prefereable for debouncing. It is working very well


text:
ESP32 and SQLite - ALTER TABLE problem
I'm using an ESP32 and SQLite3 from https://github.com/siara-cc/esp32_arduino_sqlite3_lib
Everything is OK except the ALTER TABLE command.
When I try
    ALTER TABLE TAB_JOUEUR RENAME TO TAB_NEW_JOUEUR

I get a "SQL logic error". I just see that the default source code will not compile with the ALTER TABLE option if SQLITE_OMIT_ALTERTABLE is defined.
So at the begining of the .c source, I added:
 #if defined(SQLITE_OMIT_ALTERTABLE)
      #undef SQLITE_OMIT_ALTERTABLE
#endif

But result is the same.... Any idea?

Looks like a known problem with no known fix: https://github.com/siara-cc/esp32_arduino_sqlite3_lib/issues/10

Thank. i'll see if it's also the case with add field.

Well. After searching a lot here's the way todo a "RENAME" for a table. It's a bit tricky...
Renaming table in ESP SQLite is very interesting because SQLite has very limited features for editing table. So you can't add field, remove and so on. The only way is to create a new tmp table, copy the content of the orginal one into this tmp table, drop the original one and rename the tmp with the name of the new one.
DROP TABLE is OK with the ESP version of SQLite, but as said in the question, ALTER RENAME don't work.
So here is the way to do:
1-What tables do we have?
When we init the ESP, we call
  sqlite3_initialize();

and then we give SQLite the file it will use for saving data with a call to sqlite3_open() giving the name of a previously created file.
All our own tables will be saved into this file but also definitions of our tables. For that, SQLite create system table. So in the database we have our own tables but also the SQLlite system tables
2 - The data base schema table
One of the most important table is the database schema one. Its name depend on the version of SQLite. With the version we use on ESP8266 or ESP32, its name is sqlite_master .
This table has 4 fields:

type. Value can be  'table', 'index', 'view', or 'trigger'
name. Value is the name of the data. If type='table', name is the name of
the table defined in this record
tbl_name. Name of the table. So if type='name', tbl_name = name
rootpage. An int which is the index in the Btree used by SQLite to
access the data
sql. The code to create the table

3-Check the schema
To check the content of this specific table, just make a  CREATE TABLE then SELECT * FROM sqlite_master
Here is what I've done and the result:
The CREATE TABLE CALL:
create TABLE    IF NOT EXISTS     TAB_JOUEUR ('tjoueur_id' INTEGER,"tjoueur_prenom" TEXT   , "tjoueur_nom" TEXT,   "tjoueur_ville" TEXT ,  PRIMARY KEY("tjoueur_id" AUTOINCREMENT))
The result of the SELECT * FROM sqlite_master

type = table
name = TAB_JOUEUR
tbl_name = TAB_JOUEUR
rootpage = 2
sql    = CREATE TABLE TAB_JOUEUR ('tjoueur_id'
INTEGER,"tjoueur_prenom" TEXT   , "tjoueur_nom" TEXT,"tjoueur_ville" TEXT ,  PRIMARY    KEY("tjoueur_id" AUTOINCREMENT))

and then

type = table
name = sqlite_sequence
tbl_name = sqlite_sequence
rootpage = 3
sql = CREATE TABLE sqlite_sequence(name,seq)

As you can see the sql field relative to the table "TAB_JOUEUR" as the CREATE call but it's not a pure copy of the original CREATE call. The original one as "create" in lower case, had extra spaces and has a "IF NOT EXISTS" which we don't have in the sql field of sqlite_master. But the part between the () is exactly the same (single quote for tjoueur_id, double for tjoueur_nom, extra spaces...)
4 - The trick
In order to rename a table, you just have to make a SELECT on sqlite_master in order to get the record of the table you want to rename. Then, change the content of the sql field to replace the "old name" by the "new one", and perform an update, using the rootpage as id.
So like that:
void alter_table(String old_name, String new_name){

int rc ;
String data_rootpage;
String data_sql;
int pos_start;
char *err_msg = 0;

String query_sql = "SELECT rootpage,sql FROM sqlite_master WHERE type='table' AND name = '"+old_name+"'";

const char* sql = query_sql.c_str();
rc = sqlite3_prepare_v2(db_handle, sql, -1, &stmt, NULL);
rc = sqlite3_step(stmt);
data_rootpage = (const char *)sqlite3_column_text(stmt, 0);
data_sql = (const char *)sqlite3_column_text(stmt, 1);

// Find first ( in the string
pos_start = data_sql.indexOf ('(');
String tmp = "CREATE TABLE "+new_name+" "+data_sql.substring(pos_start);

query_sql = "UPDATE sqlite_master SET sql='"+tmp+"', name='"+new_name+"', tbl_name='"+new_name+"' WHERE rootpage = "+data_rootpage;
sql = query_sql.c_str();
rc = sqlite3_exec(db_handle, sql, 0, 0, &err_msg);

sqlite3_close(db_handle);
sqlite3_initialize();
sql_connect("/littlefs/transcom.db", &db_handle);}

It's basic and don't have test (you must add some!). I start by searching for the record concerning the "old_name" table. In the sql field I search for the "(" and then I replace the first part of the sql field data with the new name of the table.
Then I update. Notice I don't escape the quote because I've previously make a CREATE call without any ' or " (easier!)
After that, I perform a sqlite3_close() then re-open with sqlite3_initialize(); If you don't do that, SQLite don't take change in account (maybe there is a cache for data).
5 - Great but... not enought!
If you try this, you'll get an error on the update call. That's because for you, "user", sqlite_master is a read only table. So you can't update it. In order to prevent writing on some table (like the sqlite_master one), when SQLite create it, it sets a "read only" flag. The trick is to edit the source code in order to give to this flag, the value of "read and write".
In the sqlite3.c of the LIB, it's a line 17420. You'll see:
  #define TF_Readonly        0x0001    /* Read-only system table */

Just change it by
   #define TF_Readonly        0x0000    /* Read-only system table */

So when SQLite will create a system table, it will set a read+write flag and so, you would be able to update the sqlite_master table. You need to compile again de lib (on Arduino IDE, just select a wrong board, try to compile, get an error, select ESP32 and compile again and the IDE will perform a full compilation of the lib)
If you have trigger, and some other specific feature, maybe it would be nice to check the result of the select * from sqlite_master in order to see if some records need also to be updated. But for basic table, this will do the job.
Hope this will help.
Edit
If you add an index (or more than one) to your table, you'll have also to update 'index" records from sqlite_master. They are like that:

type = index
name = index_ttest_nom
tbl_name = TAB_TEST
rootpage = 6
sql = CREATE UNIQUE INDEX index_ttest_nom ON TAB_TEST (ttest_nom)

So just update the tbl_name value giving the new name of the table, and update the sql field the same way.

source: Stack Exchange

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

sort: votes


text:
MPU6050 does not give output
I need help getting my MPU 6050 to actually give me data. As of right now, my program is only reading 0s from the gyroscope and when I move it, the values all go to -1 and the program just stops until I close and reopen the serial monitor. I know this question has been asked multiple times before, but I've already looked at each of those questions and tried all of the fixes listed there, but not a single one has worked. The I2C scanner does find the sensor at 0x68, but that's only thing that works. These are all brand new boards that I got a couple days ago.
I've tried every library and every example sketch I could find. I've switched to 2 new boards. I've even tried looking at the datasheet for the MPU 6050 and reading/writing the registers directly and still I'm getting no results. The serial monitor either stays blank, shows only 0s or -1s, or just gives me garbage values that change randomly. Please help me.
I've wired the sensor like this (I'm currently on an Arduino Uno):
VCC ==> 5V
GND ==> GND
SCL ==> A5
SDA ==> A4
AD0 ==> digital 13 (set to LOW)
And the code I'm using is this:
#include <Wire.h>

const int addressPin = 13;

int gyroX, gyroY, gyroZ;

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

  //designating pins as I/O
  pinMode(addressPin, OUTPUT);

  //setting IMU address to 0x68 (LOW)
  digitalWrite(addressPin, LOW);

  initializeSensor();
}

void loop() {
  readGyro();

  Serial.print(gyroX);
  Serial.print("    ");
  Serial.print(gyroY);
  Serial.print("    ");
  Serial.println(gyroZ);
}

void initializeSensor() {
  //performing full device reset, disables temperature sensor, disables SLEEP mode
  Wire.beginTransmission(0x68);

  Wire.write(0x6B);
  Wire.write(0b10001000);

  Wire.endTransmission();

  //writing to gyro config register
  Wire.beginTransmission(0x68);

  Wire.write(0x1B);
  Wire.write(0b00001000);

  Wire.endTransmission();
}

void readGyro() {
  //requesting data from gyro data registers
  Wire.beginTransmission(0x68);

  Wire.write(0x43);

  Wire.endTransmission();

  Wire.requestFrom(0x68, 6);

  gyroX = Wire.read()<<8|Wire.read();
  gyroY = Wire.read()<<8|Wire.read();
  gyroZ = Wire.read()<<8|Wire.read();
}

P.S. I few weeks ago I posted a question about I2C devices and in it, I said I had managed to successfully read data from the sensor, but I found out later those were garbage numbers. :(

It would be good to link to the questions on which you tried all solutions so people know exactly what not to repeat.  If you can, inspect the signals with a scope.  One potential difference between the I2C scanner and libraries is the requested clock rate.

From the MPU-6000/MPU-6050 Register Map and Descriptions:

Section 4.28, Register 107 – Power Management 1 PWR_MGMT_1, pages 40 to 41:

Note:
When using SPI interface, user should use DEVICE_RESET (register 107) as well as SIGNAL_PATH_RESET (register 104) to ensure the reset is performed properly. The sequence used should be:

Set DEVICE_RESET = 1 (register PWR_MGMT_1)
Wait 100ms
Set GYRO_RESET = ACCEL_RESET = TEMP_RESET = 1 (register SIGNAL_PATH_RESET)
Wait 100ms

Section 4.26, Register 104 – Signal Path Reset SIGNAL_PATH_RESET, page 37:

Note: This register does not clear the sensor registers. The reset initializes the serial interface as well.

Section 3, Register Map, page 8:

The reset value is 0x00 for all registers other than the registers below.

Register 107: 0x40.
Register 117: 0x68.

This means that the PWR_MGMT_1 register defaults to sleep mode after a reset so it needs to be rewritten to disable sleep mode after commanding a reset.
void initializeSensor()
{
  //
  // Perfrom full reset as per MPU-6000/MPU-6050 Register Map and Descriptions, Section 4.28, pages 40 to 41.
  //

  // performing full device reset, disables temperature sensor, disables SLEEP mode
  Wire.beginTransmission(0x68);  // Device address.
  Wire.write(0x6B);              // PWR_MGMT_1 register.
  Wire.write(0b10001000);        // DEVICE_RESET, TEMP_DIS.
  Wire.endTransmission();
  delay(100);                    // Wait for reset to complete.

  Wire.beginTransmission(0x68);  // Device address.
  Wire.write(0x68);              // SIGNAL_PATH_RESET register.
  Wire.write(0b00000111);        // GYRO_RESET, ACCEL_RESET, TEMP_RESET.
  Wire.endTransmission();
  delay(100);                    // Wait for reset to complete.

  // Disable SLEEP mode because the reset re-enables it. Section 3, PWR_MGMT_1 register, page 8.
  Wire.beginTransmission(IMUAddress);   // Device address.
  Wire.write(0x6B);                     // PWR_MGMT_1 register.
  Wire.write(0b00001000);               // SLEEP = 0, TEMP_DIS = 1.
  Wire.endTransmission();
}

In the following code I've:

Modified readGyro() to implement 3 states (Request, Wait, and Read) and return true when 6 bytes have been read from the MPU-6050.

Added Blink Without Delay to loop() to see whether the MCU freezes which requires changing the ADO pin from pin 13 (the built-in led) to another pin, i.e. pin 12.

Added several Serial.print() statements for debugging to see where things go wrong.

Tweaked the code in response to comments.

#include <Wire.h>

const byte IMUAddress = 0x68;   // Added for readability and maintainability.
const byte addressPin = 12;     // Changed from 13 to 12 because 13 is built-in LED.

int gyroX, gyroY, gyroZ;

void setup()
{
  Wire.begin();
  Serial.begin(115200);
  Serial.println(F("\n\nMPU-6050 Test\n"));

  // Designating pins as I/O.
  pinMode(addressPin, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);  // Added LED for heartbeat signal.

  // Setting IMU address to 0x68 (LOW).
  digitalWrite(addressPin, IMUAddress & 1);  // Added bit mask of bit 0.

  initializeSensor();
}

void loop()
{
  //
  // TASK 1: Blink without delay to indicate that MCU hasn't frozen.
  //
  const unsigned int INTERVAL = 250;
  unsigned long current_timestamp = millis();
  static unsigned long previous_timestamp = current_timestamp;
  static bool led_state = false;
  if (current_timestamp - previous_timestamp >= INTERVAL)
  {
    led_state = !led_state;
    digitalWrite(LED_BUILTIN, led_state);
    previous_timestamp += INTERVAL;
  }

  //
  // TASK 2: Read gyro.
  //
  if (readGyro())
  {
    Serial.print(gyroX);
    Serial.print(F("    "));
    Serial.print(gyroY);
    Serial.print(F("    "));
    Serial.println(gyroZ);
  }
}

void initializeSensor()
{
  //
  // Perform full reset as per MPU-6000/MPU-6050 Register Map and Descriptions, Section 4.28, pages 40 to 41.
  //

  Serial.print(F("Performing full reset of MPU-6050..."));

  Wire.beginTransmission(IMUAddress);   // Device address.
  Wire.write(0x6B);                     // PWR_MGMT_1 register.
  Wire.write(0b10001000);               // DEVICE_RESET, TEMP_DIS.
  Wire.endTransmission();
  delay(100);                           // Wait for reset to complete.

  Wire.beginTransmission(IMUAddress);   // Device address.
  Wire.write(0x68);                     // SIGNAL_PATH_RESET register.
  Wire.write(0b00000111);               // GYRO_RESET, ACCEL_RESET, TEMP_RESET.
  Wire.endTransmission();
  delay(100);                           // Wait for reset to complete.

  Serial.println(F(" Done."));

  // Disable SLEEP mode because the reset re-enables it. Section 3, PWR_MGMT_1 register, page 8.
  Serial.print(F("Disabling sleep mode of MPU-6050..."));
  Wire.beginTransmission(IMUAddress);   // Device address.
  Wire.write(0x6B);                     // PWR_MGMT_1 register.
  Wire.write(0b00001000);               // SLEEP = 0, TEMP_DIS = 1.
  Wire.endTransmission();
  Serial.println(F(" Done."));

  //
  // Writing to gyro config register.
  //
  Serial.print(F("Configuring gyro of MPU-6050..."));
  Wire.beginTransmission(IMUAddress);   // Device address.
  Wire.write(0x1B);                     // GYRO_CONFIG register.
  Wire.write(0b00001000);               // +/-500 deg/s.
  Wire.endTransmission();
  Serial.println(F(" Done."));
}

typedef enum State
{
  Request,
  Wait,
  Read
};

bool readGyro()
{
  static State state = State::Request;

  switch (state)
  {
    case State::Request:
      // Request data from gyro data registers.
      Serial.print(F("Requesting data from gyro..."));
      Wire.beginTransmission(IMUAddress);   // Device address.
      Wire.write(0x43);                     // GYRO_XOUT_H register.
      Wire.endTransmission(false);          // Restart connection, i.e. keep alive.
      Wire.requestFrom(IMUAddress, 6);      // GYRO_XOUT_H, GYRO_XOUT_L, GYRO_YOUT_H, GYRO_YOUT_L, GYRO_ZOUT_H, GYRO_ZOUT_L.
      Serial.println(F(" Done."));
      state = State::Wait;
      Serial.print(F("Waiting for data from gyro..."));
      break;

    case State::Wait:
      // Wait for data to arrive into buffer.
      if(Wire.available() < 6)
      {
        //Serial.print(F("."));
        Serial.print(F(" "));
        Serial.print(Wire.available());  // Added to show bytes received.
      }
      else
      {
        Serial.print(F(" "));
        Serial.print(Wire.available());  // Added to show bytes received.
        Serial.println(F(" Done."));
        state = State::Read;
      }
      break;

    case State::Read:
      // Read data from gyro registers.
      Serial.print(F("Reading gyro data..."));
      gyroX = Wire.read() << 8 | Wire.read();
      gyroY = Wire.read() << 8 | Wire.read();
      gyroZ = Wire.read() << 8 | Wire.read();
      Serial.println(F(" Done."));
      state = State::Request;
      return true;  // Indicate data was received.
      break;
  }

  return false;  // Indicate no data received yet.
}

Update based upon RowanP's answer
While concentrating on the software issues I missed a crucial piece of information from the other datasheet (MPU-6000/MPU-6050 Product Specification), i.e. the electrical characteristics in Sections 6.3 and 6.4 on pages 14 and 15 showing a Vdd range of 2.375 V to 3.46 V:

6.4 Electrical Specifications, Continued

This will require level shifters  on the signals between the 3.3 V MPU-6050 and the 5 V Arduino.

Thanks for the help! I've looked through the checklist that RowanP gave me and fixed anything that I thought might have been wrong, including switching to the 3.3V pin for power on the Uno. I've also used your code and it appears to still only give 0s, but when I rotate the sensor about the y-axis the code gets stuck in the State :: Wait case and only prints periods (but the heartbeat light doesn't stop). Do you have any idea why?

@TobiasGuo, as others have said, the chip could be damaged by a 5 V supply. While 5 V is within the absolute maximum rating of 6 V, it's outside the recommended operating voltage. Do you have level shifters on SCL, SDA and ADO? Try replacing the period print with Serial.println(Wire.available()); to see how many bytes it manages to read.

@TobiasGuo, you could also print and test the return value of each Wire.endTransmission().

@TobiasGuo, did you get it working? I noticed from your question about accelerometer values that you changed the code, i.e. disabled the SLEEP mode without performing a reset because the reset re-enables SLEEP mode (Section 3, PWR_MGMT_1 register, page 8), and used keep-alive with Wire.endTransmission(false) before requesting data.

I haven't tried it yet. I was working on finding some level shifters to attach to the other pins on the MPU so I haven't been able to test the code yet. I will reply with another comment once I have and let you know how things are going! Thanks again for the help!

@TobiasGuo, here is a simple bi-directional level shifter. Click switches.

Thanks! That seems to have fixed the problem! I also switched to using the I2Cdev library and that helped streamline the process of communicating with the sensors, but now my MPUs are actually giving me the correct output!

A while ago while figuring out I2C difficulties of my own I did some research and listed out all the failure modes and test techniques I could think of regarding I2C. See I2C protocol doesn't work properly. I routinely go through the list now to tick off the things I need to check to get a new I2C connection working, usually it's something simple (fingers crossed). Do you have access to an oscilloscpe?
(Edit) This old post seems to describe a similar problem (only getting zeros) MPU6050 doesn't work. The consensus there was that the 3.3V MPU6050 had been connected to a 5V UNO, frying the MPU6050 chip. That sounds very like your situation.

Thanks for linking that checklist. I will run through that to see if I have missed anything or if there is anything else I can do to fix it. I was under the impression that the VCC pin on the MPU 6050 was designed to be able to handle a 5V power supply, but maybe I was wrong. I will definitely try switching to a 3.3V power supply!

What module are you using?  I'm using the DFRobots 6DOF module (https://wiki.dfrobot.com/6_DOF_Sensor-MPU6050__SKU_SEN0142_) and it works fine with a 5V supply.  You might also try taking a look at this (https://www.fpaynter.com/2019/10/basic-arduino-mpu6050-gy-521-test/) and related articles about the MP6050 on my website (fpaynter.com)

I went back and checked my most recent use of an MPU6050 module, and notwithstanding the link I posted in my answer, I agree with @user3765883, the modules I've had are 5V tolerant as well. I don't have a schematic, but looking at the module closely there is a power regulator onboard marked 4A20. Depending on the specific module you're using I think the previous link about the MPU6050 chip being 3.3 V may be a red herring!

OK, so there is evidence of at least two different types of modules in circulation. One with a 5 to 3.3 V power regulator and one without. See https://forum.arduino.cc/t/mpu6050-eagle-files-out-of-date/633197

I used 5 V from my Arduino to power the MPU6050, and it was fine. Check out: https://www.instructables.com/How-to-Make-a-Robot-Car-Drive-Straight-and-Turn-Ex/, which has very similar code.
Also, I typically avoid pin 13, since it performs some special additional function, unlike pin 2 to 12.

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


text:
SIM800L and UNO can't request web page
I know this module is super old but the network I am on still uses GPRS so should work.
This is the module:

I am using the Adafruit example scipt FONAtest. I can connect to GPRS
    <--- SHUT OK
    ---> AT+CGATT=1
    <--- OK
    ---> AT+SAPBR=3,1,"CONTYPE","GPRS"
    <--- OK
    ---> AT+SAPBR=3,1,"APN","live.vodafone.com"
    <--- OK
    ---> AT+CSTT="live.vodafone.com","",""
    <--- OK
    ---> AT+SAPBR=3,1,"USER",""
    <--- OK
    ---> AT+SAPBR=3,1,"PWD",""
    <--- OK
    ---> AT+SAPBR=1,1
    <--- OK
    ---> AT+CIICR
    <--- OK
FONA>

There is credit on the SIM so it has data for sure, I can also send SMS.
There are several different approaches people seem to take (altering AT commands) to persuade this device to work, pretty sure I have tried all of them :) I always get a timeout when trying to read or GET a webpage.
I have tried several combinations via terminal and I seem to connect ok but get no further. It has worked once, but that was in a different part of town.
How do I check that the GPRS is actually connected? Any troubleshooting tips?
There is a dedicated 2A 5V connected to the unit, it isn't dropping out AFAIK. Do you have a rock-solid AT sequence that always works?
Also, there seem to be SAPBR commands that don't work at all, not sure why?

You should check whether the GPRS is attached with AT+CGATT?, after sending AT+CGATT=1, if it return +CGATT: 1, it means it is attached and you can proceed for the next step.

It highly depends on the URL you are trying to fetch.
Those modules DO NOT understand secure HTTP/S. They only understand plain unsecure HTTP.
Most web pages nowdays don't offer unsecure HTTP access and always redirect the request to a HTTP/S server. So in my opinion the usefulness of those devices is very limited when it comes to internet access.
If you have full control over the web server you should disable the enforcement of a secure connection.
Beyond that. The sequence you posted is just for activating GPRS.
I also found the FONA sample for fetching a page not very reliable but I was able to request the page multiple time. Perheps you have your module in a place with low signal strenght. Does your module offer an u.fl connector for a better antenna?

It does have a u.fl connector and I have the bundled antenna attached. The RSSI is -89 which I think isn't great. The code I always get is 603

I do have control over the webserver and it is http

Don't know why, I had to manually set the DNS t0 8.8.8.8 using AT+CDNSCFG?
It had DNS entries in there but they didn't want to resolve for some reason.


text:
Pro Mini - Using RAW pin for 3.3v input
I design a PCB that one of its components is a 3.3v Pro Mini. Since I want it versatile regarding powering the PCB (3.3v or 5.0v) I want to know if it is a good practice to supply 3.3v to Pro Mini's RAW pin( rather than to the VCC Pin ).

It is not ideal, no.  The RAW pin first goes into a 3.3V voltage regulator whose dropout voltage is up to 200mV (worst case).  That means that you would get around 3.1V out, and it wouldn't be properly regulated.
Oh, it would work, but the power won't be stable, which means that any analogue readings that you make that don't directly use the (shakily) regulated "3.3V" (now 3.something else V) in the generation of the analog signal (such as a simple potentiometer) will be inaccurate.
Also output logic voltages will be lower than expected which may have an effect if communicating with something whose upper input threshold is at or near the 3.3V mark (such as many 5V devices).

Thank you Majenko, those are the exact reasons I wanted to be sure of. Guy


text:
Accelerometer value meaning
I'm currently using the MPU-6050 accelerometer to receive the acceleration and angular velocity data. I'm trying to process the data for my experiment but I can't understand the exact meaning of it. I have threee questions about the situation. I append the arduino code below.
First, I happen to know that the AcX value of the code below means how much the sensor is inclined along the x axis. Is there other way to get acceleration directly? or Do I have to use formula(v = v_0 + a*t)?
Second, for the gyro sensor, I can't understand the meaning of the value. Does it sends the angular velocity or angular acceleration and if it is one of these, what's the limit?
Third, according to code, it receives data in the form of 2^14(14bit) but sometimes it sends value way over the limit. How can I translate raw data to rather regular unit like degree and rad?
Thank you
const int MPU_addr=0x68;  // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,GyX,GyY,GyZ;

void setup(){
  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  Serial.begin(9600);
  Serial.println("CLEARDATA");
  Serial.println("LABEL,TIME,AcX,AcY,AcZ,GyX,GyY,GyZ");
}

void loop(){
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr,14,true);  // request a total of 14 registers

  // deviding the 16bit input??
  AcX=Wire.read()<<8|Wire.read();  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
  AcY=Wire.read()<<8|Wire.read();  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ=Wire.read()<<8|Wire.read();  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  GyX=Wire.read()<<8|Wire.read();  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GyY=Wire.read()<<8|Wire.read();  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GyZ=Wire.read()<<8|Wire.read();  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)

  //Serial.print("AcX = ");
  Serial.print(AcX);
  Serial.println(",");
  //Serial.print(",");
  //Serial.print(" | AcY = ");
  //Serial.print(AcY); Serial.print(",");
  //Serial.print(" | AcZ = ");
  //Serial.print(AcZ); Serial.print(",");
  //Serial.print(" | GyX = ");
  //Serial.println(GyX);
  //Serial.print(" | GyY = ");
  Serial.println(GyY); //Serial.print(",");
  //Serial.print(" | GyZ = ");
  //Serial.println(GyZ);
  delay(200);
}

Doesn't the datasheet answer these questions?

Is there other way to get acceleration directly? or Do I have to use
formula(v = v_0 + a*t)?

The code appears to be currently retrieving the raw X, Y & Z acceleration and storing it in AcX, AcY & AcZ.  The equation "v = v_0 + a*t" appears to be deriving velocity.  So the question is confusing.

...for the gyro sensor, I can't understand the meaning of the value. Does
it sends the angular velocity or angular acceleration

The accelerometer sensors measure acceleration.  As the last question ultimately asked for angles, the gyroscope is not needed.  However, on page 12 in the MPU-6050 specifications the dimensions of the gyroscope is given in degrees per second or angular velocity.  Likely the mechanism within the chip depends on the Coriolis effect

...and if it is one of these, what's the limit?

On the same page the MPU-6050 chip specification shows a table containing values such as GYROSCOPE SENSITIVITY & Full-Scale Range.  Consider reading these and other values regarding the gyroscope.

...according to code, it receives data in the form of 2^14(14bit) but
sometimes it sends value way over the limit.

The code retrieves a high 8 bit and low 8 bit value for each axis of the accelerometer and the gyroscope.  This makes a 16 bit value.  Not a 14 bit value.

How can I translate raw data to rather regular unit like degree and
rad?

To obtain an angle in degrees only the accelerometer is required.
Consider calibrating the accelerator for offset and magnitude errors before using the raw values.
Consider constraining the problem such that the accelerometer is only rotated around the Z-axis.
The angle can be found by taking the inverse tangent of the ratio of the calibrated X acceleration and calibrated Y acceleration.

Other considerations:

If angles are desired in 3 dimensional space consider using commonly referred to values such as pitch, roll & yaw.  In which case many situate the accelerometer such to use these equations:

The above equations, a discussion and some example code can be found here.

So far, all the equations discussed use trigonometry and can go to infinity (unusable results) given certain inputs.  The mathematical equivalent of gimbal lock if you will.  To avoid this consider using quaternions.  This mathematical method of representing rotation in 3 dimensional space does not suffer the above problem, is easier for computers to calculate and is used extensively in computer graphics.

Re “All the sensors measure acceleration”: gyroscopes measures angular velocity, not angular acceleration. The unit used in the datasheet for gyro data is degrees per second.

That's interesting.  I can't imagine how mechanically such a device is made.  If you and I are both correct, then the MPU-6050 must be doing some type of integration to get velocity (i.e. to get a constant value for a MPU-6050 gyroscope situated at the center of an operating 33 & 1/3 RPM phonograph record player).

Ah, never mind, I see how it's done: Coriolis effect.  Learn something new everyday.

FYI, for anyone reading this, looking at the answer and scratching their head ... I changed the answer to match what @EdgarBonet was commenting on.  Thank Edgar!

"currently retrieving the raw X, Y & Z acceleration" While processing data with python code below, I happen to know that it's the location data. Can you explain what's going on?

So, the sensor gets the acceleration(may be loaction) and angular velocity data(maximum 2000 dps -according to the specification) in the form of 16bit(+,-). And for the translation, I may have to regard other values or formula. Am I right?

@JohnCho, the integral of acceleration gives velocity and the integral of velocity gives location. Consider opening a separate stack exchange question with your Arduino code regarding this or switch to another stack exchange site like Physics or Math with a more general question about acceleration, velocity and position.

@st2000, I was just curious about the data which seems to send location even though it has the name of AcX. By the way, Thanks!

Curiosity is a good thing!  I have only worked with a couple of IMUs.  But have found they report acceleration (and, of course, angular velocity).  Keep in mind deriving position from acceleration is very difficult. Deriving position is not ordinarily done with only acceleration data.  The difficulty comes when dealing with the accumulated errors. The only exception I am aware of is gaming.  Here, since you are in a virtual world, ending up half way across the living room, as long as you don't hit anything, isn't that big of a deal.

Ok, I've misunderstood the acceleration sensor. Thanks!


text:
how can I accurately recieve potentiometer values over the USB port?
I want to read the analog values of my ardunio uno into a separate c++ program. On the Arduino I have a serial port initialized for 9600 baud:
int sensorPin = A0;    // select the input pin for the potentiometer

int sensorValue = 0;  // variable to store the value coming from the sensor

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

void loop() {
  // read the value from the sensor:
  sensorValue = analogRead(sensorPin);
  Serial.println(sensorValue);
}

The output value should be right around 390, given the current settings. My serial port reading code seems to read the port fine, but only displays some of the characters sometimes.... some of the time, it reads the value fine. other times I get one or 2 of the characters, such as 3, or 39.
#include <stdio.h>      // standard input / output functions
#include <stdlib.h>
#include <string.h>     // string function definitions
#include <unistd.h>     // UNIX standard function definitions
#include <fcntl.h>      // File control definitions
#include <errno.h>      // Error number definitions
#include <termios.h>    // POSIX terminal control definitions
#include <iostream>
using namespace std;

int main(){
    const char* device ="/dev/ttyACM0";
/* Open File Descriptor */
//int USB = open( device, O_RDWR| O_NONBLOCK | O_NDELAY );
int USB = open( device, O_RDWR| O_NOCTTY );

/* Error Handling */
if ( USB < 0 ){
cout << "Error " << errno << " opening " << device << ": " << strerror (errno) << endl;
}

/* *** Configure Port *** */
struct termios tty;
struct termios tty_old;
memset (&tty, 0, sizeof tty);

/* Error Handling */
if ( tcgetattr ( USB, &tty ) != 0 ) {
   cout << "Error " << errno << " from tcgetattr: " << strerror(errno) << endl;
}

/* Save old tty parameters */
tty_old = tty;

/* Set Baud Rate */
cfsetospeed (&tty, (speed_t)B9600);
cfsetispeed (&tty, (speed_t)B9600);

/* Setting other Port Stuff */
tty.c_cflag     &=  ~PARENB;            // Make 8n1
tty.c_cflag     &=  ~CSTOPB;
tty.c_cflag     &=  ~CSIZE;
tty.c_cflag     |=  CS8;

tty.c_cflag     &=  ~CRTSCTS;           // no flow control
tty.c_cc[VMIN]   =  1;                  // read doesn't block
tty.c_cc[VTIME]  =  5;                  // 0.5 seconds read timeout
tty.c_cflag     |=  CREAD | CLOCAL;     // turn on READ & ignore ctrl lines

/* Make raw */
cfmakeraw(&tty);

/* Flush Port, then applies attributes */
tcflush( USB, TCIFLUSH );
if ( tcsetattr ( USB, TCSANOW, &tty ) != 0) {
   cout << "Error " << errno << " from tcsetattr" << endl;
}

if ( tcsetattr ( USB, TCSANOW, &tty ) != 0){
cout << "Error " << errno << " from tcsetattr" << endl;
}

/* Allocate memory for read buffer */
char buf [1024];
memset (&buf, '\0', sizeof buf);

/* *** READ *** */
int n = read( USB, &buf , sizeof buf );
cout << "buffer: " << &buf << endl;
/* Error Handling */
if (n < 0)
{
     cout << "Error reading: " << strerror(errno) << endl;
}

/* Print what I read... */
cout << "Read: " << buf << endl;

close(USB);
 return 0;
}

How can I read the correct value being sent every time?

https://www.arduino.cc/en/tutorial/potentiometer

It's odd that you don't care about Serial.print(), since it is the sort of thing Arduino gives to allow conveying data over a serial connection.  You mention "stable connection"; does this mean you have found your serial connection to be unstable?

I know how to set the arduino to send data on the serial port, its the receiving it elsewhere that I am struggling with. My interpretation of the results I am getting lead me to believe there is a stability issue.

Would capturing the Serial.print() output with a terminal emulator that supports logging output do, then post processing that file? At least it would confirm (or not) that the data being sent is correct (or not). If it's being sent correctly, your problem isn't with the Arduino or its code.

I am verifying with the serial monitor, I'd like to avoid doing loads of file IO and redirection. I think I might be getting close, set_blocking might be my final issue. .. then I'll have to try reading multiple pots.

So, after a complete rewrite of your (originally very poorly written) question you are now asking for something completely different: help with a C++ program written for your computer, not help with your Arduino....?

yea yea, poorly written perhaps, but its hard to know when your project doesn't work, whether you're approaching it in the right way at all. I'm an electrician, not a programmer, not an engineer, I don't have a degree, and I don't know how to get the data from my Arduino to my computer program reliably. The problem is the same, the question is the same. How do i get the data? please post your solution @Majenko

Your core problem is the way you're using read, as Edgar notes. You must read a line not just a random number of bytes.

There are a few issues at play here. One is that the Arduino
resets every time you open the serial connection on the PC side. You can
prevent this by putting a 1 µF (or more) capacitor between 5V and
RESET. A second issue is that the tty driver may be keeping old data in
its buffer, and you get this data when you open the connection. The
third issue is that read() returns as soon as it is able to read
some data: it doesn't wait until it has got sizeof buf bytes.
To fix those issues, I suggest:

Have some form of handshake, where the PC sends a request to the
Arduino, and then the Arduino acknowledges and starts to send the
data. The PC program would then discard everything preceding the
acknowledgement.
On the PC, repeatedly read() until you have a full line (which ends
with CRLF). You may want to use a line-oriented stream if you want
the libc to handle this for you: see fdopen(3) setlinebuf(3).

Edit: A very simple example of handshake: the PC sends S (for
“start”), then the Arduino sends OK, then it starts sending the data.
On the Arduino side:
void setup() {
    Serial.begin(9600);

    // Wait for the 'S' (start) command from the computer.
    while (Serial.read() != 'S')
        /* wait */ ;

    // Send acknowledgement.
    Serial.println("OK");
}

A longer “start” command would be more robust, but a bit more complex to
handle on the Arduino. The PC should wait a bit before sending the
command (in case the Arduino is restarting), or maybe send it multiple
times until it gets an answer.

have any good refference material for this?

@j0h: For what? About line buffering, the notation “fdopen(3), setlinebuf(3)” is a horthand for “see man 3 fdopen 3 setlinebuf.

the handshaking bit, I'm not clear on. is that Serial.read() reading from the serial port to the computer, or from the Arduino? Im thinking maybe I can send a character to the arduino, pc say, hey arduino, you there rsvp to char 42. arduino listens for char 42, gets it, and responds with a string of values or something, and posts a hangup sign, and goes back to listening for the next rsvp from the PC.  ... or something like that, is how I'm imagining it going

A USB connection is actually very complex.  And serial communications (or the CDC class of USB) is only 1 of over a dozen protocols used over USB.  Most cheap embedded processors save money by leaving out this feature.  Most Arduino's use cheap embedded processors.  For instance, the classic Arduino Uno needs a second chip (search for New USB in this link) to even talk Serial over the USB port.  Fortunately this is what Serial.print() does.  It takes care of setting up the Serial protocol over the USB port for you.  And will send your data over that connection.
How you pick up that data at the other end of the USB connection is usually beyond the discussion range of this stack exchange site.  But if you are on a windows machine it will probably be one of the COM ports.  And on Linux it will probably be something like /dev/ttyUSB0 or 1.

You don't have to, but comments are appreciated when ever there is a vote.  In either direction.  The objective is to edit and improve both the questions and the answers.

I might have to repost this, as it is now closed. But I appreciate the answer.

You can edit this question to be more focused.  That should trigger a message to person who closed it so that they can reconsider the edited version of the new more focused question.  Hint: It's always good to try something on your own first then ask when things don't go as expected.

yeah, I edited it, but its still closed. every vote to reopen helps. hint hint

I downvoted because it was and now even more is not an an answer to the question

Thanks @Juraj for responding.  I see your point.  But since @ Edgar Bonet gave such a complete answer I don't see a benefit in repeating even a part of what he said.  So as to mitigate confusion I'm going to leave things as they are.


text:
I am building a coin operated machine and am using arduino uno its working but i have to press the switch twice for credit to show on seven segment
int pin1 = 8, pin2 = 9, pin3 = 10, pin4 = 11;
volatile byte  num = 0;
int coinPin = 2;

void setup() {
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(coinPin), inc_counter, RISING );
  pinMode(pin1, OUTPUT);
  pinMode(pin2, OUTPUT);
  pinMode(pin3, OUTPUT);
  pinMode(pin4, OUTPUT);
}

void display(int num) {
  digitalWrite(pin1, bitRead(num, 1));
  digitalWrite(pin2, bitRead(num, 2));
  digitalWrite(pin3, bitRead(num, 3));
  digitalWrite(pin4, bitRead(num, 4));
}

void loop() {
  Serial.print(num);
  Serial.print("credit(s) towards balance");
  display(num);
  delay(500);
}

void inc_counter() {
  num++;
}

what is your question? ... not all people would ask the same question

Based on the code supplied, you are only updating the display every half second because of the delay(500). You could press the button a number of times in 500mills.
I feel it may be better to update a flag and check that in your loop to increment your value and trigger the display update.
Based on the info provided, this may help in your endeavours.
int pin1 = 8, pin2 = 9, pin3 = 10, pin4 = 11;
int coinPin = 2;
int num = 0;
volatile bool coinFlag = false; // When true there is a coin.

void coin_present()
{
    coinFlag = true;
}

void setup()
{
    Serial.begin(9600);
    attachInterrupt(digitalPinToInterrupt(coinPin), coin_present, RISING);
    pinMode(pin1, OUTPUT);
    pinMode(pin2, OUTPUT);
    pinMode(pin3, OUTPUT);
    pinMode(pin4, OUTPUT);
}

void display(int num)
{
    digitalWrite(pin1, bitRead(num, 1));
    digitalWrite(pin2, bitRead(num, 2));
    digitalWrite(pin3, bitRead(num, 3));
    digitalWrite(pin4, bitRead(num, 4));
}

void loop()
{
    // If the flag is set increment num and then display value.
    if (coinFlag)
    {
        //We have a coin, reset the flag first.
        coinFlag = false;

        num++;        // Increment value
        display(num); //
        Serial.print(num);
        Serial.println("credit(s) towards balance");
    }

    // No need for a delay as only `coinFlag` being `true` will update the display.
}

Hope this helps in someway.

Nice answer. Code that I can copy+paste into the IDE that compiles makes this answer better than most we receive.

@VE7JRO Thanks, your comment made me aware of the issue and now prompts me to double check!


text:
how to config the Arduino ADC'S input on A0 instead of use default?
I am try to build this AC-DC meter, the code original used default A3 as input, how can change the input on A0?
the link:
https://simple-circuit.com/arduino-autoranging-ac-dc-voltmeter-with-trms/
Thanks for help
Adam

/**************************************************************************
*
* Arduino autoranging AC/DC voltmeter.
* Voltage and frequency are printed on 1602 LCD screen.
* This is a free software with NO WARRANTY - Use it at your own risk!
* https://simple-circuit.com/
*
*************************************************************************/

#include <LiquidCrystal.h>   // include Arduino LCD library
// LCD module connections (RS, E, D4, D5, D6, D7)
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);

// define autoranging channel pins
#define CH0  2
#define CH1  3
#define CH2  4
#define CH3  5

const uint16_t Time_Out = 50000,  // time out in microseconds
              Periods  = 10;     // number of periods of measurement (for AC voltage only)

// variables
byte ch_number;
const uint16_t res_table[4] = {2444, 244, 94, 47},  // voltage divider resistances in tenths kOhms
              total_res = 22444;                   // total resistance in tenths kOhms
uint16_t current_res;
volatile byte per;

void setup(void)
{
 pinMode(CH0, OUTPUT);
 pinMode(CH1, OUTPUT);
 pinMode(CH2, OUTPUT);
 pinMode(CH3, OUTPUT);

 lcd.begin(16, 2);     // set up the LCD's number of columns and rows
 lcd.setCursor(1, 0);
 lcd.print("Voltage:");

 ch_number = 0;
 ch_select(ch_number);

 // ADC and analog comparator configuration
 ADMUX  = 0x03;
 ADCSRA = 0x87;
 ADCSRB = (0 << ACME);  // select AIN1 as comparator negative input
 ACSR   = 0x13;         // turn on analog comparator

}

// analog comparator ISR
ISR (ANALOG_COMP_vect)
{
 byte count = 0;
 for(byte i = 0; i < 50; i++) {
   if ( ACSR & 0x20 )
     count++;
 }

 if(count > 48)
   per++;
}

// main loop
void loop()
{
 bool dc_flag = 0; // DC voltage flag bit
 int32_t sum = 0;  // sum of all readings
 uint16_t n = 0;   // number of readings (samples)

 ACSR = (1 << ACI);   // clear analog comparator interrupt flag
 ACSR = (1 << ACIE);  // enable analog comparator interrupt

 uint32_t current_m = micros();  // save current millis
 byte current_per = per;         // save current period number
 while ( (current_per == per) && (micros() - current_m < Time_Out) ) ;

 if( micros() - current_m >= Time_Out ) {  // if there's time out event ==> voltage signal is DC
   dc_flag = 1;
   for (byte i = 0; i < 200; i++) {
     ADCSRA |= 1 << ADSC;   // start conversion
     while(ADCSRA & 0x40);  // wait for conversion complete
     int16_t an = (int16_t)(ADCL | (uint16_t)ADCH << 8) - 511;
     sum += an;
     n++;         // increment number of readings
     delay(1);
   }
 }

 else {   // here, voltage signal is AC
   current_m = micros();  // save current millis()
   per = 0;
   while ( (per < Periods) && (micros() - current_m < (uint32_t)Time_Out * Periods) ) {
     ADCSRA |= 1 << ADSC;   // start conversion
     while(ADCSRA & 0x40);  // wait for conversion complete
     int32_t an = (int16_t)(ADCL | (uint16_t)ADCH << 8) - 511;
     sum += sq(an);  // sq: square
     n++;            // increment number of readings
   }
 }

 ACSR = (0 << ACIE);  // disable analog comparator interrupt
 uint32_t total_time = micros() - current_m;  // used to claculate frequency

 // voltage calculation
 float v;
 if(dc_flag)   // if voltage signal is DC
   v = (4 * sum)/n;   // calculate Arduino analog channel DC voltage in milli-Volts

 else  // here voltage signal is AC
   v = 4 * sqrt(sum/n);   // calculate Arduino analog channel RMS voltage in milli-Volts

 // claculate actual (input) voltage in milli-Volts (apply voltage divider equation)
 v = v * (float)total_res/current_res;
 v /= 1000;  // get voltage in Volts

 uint16_t v_abs = abs(int16_t(v));
 if( (v_abs >= 10 && ch_number == 0) || (v_abs >= 100 && ch_number == 1) || (v_abs >= 250 && ch_number == 2) ) {
   ch_number++;
   ch_select(ch_number);
   delay(10);
   return;
 }

 if( (v_abs < 220 && ch_number == 3) || (v_abs < 80 && ch_number == 2) || (v_abs < 8 && ch_number == 1) ) {
   ch_number--;
   ch_select(ch_number);
   delay(10);
   return;
 }

 char _buffer[8];
 lcd.setCursor(0, 1);
 if( v < 0)
   lcd.print('-');
 else
   lcd.print(' ');
 if(v_abs < 10)
   sprintf( _buffer, "%01u.%02u", v_abs, abs((int16_t)(v * 100)) % 100 );
 else if( v_abs < 100)
   sprintf( _buffer, "%02u.%01u", v_abs, abs((int16_t)(v * 10)) % 10 );
 else
   sprintf( _buffer, "%03u ", v_abs );

 lcd.print(_buffer);
 if(dc_flag)
   lcd.print("VDC        ");
 else {
   lcd.print("VAC ");
   // calculate signal frequency in Hz
   uint32_t period_time = total_time/Periods;
   float freq = 1000000.0/period_time;
   sprintf( _buffer, "%02u.%02uHz", (uint16_t)freq % 100, (uint16_t)(freq * 100) % 100 );
   lcd.print(_buffer);
 }

 delay(500);    // wait half a second

}

void ch_select(byte n) {
 switch(n) {
   case 0:
     digitalWrite(CH0, HIGH);
     digitalWrite(CH1, LOW);
     digitalWrite(CH2, LOW);
     digitalWrite(CH3, LOW);
     break;
   case 1:
     digitalWrite(CH0, LOW);
     digitalWrite(CH1, HIGH);
     digitalWrite(CH2, LOW);
     digitalWrite(CH3, LOW);
     break;
   case 2:
     digitalWrite(CH0, LOW);
     digitalWrite(CH1, LOW);
     digitalWrite(CH2, HIGH);
     digitalWrite(CH3, LOW);
     break;
   case 3:
     digitalWrite(CH0, LOW);
     digitalWrite(CH1, LOW);
     digitalWrite(CH2, LOW);
     digitalWrite(CH3, HIGH);
 }
 current_res = res_table[n];
}

// end of code.

The input to the ADC is selected by the four least-significant bits of
the “ADC Multiplexer Selection Register”, aka ADMUX. It is set to
analog input 3 by this line of code:
ADMUX  = 0x03;

Change this line to ADMUX = 0; and the ADC will read pin A0.

Your code is to hard to read, it is just a blob of characters on my screen but you have a pretty picture of the arduino. Change your code to use A0 instead of A3. Change your physical connection from A3 to A0 and you are all set. I miss read the code you posted.
It is a tricky circuit and he did all of the the registers directly, making it extremely hard to follow. I do not know the register set well enough to speak knowledgeable about what he is doing. The Optocouplers short out parts of the input divider network which he selects in his code. This is how he does the ranging. The optocouplers are drawn in reverse with the output on the left and the input on the right. Try this link to Nick Gammon's site: https://www.gammon.com.au/adc Also try this one: https://www.arduino.cc/en/Reference/PortManipulation

Thanks. Can you tell how to post a code better? There is not a A3, in the code, cause of it is default. that's why I don't how to change.

I have never done so at this point I will not try to explain it. There are many others that do a better job then I can.    ADMUX  = 0x03; Is one of the statements I believe you need to change it to   ADMUX  = 0x00; Let us know how you did? I chased the circuit back to simple circuits where somebody asked the same question. There answer was close to mine. "  If you need to change A3 to A0 you must change the analog pin definition in the code"

perfect ! charged ADMUX = 0x03 as ADMUX = 0x00, it works. Thank you.

Actually, charged ADMUX = 0x03 as ADMUX = 0x02, A2 as input; but charged ADMUX = 0x03 as ADMUX = 0x01, A1-A7 non of as input works! WHY?

Did you move the connection to A0? Also check any references to ADMUX.

Yes, I moved the input to relative pin and checked the above results. I didn't change any thing else, Don't know how to check the references to ADMUX?

The Optocouplers short out parts of the input divider network -- Er... no. They select different taps in the divider network to read the voltage from.

Thanks. I used this solution to MEGA2560, got the same result, but how to define the A5,A6,A8 on MEGA2560? I tried  some number like 0100, 0110 no GOOD.

@oldbin you should read the datasheet for the chip. It tells you what all the registers are and what the different values mean.


text:
How to fix serial communication problem between Arduino UNO and sim900A
I've connected the arduino UNO to the sim900a. But after checking the serial communication between the two I keep getting these output.

Here is the connections and code that I used
#include <SoftwareSerial.h>
SoftwareSerial SIM900A(2, 3);
// Connect the SIM900A TX to Arduino pin 2 RX.
// Connect the SIM900A RX to Arduino pin 3 TX.
char c = ' ';
void setup()
{
 // start th serial communication with the host computer
 Serial.begin(9600);
 while (!Serial);
 Serial.println("Arduino with SIM900A is ready");
 // start communication with the SIM900A in 9600
 SIM900A.begin(9600);
 Serial.println("SIM900A started at 9600");
 delay(1000);
 Serial.println("Setup Complete! SIM900A is Ready!");
 }
 void loop()
 {
  // Keep reading from SIM900 and send to Arduino Serial Monitor
  if (SIM900A.available())
  { c = SIM900A.read();
    Serial.write(c);
   }
  // Keep reading from Arduino Serial Monitor and send to SIM900A
  if (Serial.available())
  { c = Serial.read();
   SIM900A.write(c);
  }
 }

How can I fix this?

On what baudrate does the SIm module run? I would guess you have a baudrate mismatch

SIM900 has auto baud rate detection, meaning you need to send a couple of  "AT" to the module to sync the baud rate before sending the rest. If the baudrate is sync, it will reply "OK". Also are you powering the SIM900 with your Uno? The Uno can't supply sufficient current to power the module.

Yes, I've connected 5V(arduino) to VCC(SIM900). So the problem is the lack of current in the module?

SIM900A datasheet says Single supply voltage: 3.4V – 4.5V and while transmitting current can go up to 2A. None of these can be provided by the UNO.

@hcheung I can see no reference to auto baud for the SIM900A. Do you have a reference? All I can find is that it has a default baud rate of 9600 and that can be configured using AT commands to between 9600 and 115200 baud.

@Majenko See section 3.7.1 of SIM900 hardware design reference (or page 34), in fact nearly all SIMCOM modules are capable of auto baud rate.

You are using the wrong pins on the SIM900A to communicate with your Arduino.
That specific module has a MAX232 interface on it to convert TTL UART to RS232. That is not compatible with the Arduino unless you add another MAX232 to undo the conversion that the one on the board does.
Instead you need to use the other 3-pin header at the other end of the board.  It should (according to this site) be wired like this:

Of course you can use other pins than 0/1 on your Arduino, as long as you connect them to the right place on the SIM900A module as shown in that diagram.
Also note what I take to be a pair of jumpers bridging pins on the header you're currently connecting to (ring around them in the diagram).


text:
Read serial with header and end marker
I am trying to use Topway display for HMI lcd with Arduino. This display using RS232C protocol at docs it has a "Communication Packet Structure" like this.

So my query should start with AA and end with CC 33 C3 3C.  This sample reading code was taking topway youtube channel.
Serial.write(0xaa); // packet head
Serial.write(0x3e); // VP_N16 read command
Serial.write(0x00); // VP_N16 address
Serial.write(0x08);
Serial.write(0x00);
Serial.write(0x00);
Serial.write(0xcc); // packet tail
Serial.write(0x33); // packet tail
Serial.write(0xc3); // packet tail
Serial.write(0x3c); // packet tail

3E is the command (for reading) code and this is the list of all commands. docs over here

The point is parsing of smart LCD's response at the original. They use this code: (at first comment)
     while (!Serial.available()) {}
     if (Serial.read()==0xaa) {                     // packet head
     packet_OK=1;
     while (!Serial.available()) {}
     if (Serial.read()==0x3e) {                   // packet command
      while (!Serial.available()) {}
      temp_h=Serial.read();                      // read back value high byte
      while (!Serial.available()) {}
      temp_l=Serial.read();                      // read back value low byte
      while (!Serial.available()) {}
      if (!(Serial.read()==0xcc)) {packet_OK=0;} // packet tail
      while (!Serial.available()) {}
      if (!(Serial.read()==0x33)) {packet_OK=0;} // packet tail
      while (!Serial.available()) {}
      if (!(Serial.read()==0xc3)) {packet_OK=0;} // packet tail
      while (!Serial.available()) {}
      if (!(Serial.read()==0x3c)) {packet_OK=0;} // packet tail
      }
      else
      {packet_OK=0;}
     }
     else
     {packet_OK=0;}

It looks nasty and cumbersome because I must write different method for each LCD display commands. Is there any way to read all serial response them as a char array with starting marker "0xAA" and read until finishing marker "0xCC 0x33 0xC3 0x3C" and after that parse it?
You can watch and check this code on youtube

It looks like you've put some effort into the post but, what is the question?

you cannot simply wait for the packet tail ... the data payload could contain the same bytes ... you have to keep track of the number of bytes in the message ... them check if packet tail arrives as expected

@timemage funny :)

The short answer to your question is “yes, there is a way”. Multiple
ways actually. You could write a blocking function, which follows more
or less the logic of the example you show, blocking while waiting for
each new byte. Or you could write a non blocking function, which
always return immediately and, either gives you the complete packet,
or tells you that no full packet has been received so far.
The non-blocking way may be a bit more complicated, but it is more
useful, because you program can do other stuff, and be responsive, while
waiting for a packet. Here is my take at it. It is based on a finite
state machine:
// Return whether the payload of this command is of string type.
bool command_payload_is_string(uint8_t command);

// Return the expected packet length for the provided command,
// excluding header and tail.
int packet_length(uint8_t command);

// Attempt to read a packet, but do not block.
// Return a pointer to a static buffer holding the packet,
// or nullptr if no complete packet was received this time.
uint8_t *read_packet() {
    const uint8_t expected_header = 0xaa;
    const uint8_t expected_tail[4] = {0xcc, 0x33, 0xc3, 0x3c};

    // Return immediately unless we have a byte to process.
    if (Serial.available() == 0) return nullptr;
    uint8_t data = Serial.read();

    static uint8_t buffer[BUFFER_SIZE];
    static int bytes_received, bytes_expected;
    static enum {
        EXPECTING_HEADER, EXPECTING_COMMAND,
        EXPECTING_STRING, EXPECTING_PAYLOAD, EXPECTING_TAIL
    } state = EXPECTING_HEADER;
    switch (state) {
        case EXPECTING_HEADER:
            if (data = expected_header)
                state = EXPECTING_COMMAND;
            break;
        case EXPECTING_COMMAND:
            buffer[0] = data;  // command byte
            bytes_received = 1;
            if (command_payload_is_string(data)) {
                state = EXPECTING_STRING;
                // bytes_expected is not relevant in this case.
            } else {
                state = EXPECTING_PAYLOAD;
                bytes_expected = packet_length(data);
            }
            break;
        case EXPECTING_STRING:
            if (data == '\0') {  // end of string
                buffer[bytes_received++] = '\0';
                state = EXPECTING_TAIL;
                bytes_expected = 4;
                bytes_received = 0;
            } else if (bytes_received < BUFFER_SIZE - 1) {
                buffer[bytes_received++] = data;
            } else {
                // Do nothing. As the string is too long
                // to fit in the buffer, this byte is discarded.
            }
            break;
        case EXPECTING_PAYLOAD:
            buffer[bytes_received++] = data;
            if (bytes_received >= bytes_expected) {
                state = EXPECTING_TAIL;
                bytes_expected = 4;
                bytes_received = 0;
            }
            break;
        case EXPECTING_TAIL:
            // If we don't get the expected tail,
            // give up and wait for a new header.
            if (data != expected_tail[bytes_received++]) {
                state = EXPECTING_HEADER;
                break;
            }
            // If the tail is all right, return the buffer
            // and get ready for the next packet.
            if (bytes_received >= bytes_expected) {
                state = EXPECTING_HEADER;
                return buffer;
            }
    }
    return nullptr;
}

It will be up to you to implement packet_length(). See jstola's
comment on why it is needed.
You would use read_packet() like this:
void loop() {
    uint8_t *packet = read_packet();
    if (packet)
        parse_and_handle(packet);

    // the rest of the program, never blocked by read_packet()...
}

Edit: According to your comment, some commands have a payload which
is a string of unknown length, but seemingly NUL-terminated. I
edited the code, and added an extra EXPECTING_STRING state to handle
this special case. It is up to you to implement the boolean function
command_payload_is_string().

Edgar thanks a lot! for your wise answer, after reading 10 times, I have understood half of them :). I have a last question. Almost all command respons lenght are known before. But only reading string is not known before. it deponds on user. You can think like that keyboard input. at this point what should I do, while reading string for packet_length().

@mehmet: See amended answer. Now packet_length() will not be called if the payload is of string type.


text:
Find OK or ERROR in serial string
I am trying to figure out how to capture the OK or the ERROR from a SIM800l.
I have tried
mySerial.println("AT");
while (mySerial.available() > 0 ) {
String str = mySerial.readString();
Serial.println(str);
     if (str.equals("OK")) {
        Serial.println("ok");
     } else {
        Serial.println("unknown");
     }
   }

But I always getting nothing back?

Does this answer your question? Comparing a String after reading it from Serial fails. The issue is that the string read from the serial port also contains a closing "newline" character so the comparison fails. You need to strip off the newline.

You can use .indexOf to find characters in a String. It returns a -1 if a match is not found. See https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/indexof/
mySerial.println("AT");
String str;

while (mySerial.available() > 0 )
{
    str = mySerial.readString();
    Serial.println(str);

    if (str.indexOf("OK") != -1)
    {
        Serial.println("ok");
    } else if (str.indexOf("ERROR") != -1)
    {
        Serial.println("error!");
    } else {
        Serial.println("unknown");
    }
}


text:
Arduino Reset via Software (every day)
Dear Stack Exchanger's,
I want to reset my Arduino and system in every 24h for preventing frozen software and also other connectivity stuffs.
I wrote a program which connects a digital pin to reset pin of Arduino and I want to reset with that way.
For example my code :
unsigned long myTime; // Millis() function time value
int timeExpected = 5000; // I want to reset it in every 5 secs for testing.
const int RESET_PIN = 2; // Reset pin's connection

void setup() {
  Serial.begin(9600);
  pinMode(LED_BUILTIN,OUTPUT);
}
void loop() {
  digitalWrite(LED_BUILTIN,HIGH);
    myTime = millis();
    Serial.println(myTime); // prints time since program started
     delay(1000);

   if(myTime % timeExpected == 0) {
    digitalWrite(LED_BUILTIN, LOW);
    delay(1000);
     Serial.println("RESET");
    //digitalWrite(RESET_PIN, LOW);(I just test with LED_BUILTIN Low function)
    }

  }

I have tried the watchdog timer but I cannot do it for 24 hours.
If you have another solution for reset in 24h please tell me and send me the related article/book/link etc. I will check and implement into my code.
UPDATE:
I have done this but it does not reset at very 5s .
Code :
#include <avr/wdt.h>
unsigned long myTime;
int timeExpected = 5000;

void setup() {
  Serial.begin(9600);
Serial.println("Setup started :");
// make a delay before enable WDT
// this delay help to complete all initial tasks
delay(2000);
wdt_enable(WDTO_2S);
}

void loop() {
    myTime = millis();
    delay(1000);
    Serial.println(myTime); // prints time since program started
   if(myTime == timeExpected) {
     Serial.println("RESET");
    wdt_reset();
    }

You can't really use unstable software to reset itself - if it freezes, how can it execute the reset code? You'll need to either: 1) debug the software (you should do this anyway); 2) use the built-in watchdog timer to reset the arduino if your software doesn't reset the watchdog; or 3) use an external hardware timer to reset the Arduino at intervals. Solution 3) should be unnecessary if you do 1) and 2).

wdt_reset() resets the watchdog's timer to avoid reset of the MCU. read my answer again

You can use the watchdog timer, but you have to change the way you measure the elapsed time. Try this code:
#include <avr/wdt.h>

unsigned long myTime; // Millis() function time value
unsigned long elapsedTime;
unsigned long timeExpected = 5000; // I want to reset it in every 5 secs for testing.
const int RESET_PIN = 2; // Reset pin's connection

void setup() {
  Serial.begin(9600);
  pinMode(LED_BUILTIN, OUTPUT);
  myTime = millis();
  Serial.println("INIT");
  wdt_enable(WDTO_2S); //Enable wdt every two seconds

}
void loop() {

  //************RESET HANDLER********************//
  elapsedTime = millis() - myTime;
  if (elapsedTime > timeExpected) {
    Serial.print("RESET");
    while (1); //Intentionally halt the program, so the watchdog performs the reset
  }
  //**********************************************
  //****************REST OF THE PROGRAM***********
  wdt_reset(); //Ensure one call to this function at least one time in two seconds or less
  digitalWrite(LED_BUILTIN, HIGH);
  Serial.println(elapsedTime); // prints time since program started
  delay(1000);
}

Please note that if you have multiple delays in your program, you have to ensure the call to wdt_reset() in order to prevent unwanted resets.
Personally I try not to use delays and would recommend avoid delays as much as possible. You may check out this tutorial if you want to see how to avoid delays. If you achieve avoiding delays you can call wdt_reset() just one time at the begining of the loop.

You can do an almost immediate full reset with watchdog by activating it 'on place'.
wdt_enable(WDTO_15MS); // resets the MCU after 15 milliseconds
while (true);

You can use millis() for timing the reset as any other timed function.


text:
How to fade LED in a defined time using FastLED
I'm using FastLED library, Arduino Nano and 5 addressable LEDs (WS2812B).
I'd like to create the sequence in the image attached. (all in white color for example)
I know how to turn ON each LED every 0.2 sec and I know how to fade.
I don't know how to make sure each LED goes from 0% brightness to 100% in 0.4 sec + start fading in the next LED after 0.2 sec.
Here is a fading LED:
void loop() {
  uint32_t cur_ms = millis();
    if (cur_ms - fade_ms > 200) {
        fade_ms = cur_ms;
        brightness += 5;
        leds[0] = CHSV(255, 0, brightness);
    }

FastLED.show();
// delay(10);

}
Can anyone help me figure it out?

Hi Welcome to ASE. Just an Idea. You can use the remaining millis() and the current brightness value to compute the next needed jump or reduction in the brightness

I'd appreciate if you could supply a snippet

can you share the complete code snippet of what you have worked on? Also, The below answer is really really good. You might be in a hurry now, but bookmark it and come back when you have time.

One of the SimpleTimer libraries such as this one by Marcello Romani (which I mention because I have used it; there are others). It creates a timers object that has 10 (in this case) software-based timers with a variety of operating modes (run once, run x times, run forever, e.g.).
The basic idea (for a 1-LED example) is that you write a function (known as a "callback" to step up the brightness of an LED by one step. Let's call it stepUp().
You write another callback function to turn off the LED and start a timer that will call stepUp() at whatever interval you choose for as many times as it takes to reach 100%. Let's call this one cycleLED().
In your setup(), you'll start another timer that will call cycleLED() as often as you want that process to run - every 1200 mSec in this case - and for as many times (or forever) as you choose.
In your loop() function, you'll need a call to your timer object's .run() function as often as possible - that is what makes the timers work, and it is the timers that will call your callback functions to make your LEDs behave as you want them to.
So far, we one fading-up LED, and I'd recommend you implement this much at first.
There are two ways to go from here. You can write the above pair of callbacks for each LED, but they will be nearly identical and why write maintain the same code, several times over? Or you can use another feature of the library - a pointer-to-void argument to the callback function - in which you can pass any value, such as an LED's number or address, so that one callback could operate on the specified LED.
If you go with first option, your setup() function will need to to start 5 timers, one for each cycleLED() function (which would need to have distinct names, of course), and those timers start-times will need to be staggered.
With the second option, you would write a third callback, allCycles() that sequences the starts of each cycleLED() in turn. In this case, your setup() function would only need to start a timer to repeatedly call allCycles().
There's a lot there, if these are new concepts. If so, it will be a lot easier to experiment with the SimpleTimer library doing something trivial at first, like flashing (not fading) one LED, then several LEDs, until this way of coding timed events feels less foreign.

Thank you, but this isn't helpful.
It should be very simple & clean code.
I should use this: "if (cur_ms - x_ms > y_ms)" twice.
One for incrementing the brightness and one for increasing the index to the next LED.
I also need a struct/array to create different brightness value for each LED.

It really doesn't get much cleaner than that. You can of course, write layers of if (cur_ms - x_ms > y_ms) and keep all of the code visible all of the time, but modular code is generally easier to understand, write correctly, debug, and maintain. You're welcome.

@yuvix_man how is Jroberts answer not helpful? Jrobert laid out everything clearly. Writing actual (clean) code is up to you, which should be easy after this explanation.


text:
SMBus on ATTiny204
So I want to connect multiple LED Panels with dynamic addressing to a Master Controller.
Seems like SMBus should be able to do that, however I don't find any Library for the Arduino framework.
Does SMBus require Hardware implementation and if if works in Software is there a library for that and does it even work on the ATTiny?

SMBus and I2C are almost the same. Just a few specs between them. So... why SMBus and not I2C which is by far more ubiquitous?

@Majenko Because I really want the ARP feature of SMBus that enables me to use dynamic adressing. If there's a simpler solution to have dynamic adressing I'd love to hear that too

The ATMega TWI Arbitration module only (afaict) works in master mode. So you would have to write a bit-banged slave emulation with arbitration built in. Doable, but not nice.

@Majenko so is there a better solution?

ARP's your big sticking point. However since you need to allocate a UUID to each device anyway you could just allocate a unique I2C address to each device instead? Then you can scan the I2C bus looking for what I2C addresses exist.

@Majenko yes I thought about that, but the 7bit/10bit adress range is too small for my application. Chances that I got two or more panels with the same ID are too high

I designed a system once based around a single direction of UART transmission (TX->RX) and one single pulse indication in return with 24 bit addresses. That allowed for 16 million unique addresses, and I devised a tree-like scanning method to find all the devices that were present on the bus fairly rapidly without having to cycle through all 16 million addresses. You can see my thoughts on the protocol here: https://github.com/MajenkoProjects/LIBus/blob/master/PROTOCOL.md

@Majenko Interesting Idea, I thought about UART but with factory set and delivered QR Codes that contain the Adresses for the Master. I wasn't sure if multi TX to one RX works electrically with UART. Thank you!

Multi tx to single rx can be done, but it's tricky. If you want that way around maybe RS485 would be a better choice.

The AVR chips lack hardware support for bus arbitration when operating as a slave device in I2C, which would be required for it to work as SMBus with ARP.
You would have to write your own bit-banged driver to act as a slave whilst monitoring the SDA pin whenever it transmits to look for bus collisions.
A better solution would be to allocate each device a unique address using an address space of your choosing (to give you enough addresses for uniqueness) at build / programming time. A bus of some design (maybe RS485 would be a good choice for this) can then be scanned looking for, and cataloguing, what addresses are in use.


text:
NRF24 and Arduino Nano Every usage
Im building an RC car project and using 2 NRF24's for communication. I own an Arduino Uno, Nano and Nano Every. The NRF's work great with the Uno and Nano in any combinations but using a Nano Every either as TX or RX doesn't work.
I have tried the NRF24 and NRFLite and both say "Cannot communicate with radio".
When using the NRFLite library examples Basic_TX on the Uno/Nano and Basic_RX on the Nano Every, the Uno/Nano says transmission was successful even though the Every says "Cannot communicate with radio". This lasts about 1 second before the Uno/Nano says the transmission failed again. This happens every time you reset the Every. It is as if the NRF24 gets powered on but then is unable to communicate with the Every.
I am using power adapters for the NRF's and powering them through the 5v pin. No luck with capacitors either. Have swapped out all the wires and also double checked all connections.
Is there something wrong with the Nano Every? Does it work with a NRF24 for anyone?
I have completely ran out of ideas to fix this.
Thank you in advance

How do you wire the Nano Every and define your pin definition on your sketch? Nano Every has SS pin on D8, not like most of the Arduino AVR-based boards on pin 10.

Hi hcheung! I have the SCK on D13, MISO on D12, MOSI on D11, CE on 7 and CSE on 8. I'm not sure what the SS pin is :(

SS is Slave Select, some called Chip Select (CS), you might want try to use pin 8 as CE, and pick another pin for CSE.

Sadly no luck with that. I bought a new nrf24 and that didnt help either, it worked with the regular Nano tho. Looks like my Nano Every is just broken.

I stucked with the same problem too when use nRF24L01+ and Arduino Nano Every to transmit data to Arduino Uno with nRF24L01+. So I have solved the problem as follows below. I hope it could help you and for somebody else.

First of all you should add Arduino megaAVR Boards in the boards manager.

1.1 It is first necessary to add the URL of their Boards Manager JSON file in: File > Preferences > Additional Boards Manager URLs and Paste the link: https://raw.githubusercontent.com/amperka/iskra-boards/master/package_amperka_index.json
1.2. Then go to Tools>Boards Manager, search Arduino SAMD Boards and install it

1.3. Choose Arduino Nano Every in Tools>Board>Arduino megaAVR Boards>Arduino Nano Every

Upload the library for RF24. It must be compatible for architecture megaavr because  Arduino Nano Every uses Microchip ATmega4809. I use the latest version RF24-1.4.1.
Here is the link to the library: https://www.arduinolibraries.info/libraries/rf24

You should check whether you connected nRF24L01+ and arduino correctly.

The pinout of Arduino Uno is as follows:
5V - VCC if you connect nRF24L01+ via nRF24L01+ adapter (I use adapter)
or 3.3V - VCC without adapter
GND - GND
9 pin - CE
10 pin - CSN
11 pin - MOSI
12 pin - MISO
13 pin - SCK
not connected - IRQ
However, I use another pinout for Arduino Nano Every. When I use the same pinout as Arduino Uno it can't find nRF24L01+. You can check it in Serial Monitor by using a sketch below. If you get zeros in the third line, for example, something like this: RX_ADDR_P0-1 = 0x0000000070 0x0000000000. It means that Arduino Nano Every isn't connected to nRF24L01+ correctly and Arduino Nano Every doesn't see it.
I suppose the problem with the library of RF24 and it should be fixed. Perhaps I'm wrong and the problem with another things.
So I use the following pinouts for Arduino Nano Every:
5V - VCC if you connect nRF24L01+ via nRF24L01+ adapter (I use adapter)
or 3.3V - VCC without adapter
GND - GND
10 pin - CE
A3 - CSN (if you will get zeros in the third line RX_ADDR_P0-1 in Serial Monitor then change A3 to another one. You can vary pin from A5 and so on until A0). do not use A7 and A6 because on some model dev boards, A6 and A7 are analog input only.
11 pin - MOSI
12 pin - MISO
13 pin - SCK
not connected - IRQ
The sketch for checking:
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(10,A3);  // for arduino nano every
//RF24 radio(9,10); // for arduino uno

const uint8_t num_channels = 128;
uint8_t values[num_channels];
void setup(void)
{
  Serial.begin(9600);
  printf_begin();
  radio.begin();
  radio.setAutoAck(false);
  radio.startListening();

  radio.printDetails();
  delay(5000);

  radio.stopListening();
  int i = 0;
  while ( i < num_channels )  {
    printf("%x",i>>4);
    ++i;
  }
  printf("\n\r");
  i = 0;
  while ( i < num_channels ) {
    printf("%x",i&0xf);
    ++i;
  }
  printf("\n\r");
}
const int num_reps = 100;

void loop(void)
{
  memset(values,0,sizeof(values));
  int rep_counter = num_reps;
  while (rep_counter--) {
    int i = num_channels;
    while (i--) {
      radio.setChannel(i);
      radio.startListening();
      delayMicroseconds(128);
      radio.stopListening();
      if ( radio.testCarrier() )
        ++values[i];
    }
  }
  int i = 0;
  while ( i < num_channels ) {
    printf("%x",min(0xf,values[i]&0xf));
    ++i;
  }
  printf("\n\r");
}
int serial_putc( char c, FILE * ) {
  Serial.write( c );
  return c;
}

void printf_begin(void) {
  fdevopen( &serial_putc, 0 );
}

Here is the correct output in Serial Monitor
the third line without zeros: RX_ADDR_P0-1  = 0xf0f0f0f0d2 0xc2c2c2c2c2
SPI Speedz  = 10 Mhz
STATUS      = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1    = 0xf0f0f0f0d2 0xc2c2c2c2c2
RX_ADDR_P2-5    = 0xc3 0xc4 0xc5 0xc6
TX_ADDR     = 0xf0f0f0f0d2
RX_PW_P0-6  = 0x20 0x20 0x20 0x20 0x20 0x20
EN_AA       = 0x00
EN_RXADDR   = 0x02
RF_CH       = 0x00
RF_SETUP    = 0x14
CONFIG      = 0x0f
DYNPD/FEATURE   = 0x38 0x38
Data Rate   = 1 MBPS
Model       = nRF24L01+
CRC Length  = 16 bits
PA Power    = PA_HIGH
ARC     = 15

the next two lines are a list of available channels that should be read from top to bottom (i.e. we have 127 channels, еру channels are presented in 16-bit version, the first line is the first digit of each of 127 channels, the second line is the second digit of each of 127 channels).
00000000000000001111111111111111222222222222222233333333333333334444444444444444555555555555555566666666666666667777777777777777

0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef

then the level of noisiness of the channels is displayed.
There are noise from the channel 09 to the channel 3f approximately.
this noise from my wifi router and some another electronics.
you should choose free channels for your purpose.
00000010114663444533233300000000001000011233544433221100112223212010000000000000000000000000000000000000000000000000000000000000

00200000035575656777697332111321022125625559643632551111000333012000000000100000010001000000001000000000000011010000000000000000

00000001135a9a767767c89a85646565866555645897434644445200121212122000000000000000000000001000000000000000011000000010000000000000

00101000035567667357878a51123341220322335373542222122000112313112000000001010000000001000000020000000010000000000000100000000010

11000011047587577457694521122232111121243247542232210100002222111000000000100002000002000000000000000000000000000010000000000000

Note:

Check Tools. There should be:
Board:Arduino Nano Every;
Registers emulation: "ATMEGA328";
Port:COM#(Arduino Nano Every).

some transmission errors can occur due to poor contacts between wires and pins of arduino, so the wires should be soldered.

If everything is ok, then you can use your sketches for the receiver and transmitter respectively. Good luck!

so you say: pin 9 doesn't work as CE or pin 10 doesn't work as CS if Nano Every is used with ATmega328 emulation? could you try which one is the problem?

The problem is that CSN doesn't work on digital pins of Arduino Nano Every but it works on one of Arduino Uno. CSN works only on analog pins (A5-A0) of Arduino Nano Every. CE works well if you connect it to the 9 or 10 pin of arduino nano every. Actually I have found it accidentally.

UPD: If you use registers emulation "None (ATMEGA4809)" it works too. I mean if you use pinout as shown above. Otherwise it doesn't work.

I have no problem to use pin 10 as CS (for Ethernet) even in 328p emulation mode

Thank you for those excellent instructions.
After days of trying to get this danged Nano Every to work with the nRF24L01+, your guide got it going! I can't think you enough. I hope it's ok to share this URL with others who are also struggling to date...?? Cheers


text:
CT Sensors with Arduino and ESP32
there. I am following this tutorial to build an energy monitor system.
The link is https://learn.openenergymonitor.org/electricity-monitoring/ct-sensors/interface-with-arduino
Everything works fine with an Arduino UNO on ADC A1, but I need to send the data to a WebServer, so I decided to do the same setup with ESP-WROOM-32 which has a wifi module. I read the value from pin 34, the code I am using is following
// EmonLibrary examples openenergymonitor.org, Licence GNU GPL V3

#include "EmonLib.h"                   // Include Emon Library
EnergyMonitor emon1;                   // Create an instance

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

  emon1.current(34, 111.1);             // Current: input pin, calibration.
}

void loop()
{
  double Irms = emon1.calcIrms(1480);  // Calculate Irms only
  Serial.println(Irms);            // Irms
}

The current is always 0, when I add a println(analogRead(34)), it always gives me back the maximum number 4095. I am confused when it is not working with the ESP32 but with Arduino UNO, the power supply for both is 3.3V.

Can someone help me, please? Thank you so much!

it looks like you're feeding the orange ADC wire with 3.3v from the white wire. measure from row 60?

Your R2 doesn't seems to be connect to the mid-point. Also the library you are using EmoLib doesn't work for ESP32 as the formula and assumptions it used in the library is wrong for ESP32. Try EmonLib-ESP32 which fix the library and make it works for ESP32.

@hcheung Hi, the circuit on the breadboard working fine with the Arduino UNO, I don't think there are any connection issues, but I will try to use that library, thank you so much!

@hcheung If you zoom in on the 33R load resistor you can just see a tiny bit of yellow peeking through that looks like it might be the "missing link" on the R2 midpoint resistor.

@Majenko Hi, Can you see the answer I posted? I took the picture with a different angle this time

Since you did not post a link to the hardware I will take a SWAG. Many of the ESP32s have a max of 1 volt on the analog to digital converter. You will need to check your data sheet for that. I would also be sure you limit the current into the A/D so you do not blow it.


text:
Using index of to search for multiple characters
In my Arduino project, a string will be received. I understand using .indexof to find the placement of a certain character in the string. My problem is that I need to find the first occurrence of any letter A-Z and haven't found any resources regarding using or  statements in an .indexof aka string.indexof("a" || "b" ....).
Is this something that is not possible using indexof functions and if so is there any function that I can use to solve this! Thanks!

index is only for one comparison at a time. there's a built-in isupper(char): http://www.cplusplus.com/reference/cctype/isupper/. you can find many chars at once using https://www.cplusplus.com/reference/cstring/strcspn/

You can also use a for loop that checks the value of i (or whatever variable) and then depending on what i is it runs indexof with different letters.

Here are two functions that I hope help in your endeavours. You can supply either a String or a char array and you should get the first position of an alpha character. Returns -1 if not present.
See https://www.arduino.cc/reference/en/language/functions/characters/isalpha/
Update:
Thanks to great comments from Edgar & Mat I have updated the functions with best practise and cost improvements.
int alphaPos(const char* str)
{
  for (int i = 0; str[i] !=0 ; ++i) {
    if (isAlpha(str[i]))
    {
      return i;
    }
  }

  return -1;
}

int alphaPos(const String& str)
{
  return alphaPos(str.c_str());
}

/*
    Usage:

    String bobble = "&&&88434a";
    int x = alphaPos(bobble);

    if (x != -1)
    {
      ...x has the position in the string
    }
    else
    {
     ...There is no alpha char present.
    }
*/

I suggest passing a const reference to the second overload.

@EdgarBonet, I admit I have much to learn so ask honestly what the benefit is?

@voidPointer: it indicates to the caller that the function will not modify the passed String. It is good practice. Also you can avoid the strlen call (which doubles the cost of the function) - use str[i] != 0 in the loop condition instead.

@Mat. Thanks. That strlen tip is pretty cool and will help others too.

To elaborate on Mat's comment: if you wan to get an idea of why it is considered good practice, see Const Correctness on the isocpp.org wiki.

@EdgarBonet That is a good read. Thanks.


text:
How to reset ESP32 after a certain duration?
I would like to reset my ESP32 from the software, how do I do it and how to make it do this at regular intervals.

Hope this helps.

uint32_t resetAfterMillis = 30000; // Reset after 30 seconds.
uint32_t lastResetWas;

void setup() {
   lastResetWas = millis();
}

void loop() {
  uint32_t now = millis();
  if (now >= lastResetWas + resetAfterMillis)
  {
      lastResetWas = now;

      // Whatever you want to do here
      ESP.restart();

  }

}