text:
Continuous servo speed control with Arduino Uno controller and servo shield
It is very simple device, 2 continuous servos FS5113R, rotates continuously in one direction. Here is device original content, which is this servo shield it looks like russian, and here is library, I have added to Arduino IDE, also I have original code, which runs this device, given below.
I'm trying to figure out, what can I do with speed, to run it slower, I've tried change  delay(15); number to 1000, but it moves with same speed.  I've tried  increment variable  in  while (z < 2) loop and pass it with interval, but speed is same:
#include <Wire.h>
#include <Multiservo.h>

#define SERVO_COUNT 2

Multiservo servo[SERVO_COUNT];

int pos1 = 0;
int pos2 = 0;

int z = 1;

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

  for (int i = 0; i < SERVO_COUNT; ++i)
  {
    servo[i].attach(i);
    servo[i].write(0);
  }
}

void loop(void)
{
    while (z < 2){
        pos1 + 1;
        pos2 + 1;
        servo[1].write(pos1);
        servo[2].write(pos2);
        delay(15);
    }
}

Any advice, guide or example would be useful

It is unclear what exactly you are trying to achieve. You never change pos1 or pos2, thus the speed doesn't change. Try doing pos1++; instead of pos1 + 1

@chrisl Hello, same behavior with pos1++, but I'm trying rotate motor slower, example above shows exist code, which runs servos with given speed

If you use the above code with a continuous rotation servo, the servo will first rotate in one direction, getting slower (1.3 seconds duration), then changing rotation direction (as the value goes through 90), then getting faster for 1.3s and then keeping this speed, until pos1 and pos2 overflow. This would take 136h. Is this, what you are seeing? Since the servo cannot change direction very fast, that movement wouldn't be very strong, maybe just a long twitch at the start of the program

@chrisl I see movement of both motors always in one direction without changing direction as required, but too fast, code above is default  for device. My goal is to make movement   in one direction,  but with a slower  speed, same way as it is done, except for the behavior that you described, although I did not checked it for 136h

The speed of your servo is controlled by the pulswidth of a square wave signal. According to the datascheet of the servo the motor stops on a pulsewith of about 1500 µSec (+- 5 µSec).
From 1500 to 900 μSec the motor turns clock wise. And it getting faster with decreasing pulsewidth.
From 1500 to 2100 μSec the motor turns counter clock wise. And it getting faster with increasing pulsewidth.
Next we have to check whether your shield and the library can handle that values and which value you have to give to the servo[i].write(?) function. I can read cyrillic but I do not understand russian good enough to read the f. manual. So I have to look into the code on GitHub (https://github.com/amperka/Multiservo/blob/master/library/Multiservo ).
Et voila:
Multiservo::attach(int pin, int minPulse, int maxPulse)

You can define the min and max pulseWidth, that's great. Let's do it:
#include <Multiservo.h>
#define SERVO_COUNT 2

Multiservo servo[SERVO_COUNT];
// speed is 0 ( full speed CW )
int speed = 0;

void setup(void)
{
  for (int i = 0; i < SERVO_COUNT; ++i)
  {
    servo[i].attach( i, 900, 2100);
    // 900 - 2100 is mapped from 0 to 180
    // so 90 is the middle where the motor stopps
    // 180 the motor runs as fast as possible CCW
    // 0 the motor runs as fast as possible CW
    servo[i].write( speed );
  }
}

void loop(void)
{
   // Here I halt the program if the motor stops.
   // If you use a lower value than 89 you can halt the program
   // at the corresponding speed. If you use a higher value instead of 89
   // the motor starts rotating counter clockwise.
   // Do not use a value greater then 179 or less than 1.
   if ( ++speed > 89 ) speed = 90;

   servo[1].write( speed );
   servo[2].write( speed );

   delay(25);
}

Ah, of cause I have not hte hardware, so I can not test the program. Use it as an example.

Hello, thank you for your answer. As I've said I want change code for this device to make move both servos always in one direction with slower speed, but now I'm not able to check your example, because seems like this shield is damaged, besides, I don't understand russian either, so I've to change this device very soon and check upload with your code, then I will comment about result to mark you answer


text:
How do I power a linear actuator at different speeds for specified periods of time
I am new to Arduino and wondering if anyone can help me get it programmed correctly. I am using two buttons to control a linear actuator to open and close a barn door. I want it to go a certain speed for a specified period of time... like 3 seconds. Then I want it to slow down and go another 2 seconds. The linear actuator does not have feedback which is fine for the application because it does not have to be precise. Below is the code I copied from the manufacturers website - it works well, but I can’t figure out how to make it go for specified periods of time. Please remember I’ve never used an Arduino before and this is literally a foreign language to me. I’m just hoping someone can tell me what to do. It’s for my house, not for a school project.
*** ADDENDUM - Thanks for the help. Wish I could post a video... Here is the final code:
/* Firgelli Automations
 * Limited or no support: we do not have the resources for Arduino code support
 *
 * Program enables momentary direction control of actuator using push button
 */

int RPWM = 10; //connect Arduino pin 10 to IBT-2 pin RPWM
int LPWM = 11; //connect Arduino pin 11 to IBT-2 pin LPWM
int RPWM2 = 5; //connect Arduino pin 5 to IBT-2 pin RPWM
int LPWM2 = 6; //connect Arduino pin 6 to IBT-2 pin LPWM
int downPin = 12;
int upPin = 13;
int speed1 = 0; // Top speed you can change it between [0-255]
int speed2 = 0; // Low speed you can change it between [0-255]
int speed3 = 0; // Low speed you can change it between [0-255]

void setup() {
  pinMode(RPWM, OUTPUT);
  pinMode(LPWM, OUTPUT);
  pinMode(RPWM2, OUTPUT);
  pinMode(LPWM2, OUTPUT);
  pinMode(downPin, INPUT_PULLUP);
  pinMode(upPin, INPUT_PULLUP);
}

void loop() {
  if(digitalRead(upPin)==LOW){ //check if extension button is pressed
    analogWrite(RPWM, 0);
    analogWrite(RPWM2, 0);
    analogWrite(LPWM, 255); // rotate motor with top speed (with PWM set to 255)
    analogWrite(LPWM2, 236); // rotate motor with top speed (with PWM set to 255)
    delay(3000);               // wait for x sec
    analogWrite(LPWM, 185); // rotate motor with low speed (with PWM set to 150)
    analogWrite(LPWM2, 181); // rotate motor with low speed (with PWM set to 150)
    delay(1600);               // wait for x sec
    analogWrite(LPWM, 80); // rotate motor with low speed (with PWM set to 150)
    analogWrite(LPWM2, 80); // rotate motor with low speed (with PWM set to 150)
    delay(1400);               // wait for x sec
    analogWrite(LPWM, 0);     // uncomment if you want to stop motor now
    analogWrite(LPWM2, 0);     // uncomment if you want to stop motor now
  }

  else if(digitalRead(downPin)==LOW){ //check if retraction button is pressed
    analogWrite(LPWM, 0);
    analogWrite(LPWM2, 0);
    analogWrite(RPWM, 254); // rotate motor with top speed (with PWM set to 255)
    analogWrite(RPWM2, 255); // rotate motor with top speed (with PWM set to 255)
    delay(3000);               // wait for x sec
    analogWrite(RPWM, 170); // rotate motor with low speed (with PWM set to 150)
    analogWrite(RPWM2, 170); // rotate motor with low speed (with PWM set to 150)
    delay(1500);               // wait for x sec
    analogWrite(RPWM, 80); // rotate motor with low speed (with PWM set to 150)
    analogWrite(RPWM2, 80); // rotate motor with low speed (with PWM set to 150)
    delay(1500);               // wait for x sec
    analogWrite(RPWM, 0);     // uncomment if you want to stop motor now
    analogWrite(RPWM2, 0);     // uncomment if you want to stop motor now
  }

  else{ //if no button is pushed, remain stationary
    analogWrite(RPWM, 0);
    analogWrite(LPWM, 0);
    analogWrite(RPWM2, 0);
    analogWrite(LPWM2, 0);
  }
}

you will need to implement a state machine sketch ... https://duckduckgo.com/?q=arduino+fsm&ia=web ... also, examine the blinkWithoutDelay example sketch to learn how to time events in a non-blocking way, so that the program can respond to button presses, and releases, while the door is moving

start by making a list if all possible states that the door has ... for example, closed, open, closing fast, closing slow, stopped in middle .... assign a number to each state ... draw a chart and indicate what happens at each state and what causes the transition from one state to another state ... https://www.instructables.com/Arduino-Traffic-Lights-Using-Finite-State-Machines/

You can do this easily by using Arduino built-in PWM function and using delay function. But remember that using delay in your code will block your code so if your program just want to sit and wait for 3 seconds at some speed then delay is ok for you else you need to implement Millis function.
first you need to define different speeds as per your requirement remember PWM function has value from 0-255 where 0 in min speed and 255 is top speed.
So here I will define speed1 for top speed and speed2 for low speed
So now your program will look like this
int RPWM = 10; //connect Arduino pin 10 to IBT-2 pin RPWM
int LPWM = 11; //connect Arduino pin 11 to IBT-2 pin LPWM
int downPin = 12;
int upPin = 13;
int speed1 = 255; // Top speed you can change it between [0-255]
int speed2 = 150; // Low speed you can change it between [0-255]

void setup() {
  pinMode(RPWM, OUTPUT);
  pinMode(LPWM, OUTPUT);
  pinMode(downPin, INPUT_PULLUP);
  pinMode(upPin, INPUT_PULLUP);
}

void loop() {
  if(digitalRead(upPin)==LOW){ //check if extension button is pressed
    analogWrite(RPWM, 0);
    analogWrite(LPWM, speed1); // rotate motor with top speed (with PWM set to 255)
    delay(3000);               // wait for 3 sec
    analogWrite(LPWM, speed2); // rotate motor with low speed (with PWM set to 150)
    delay(2000);               // wait for 2 sec
   // analogWrite(LPWM,0);     // uncomment if you want to stop motor now
  }

  else if(digitalRead(downPin)==LOW){ //check if retraction button is pressed
    analogWrite(LPWM, 0);
    analogWrite(RPWM, speed1); // rotate motor with top speed (with PWM set to 255)
    delay(3000);               // wait for 3 sec
    analogWrite(RPWM, speed2); // rotate motor with low speed (with PWM set to 150)
    delay(2000);               // wait for 2 sec
    // analogWrite(RPWM,0);     // uncomment if you want to stop motor now
  }

  else{ //if no button is pushed, remain stationary
    analogWrite(RPWM, 0);
    analogWrite(LPWM, 0);
  }
}

Excellent! Thanks for your help! Eventually I may want to use millis () but for now this works pretty dang well. Will post final code as addendum above.

Good to hear that chris.

source: Stack Exchange

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

sort: votes


text:
INA219 with L298N POWER LOGGER
I Have been working on a power logger with INA219 and L298N
the thing is, the voltage and current displayed on Serial Monitor is not the same on my multimeter.
the Arduino is connected to the pc to view the result on the serial
#include <Wire.h>
#include <Adafruit_INA219.h>

Adafruit_INA219 ina219;

//Adafruit_INA219 ina219_A;
//Adafruit_INA219 ina219_B(0x41);

void setup(void)
{
  Serial.begin(115200);
  while (!Serial) {
      // will pause Zero, Leonardo, etc until serial console opens
      delay(1);
  }

  uint32_t currentFrequency;

  Serial.println("Hello!");

  if (! ina219.begin()) {
    Serial.println("Failed to find INA219 chip");
    while (1) { delay(10); }
  }
  ina219.setCalibration_32V_1A();

  Serial.println("Measuring voltage and current with INA219 ...");
}

void data(void)
{
  float shuntvoltage = 0;
  float busvoltage = 0;
  float current_mA = 0;
  float loadvoltage = 0;
  float power_mW = 0;
    delay(2000);
  shuntvoltage = ina219.getShuntVoltage_mV();
  busvoltage = ina219.getBusVoltage_V();
  current_mA = ina219.getCurrent_mA();
  power_mW = ina219.getPower_mW();
  loadvoltage = busvoltage + (shuntvoltage / 1000);

  Serial.print("Bus Voltage:   "); Serial.print(busvoltage); Serial.println(" V");
  Serial.print("Shunt Voltage: "); Serial.print(shuntvoltage); Serial.println(" mV");
  Serial.print("Load Voltage:  "); Serial.print(loadvoltage); Serial.println(" V");
  Serial.print("Current:       "); Serial.print(current_mA); Serial.println(" mA");
  Serial.print("Power:         "); Serial.print(power_mW); Serial.println(" mW");
  Serial.println("");

  delay(2000);
}

void loop() {

    analogWrite(9, 245); //ENA pin
    digitalWrite(8, HIGH);
    digitalWrite(7, LOW);
    data();
    delay(5000);

    analogWrite(9, 200); //ENA pin
    digitalWrite(8, HIGH);
    digitalWrite(7, LOW);
    data();
    delay(5000);

    analogWrite(9, 150); //ENA pin
    digitalWrite(8, HIGH);
    digitalWrite(7, LOW);
    data();
    delay(5000);

    analogWrite(9, 0); //ENA pin
    digitalWrite(8, LOW);
    digitalWrite(7, LOW);
    data();
    delay(5000);

}

not the same on my multimeter What sort of difference are you seeing?

The INA219 gives you the instantaneous current and voltage at a given moment in time, whereas your DMM shows you the average over a period.
The L298N is giving out a PWM waveform that is rapidly being turned on and off.
You see where this is going?
Your Arduino detection will be giving you either full power or no power (or somewhere in between owing to the low-pass filter effect of the motor), pretty much randomly, whereas the DMM will give you the average over a number of samples.
You would need to rapidly sample the PWM signal over a period of time and calculate the average to get an idea of what the current and voltage might be.

Thank you sir, but do you think there is something wrong with the connection or i will just add code for DMM somewhere?

You need to add code to create an average over time of the values.

Unless I missed something, I didn't see where the control pins (7,8,9) were initialized properly.  There should be some 'pinMode()' statements in setup().  Am I missing something?

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


text:
Timer to send a periodic pulse
I am looking for a very low power, small component (perhaps an arduino) that will send a pulse 3.3V logic HIGH pulse once every X seconds to another system.  I want to be able to configure X (maybe a trim pot or something) based on the use case the most rapid use case would be about once per second and the slowest would be once per hour. The duration of the pulse doesn't really matter much as long as it's one second or less.
Adafruit sells an item (PRODUCT ID: 3573) based on a Texas Instruments TPL5110 chip that sort of does this but it's a timed constant HIGH signal, not a pulse.  I am an electronics noob and am not sure what category of component this falls under but I have tried googling and reading tutorials on timers.

There are a lot of 555 (NE555) circuits published on the web that will probably do what you want. You might search for a 555 pulse generator and pick a circuit you can build with the parts on hand.

thanks!  I will try looking for "pulse generators"

there is no "arduino" in your question

You could do that with an Arduino: that would make the question on-topic here. Then use a sleep mode and port your code to an ATtiny85 (there are Arduino cores for it): that would make the component small and low power.

As Edgar Bonet commented, you can do this using an ATtiny85 IC in an 8-pin DIP package which is available for about $1 and can be programmed using the Arduino IDE.
You have to tell the Arduino software about the ATtiny85 by installing a "core" for it such as Spence Konde's
You will need a device to transfer the program into the ATtiny85, either a $5-$15 AVR programmer or something like an Arduino Uno using the Arduino-as-ISP sketch .
Writing the software will be extremely easy by Arduino standards.
One advantage of the ATtiny85 over the same sized NE555 is that the ATtiny85 needs no external components (resistors capacitors etc) and so is a lot simpler to use. You can run this ATtiny85 on a 3.3 Volt supply (anything from 2.7 → 5.5 V will work).
If you want an ATtiny85 on a pre-assembled PCB (like that Adafruit TPL5110 product), try a Digispark or a $1 Digispark clone, it can be plugged directly into a USB port for programming with the Arduino IDE. I haven't tried running one on 3.3V but I suspect that should be possible by connecting the 3.3V supply to the "5V" pin to bypass the Digispark's 5V regulator.

See https://wokwi.com/arduino/projects/310458692893934146

I was also able to run it on a cheap Digispark clone from a 3V3 supply

The only advantage over a bare ATtiny85 is that you don't need any programming hardware, just a USB port on a PC.

Awesome idea!  this is perfect. I hadn't thought of an Arduino as a subcomponent of another arduino! I also appreciate the really thorough answer with the great links, sketch, and even picture. Really helpful and I appreciate it

Do you have thoughts about making this sleep between pulses since I'd need that to be low power?

@rfii: That's a different question, there may be some answers to similar questions here. You need to put the device into a low-power sleep-mode and set an interrupt-timer to wake it. There's a really good example project at David Johnson-Davies's blog - he has many projects that use low-power sleep to extend battery life. He does tend to use a more serious coding style though.

Thanks! I found code from Sparkfun at https://learn.sparkfun.com/tutorials/h2ohno/all which has sleep functions.  I inserted sleep periods in and it works


text:
How can I get a Faster boot with the Adafruit Feather SAMD21?
The Adafruit Feather SAMD21 takes about two seconds from power being supplied to when setup() starts running.  How can I shorten that time so that setup() will run sooner?  I measure this time using a power supply and others appear to measure similar times with their eyeballs.
I understand that 328 microcontrollers can be made to boot quicker (almost instantly from a human perspective) using different bootloaders for example, but I haven't found one for the M0 SAMD21 nor another method.
The code isn't relevant because the blink example shows the same timeframe, but here's another example:
//no libraries, global variables, nothing.
setup(){
digitalWrite(LED_BUILTIN, HIGH);
}

loop(){
}

I dont think that is relevant because other people observe the same start time.  Anyway here it is, apologies for the formatting setup(){ digitalWrite(LED_BUILTIN,HIGH);} loop(){}  There is nothing else before or after.  The standard Blink example shows the same thing.

Measured with a power supply.  Other people observe about the same time.


text:
How to execute programs based on received bluetooth value - wake-up-light (ESP32)
I'm trying to execute programs on my arduino based on values received via bluetooth. Although I've experimented a lot, I'm unable to get the code to  work.
I have build a simple android app with three buttons that sends either value "11", "21" or "31" to the arduino over bluetooth, which should trigger the code to operate a DIY wake-up-light (ESP32 + NeoPixels). Can anyone tell me what I'm doing wrong? Thanks in advance!
#include "BluetoothSerial.h"
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>

// init Class:
BluetoothSerial ESP_BT;

#define LED_PIN    5
#define LED_COUNT 7

Adafruit_NeoPixel matrix = Adafruit_NeoPixel(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  matrix.begin();
  matrix.show(); // Initialize all pixels to 'off'

  Serial.begin(19200);
  ESP_BT.begin("Wake_Up_Light"); //Name of Bluetooth interface
}

int led_pin_1 = 5;
int incoming;

void loop() {

// ------------ call wakeup program or gotosleep program ----------------
  if (ESP_BT.available())
  {
    incoming = ESP_BT.read(); //Read what we receive

    int rnumber = incoming;

    switch (rnumber) {
      case 1:
        Serial.print("11"); //----- Activate wake-up light after 6 hours -----
          6hours();
          wakeup();
          ledsoff();
        break;

      case 2:
        Serial.print("21"); //----- Activate go-to-sleep mode -----
          gotosleep();
        break;

      case 3:
        Serial.print("31"); //----- Activate powernap mode -----
          gotosleep();
          wakeupdelay();
          wakeup();
          ledsoff();
        break;
      }
  }
}

void wakeup() {

    uint16_t i, j;

  for (j = 1; j < 10; j++) {
    for (i = 0; i <LED_COUNT; i++) {
      matrix.setBrightness(255);
      matrix.setPixelColor(i, 3, j, j);
    }
    matrix.show();
    delay(18000); //-------- 180.000ms (3 minutes) / 10 steps = 18.000 ---------
  }
}

void gotosleep() {

    uint16_t i, j;
  for (j = 10; j > 0; j--) {
    for (i = 0; i <LED_COUNT; i++) {
      matrix.setBrightness(255);
      matrix.setPixelColor(i, 3, j, j);
    }
    matrix.show();
    delay(16363); // ---- 180000ms (3 minutes) / 11 steps = 16363 --------
  }
  matrix.setBrightness(0);
  delay(40000); // ---- 40 seconds delay
  }

void wakeupdelay() {
  delay(1200000);
}

void ledsoff() {
    matrix.setBrightness(0);
}

void 6hours() {
  delay(21600000)
}

It is not clear where you are sending what. In your text you state to send "11", etc from the android app to the ESP. But your code reacts to binary data with values of 1 to 3 from bluetooth and will itself send "11" etc. Please clarify

why are you not printing the received value? ... that would be the first thing to do when debugging ... also, why are you not saying what the problem is?

The entire code is loaded on the ESP32. I connect my phone to the ESP32 via bluetooth and send the number 11, 21 or 31 to the ESP32 (Send1ByteNumber method). The ESP32 should be listening to anything received over bluetooth and for example, when receiving value 11, it should run  6hours();  wakeup();  and   ledsoff(); after each other and then wait for further instructions (bluetooth input). Nothing needs to be send back to the phone/app.

The "case" values inside your "switch" statement currently compare the received value to 1, 2 and 3, not to 11, 21 and 31 like your intention seems to be.

Thanks for the replies. I've taken another aproach and was able to get the code to work. I'll post it here. Not yet 100% finished, but mostly doing what I wanted.
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "BluetoothSerial.h"
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>

#define LED_PIN    5
#define LED_COUNT 7

Adafruit_NeoPixel matrix = Adafruit_NeoPixel(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);

String  Recvd;
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif

BluetoothSerial ESP_BT;
void printDeviceAddress() {

const uint8_t* point = esp_bt_dev_get_address();

for (int i = 0; i < 6; i++) {
   char str[3];
   sprintf(str, "%02X", (int)point[i]);
   Serial.print(str);
   if (i < 5){
   Serial.print(":");}
}
Serial.println();
}

void setup()
{
Recvd = "";

Serial.begin(19200);

  ESP_BT.begin("Wake_Up_Light");
  Serial.println("Address:");
  printDeviceAddress();

}

int led_pin_1 = 5;
int incoming;

void loop()
{
matrix.setBrightness(0);
matrix.show();
    if (ESP_BT.available()) {
      Recvd = (ESP_BT.read());
      Serial.println("Received value:");
      Serial.println(Recvd);
      if (Recvd == "11") {
        Serial.println("Running wake-up>6hr mode");
        sixhours();
        wakeup();
        ledsoff();

      }
      if (Recvd == "21") {
        Serial.println("Running go-to-sleep mode");
        gotosleep();

      }
      if (Recvd == "31") {
        Serial.println("Running powernap mode");
        gotosleep();
        wakeupdelay();
        wakeup();
        ledsoff();

      }

    }

}

void wakeup() {

    uint16_t i, j;

  for (j = 1; j < 10; j++) {
    for (i = 0; i <LED_COUNT; i++) {
      matrix.setBrightness(255);
      matrix.setPixelColor(i, 3, j, j);
    }
    matrix.show();
    delay(18000); //-------- 180.000ms (3 minutes) / 10 steps = 18.000 ---------
  }
}

void gotosleep() {

    uint16_t i, j;
  for (j = 10; j > 0; j--) {
    for (i = 0; i <LED_COUNT; i++) {
      matrix.setBrightness(255);
      matrix.setPixelColor(i, 3, j, j);
    }
    matrix.show();
    delay(16363); // ---- 180000ms (3 minutes) / 11 steps = 16363 --------
  }
  matrix.setBrightness(0);
  delay(40000); // ---- 40 seconds delay
  }

void wakeupdelay() {
  delay(1200000); // (20 minutes)
}

void ledsoff() {
    matrix.setBrightness(0);
}

void sixhours() {
  delay(21600000); // (6 hours)
}


text:
I cant get a stepper motor to work with arduino UNO
I'm using an arduino UNO with a L2989N motor controller with a nema 17 hanpose 17h3401 stepper motor. I'm using two 9 volt batteries in series to power it. I'm sure I connected them properly but it just doesn't work. I tried using the example stepper motor sketch stepper_oneRevolution but it didn't work. I just cant pinpoint what's wrong.
PS. I'm very new to this

standard 9V block batteries? They are not made for providing that much current. You need other batteries

It is highly likely your power source supplies insufficient current to power both the stepping motor and the Arduino reliably.
This is very similar to one of my past stackexchange question / answer.
Where I say ...

Consider using a power source which can supply more current.  For
instance, D size cell batteries can supply much more current than
a small 9 volt battery.

... all that said, stepping motors are high current devices.  It may not be feasible to run stepping motors off batteries.

Can you post a schematic as you have wired it showing all connections. You connect a lot of things but to what? Also post links to the hardware items. I did not find the L2989N motor controller.

@Gil, if you are asking questions of the O.P. then you might put your comment after the Question and not after the Answer. Then the O.P. might get a notification instead.

@김준호, do edit your original post instead of posting an answer.  Otherwise it is confusing as people can and do sometimes answer their own questions.  A L298 does not appear to have a 12v to 5v regulator.  But maybe there is one on the board you bought?  Do you have a link to that product?  What a battery can power depends on more than it's chemistry (LiPo) or voltage (14.8V).  Maybe try 2 different batteries.  One for the Arduino and another for the motor.  As a test if nothing else. Just so you know, some large steppers may need the likes of a motor cycle battery to keep running.


text:
How can I split data coming from JSON?
In my recent project, I'm working with Arduino and JSON. Now, I get data from JSON and I can able to receive in Arduino side.
Below one is my Arduino code:
#include<LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

String response = "";
bool begin = false;

void setup()
{
  Serial.begin(9600);
  lcd.begin(16, 2);
}

void loop()
{

  while(Serial.available() || !begin)
  {
    char in = Serial.read();

    if (in == '{')
    {
      begin = true;
    }

    if(begin) response += (in);

    if(in == '}')
    {
        break;
    }
    delay(1);
  }

  lcd.setCursor(0, 0);
  lcd.print(response);
}

Output :
{"TPS":"0.40","MAP":"1.05","LOAD":"14"}

Now, I want to split data means store 0.40 in one variable, 1.05 in another variable and 14 in another variable. I don't know how to split this.

Try this: https://hackingmajenkoblog.wordpress.com/2017/04/08/splitting-up-text-in-c/

Can try this JSON library: https://github.com/bblanchon/ArduinoJson

@goddland_16 I try out that library but I face one problem.

if you know the number of variables and it is fixed, and the order of incoming data, you can parse yourself. Well, I can parse the example string provided all the above conditions are met.

Finally, I got it. I have fixed length of data. So, I use a counter to calculate the how many characters are there in my data. Now using the index of this characters, I find out proper data and then store in a different variable.
Below is my code:
#include<LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

String responseOne = "";
String responseTwo = "";
String responseThree = "";
bool begin = false;

int counter = 0;

void setup()
{
  Serial.begin(9600);
  lcd.begin(16, 2);
}

void loop()
{

  while(Serial.available() || !begin)
  {
    char in = Serial.read();

    if (in == '{')
    {
      begin = true;
    }

    if(begin)
    {
      counter++;

      if(counter >= 9 && counter <= 12)   // This gives 0.40
      {
        responseOne += (in);              // 0.40 store in responseOne variable
      }

      if(counter >= 22 && counter <= 25)  // This gives 1.05
      {
        responseTwo += (in);              // 1.05 store in responseTwo
      }

      if(counter >= 36 && counter <= 37)  // This gives 14
      {
        responseThree += (in);            // 14 store in responseThree
      }
    }

    if(in == '}')
    {
        break;
    }
    delay(1);
  }

  float newResponseOne = responseOne.toFloat();  // Convert string into Float
  float newResponseTwo = responseTwo.toFloat();  // Convert string into Float
  int newResponseThree = responseThree.toInt();  // Convert string into Integer

  lcd.setCursor(0, 0);
  lcd.print(newResponseOne);

  lcd.setCursor(8, 0);
  lcd.print(newResponseTwo);

  lcd.setCursor(0, 1);
  lcd.print(newResponseThree);
}

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


text:
Why the command noDisplay() clear all LCD screen?
i want to preserve video information for long time without communicating with arduino on lcd 1602, i'm tryng to use the command of liquidCrystal library noDisplay() but when i use it,this clear all display. On arduino website here is the description of this command "Turns off the LCD display, without losing the text currently shown on it." but i lose all on screen. Thanks for reply
there is my test code
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void setup() {
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("hello, world!");
}

void loop() {
  // Turn off the display:
  lcd.noDisplay();
  delay(500);
  // Turn on the display:
  lcd.display();
  delay(500);
}

with this code display blinking and don't show continuos "hello word".

I tried out your code. It's working absolutely fine.
Whenever lcd.noDisplay() executes then LCD not displaying hello, word!...
And whenever lcd.display() executes then LCD displaying hello, word!...
So, that's why "hello word" not continuously displaying.
And you can also find the display() and noDisplay() functions to turn on and off
the display comment on top of arduino sketch.

I tried out your code. It's working absolutely fine.
Whenever lcd.noDisplay() executes then LCD not displaying hello,
  word!... And whenever lcd.display() executes then LCD displaying
  hello, word!...
So, that's why "hello word" not continuously displaying.
And you can also find the display() and noDisplay() functions to turn
  on and off the display comment on top of arduino sketch.

To follow on @Hasan's answer:
noDisplay() doesn't clear the previous displayed stuff, it just inhibits it, all displayed pixels are latched in the chip while it remains powered on.
In case you need to clear the display, you can use lcd.clear() function.

i don't need to clear but to preserve the words on display without communicating

Then, as Hasan answered you, just remove the first 2 lines of the loop... particularly lcd.noDisplay(); ... By the way, you can remove everything that is in the loop() function. Just update the text when needed using lcd.print("new text") function.

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


text:
Input-Output Circuit Issue
I have design a circuit with 2 led (red and UV) and 2 button.So, the circuit supposed to work like this:
If i press the button for red led, the red led lights up and the uv led turn off, and if i press the button for uv led the uv led lights up and the red led turn off.

But the circuit is not work like that, when i upload the code, the uv led suddenly turn on without touching the button.The red led had no issue.The red led turn on when the button is push.And turn off when the button is unpress.But when i push the red button, the uv led does not turn off.It stay glow.The uv led turn on whatever i push the button or not.
Here is the code :
int red = 8;
int uv = 9;
int redbutton = 2;
int uvbutton = 3;
int redbutcondition = 0;
int uvbutcondition = 0;

void setup()
{
  pinMode (red, OUTPUT);
  pinMode (uv, OUTPUT);
  pinMode (redbutton, INPUT);
  pinMode (uvbutton, INPUT);
}

void loop()
{
  redbutcondition = digitalRead(redbutton);
  uvbutcondition = digitalRead(uvbutton);

  if (redbutcondition == HIGH)
  {
    digitalWrite(red, HIGH);
    digitalWrite(uv, LOW);
  }
  else if(uvbutcondition == HIGH);
  {
    digitalWrite(uv, HIGH);
    digitalWrite(red, LOW);
  }
}

Your Schematic seem to be wrong. Let me do correct it.

Are your buttons definitely plugged into pins 2 and 3? The schematic and the code look correct, but the picture looks like there is they're not plugged into neighbouring pins - it looks like there is a gap between them, but it is very hard to tell conclusively.

Try out this schematic. It will work.

So code will be :
int red = 8;
int uv = 9;
int redbutton = 2;
int uvbutton = 3;
int redbutcondition = 0;
int uvbutcondition = 0;

void setup()
{
  pinMode (red, OUTPUT);
  pinMode (uv, OUTPUT);
  pinMode (redbutton, INPUT_PULLUP);
  pinMode (uvbutton, INPUT_PULLUP);
}

void loop()
{
  redbutcondition = digitalRead(redbutton);
  uvbutcondition = digitalRead(uvbutton);

  if (redbutcondition == LOW)
  {
    digitalWrite(red, HIGH);
    digitalWrite(uv, LOW);
  }
  else if(uvbutcondition == LOW)
  {
    digitalWrite(uv, HIGH);
    digitalWrite(red, LOW);
  }
}

To make that work need to change pinMode (redbutton, INPUT);
pinMode (uvbutton, INPUT); to pinMode (redbutton, INPUT_PULLUP);
pinMode (uvbutton, INPUT_PULLUP); and invert the logic in if's

@jwpat7 Yeap, you're right.

But im using a pull up resistor on the button.So, i didnt need INPUT_PULLUP right?I think my schematic and my code are wrong.Btw thanks for your help

@deadguy88 May be you're right. But it is better to apply pull up through program because why you use extra circuitry if that things happens through program. Usually, I prefer this things. Try out my code and schematic. It will definitely work.


text:
ESP8266 Serial Communication with ATMega328P
I am isolating the ATMega328P from the Arduino Uno. I have used it for many other projects, so it does work as intended. Also, I have used my ESP8266-01 for other projects and works great (including serial communication).
I am trying to get the ESP8266-01 to make the ATMega328P pin 13 blink an LED. That is all.
When the ESP8266 is hooked to the TX/RX of the arduino board, the program works exactly as intended. I hook it up the exact same way to the ATMega328P and it doesn't work.
I am using baud rate of 9600 for the communication and using a 16MHz crystal for the ATMega328P.

simulate this circuit – Schematic created using CircuitLab
The controller is getting 3.3v from the supply as well. And pin 13 is supposed to turn on/off depending on the serial value. Below is the code for the ESP8266:
#include <ESP8266WiFi.h>

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

void loop() {
  delay(10000);
  Serial.write("LED ON");
  delay(10000);
  Serial.write("LED OFF");
}

And below is the code for the ATMega328P:
#include <SoftwareSerial.h>

SoftwareSerial esp8266(2,3);

void setup()
{
  Serial.begin(9600);
  esp8266.begin(9600);
  pinMode(13, OUTPUT);
}

void loop()
{
  if(esp8266.available())
  {
    String command = "";
    while(esp8266.available())
    {
      command += (char)esp8266.read();
    }

    if(command == "LED ON") {
      digitalWrite(13, HIGH);
    }

    if(command == "LED OFF") {
      digitalWrite(13, LOW);
    }
  }

  delay(500);
}

As stated, they work great separately, but when I try serial communication with them together, it doesn't work.
P.S. I usually set my ESP8266 baud rate to 115200, but the ATMega328P, I believe, needs to run at 9600 because of the 16MHz clock frequency. Not sure about this part, though.
EDIT:

simulate this circuit

"but the ATMega328P, I believe, needs to run at 9600". Its hardware UART is fully capable of 115200 baud and higher. The 9600 baud limitation applies to a SoftwareSerial port, which is simulated by programmed 'bit-banging' on another pair of digital I/O pins.

Generally, try to debug the problem.  Evidently either you're not getting data from your esp8266.available() and/or esp8266.read(), or it's not the right data.  Put traces (Serial.println(...)) in, print things out, and find out what's going wrong.

Specifically, I suspect the issue here is that you are relying on all the data being available immediately: you check esp8266.available() which will tell you whether one or more bytes is available.  Then you esp8266.read() until there are no more bytes available.  What if there's a 1ms delay between bytes arriving?  You'll get,perhaps LED O, esp8266.available() will tell you there's no more data (there's not, yet!) and you stop reading.
You could probably get it working by putting a small delay() in:
while(esp8266.available())
{
  command += (char)esp8266.read();
  delay(100);
}

That's a solution (probably) but not a good one.  A better solution would be to make your commands LED_ON\n and LED_OFF\n - and read until you get a \n.

I tried the above and still no luck. I don't think that would be the issue because the code works with the atmega attached to the uno. All I truly did was isolate it from the uno and added the 16MHz crystal for the external clock.

I don't know then, sorry. What is actually going wrong? Have you put trace in to find out how far it's getting, where it's failing etc?

I put it back into the uno, and now it is not working. I may have messed up the controller. I will try with a new atmega.

Okay. It works perfectly with the uno. But when I take the controller off and set it up as shown above, it wont work.

Omg. I figured it out. I forgot to power the other side of the chip. wow.


text:
Current difference between pinMode(pin, INPUT_PULLUP) and digitalWrite(pin, HIGH)?
Does pin 5 or pin 6 use more power if they're just being used as a signal to an external device?
pinMode(5, INPUT_PULLUP);

pinMode(6, OUTPUT);
digitalWrite(6, HIGH);

.
EDIT:  Thanks to some links below, I hopped thru a series of threads until I found the website www.gammon.com.au/power which did tests with a 328 and found the following results with the pins disconnected (which is different than my question but seems relevant nonetheless):
In SLEEP_MODE_PWR_DOWN:

All pins as outputs, and LOW: 0.35 µA.
All pins as outputs, and HIGH: 1.86 µA.
All pins as inputs, and LOW (in other words, internal pull-ups disabled): 0.35 µA (same as before).
All pins as inputs, and HIGH (in other words, internal pull-ups enabled): 1.25 µA.

See also resistor - does INPUT_PULLUP use power?.

It all depends on the external device. If it has high-impedance inputs,
then it makes no difference. The Arduino itself has high-impedance on
its pins configured as INPUT. If the device draws current from this
signal, then chances are it will draw more current from an OUTOUT
HIGH than from an INPUT_PULLUP. How much more? We cannot say without
knowing the specifics of that device.
If you model the device as a simple resistor to ground (which is almost
certainly overly naive), then the current draw is
I = VCC / (R + Ro)
where R is the value of the resistor and Ro the output
resistance of the Arduino: about 25 Ω for an OUTPUT and
32 kΩ for an INPUT_PULLUP.

Thanks, for us noobs is the signal wire to most transistors/MOSFETs considered high-impedance?

@rfii: The input of a MOSFET (the gate) is high impedance (it's actually capacitive, thus high impedance for DC). The input of a BJT (the base) is low impedance, and it needs a current-limiting resistor.


text:
arduino 28BYJ-48 stepper only whining, not rotating
Edit, this question has been answered in the comments by chrisl, and also after retesting the code with delay() which showed I forgot to update my lastupdate variable(eerst), I have answered it in the comments and chrisl possibly also will post their findings in a answer
TLDR- 28BYJ-48 unipolar 5v not working only whining. run using transistors and code in the bottom of the post. transistors connected to 5V and resistors ranging from 100ohm to 1000ohm tried from Arduino to the transistors Trigger/Gate. - END TLDR
More Detailed
I have some 5v and 12v 28BYJ-48 unipolar stepper motors,(I only connect one to the Arduino at a time) the common(tested with resistance meter) is connected to +, and I the other pins are connected to one BC336 transistor per pin so 4 in total. these transistors should handle 0.8A a piece and I measured the maximum amperage used by the coils to be 0.2+-0.02A for the 5v version at 5v, and 0.045 +- 0.001A for the 12v version at 5v. it makes sense if the 12v version doesn't work at 5v, I just wanted to test it to have an ultra-low-power stepper motor. however the 5v version should work, My setup allows a higher voltage drop in the coils in the motor and can handle a higher amperage than a normal driver however this is limited by the motors resistance ofcource.
I drive it according to the steps in the datasheet with the standard method. and simplified my code to leave out all extra things and even hardcoding the values but still it only whiles and doesn't run the motor. I use the Arduino 5v to run the stepper motor but according to the datasheet and my measurements, you could drive more than one stepper motor on the 5v pin, even when running from USB power. I also set it really slow so that it should work(based on datasheet). I want to get this working like this because I am working on a custom budget stepper driver for Arduino which allows much simpler control, and which is much cheaper than the current drivers as well as that it by default can run higher voltage stepper motors as well, and one very specific functionality which almost everyone who has ever used one stepper motor or more has hoped that their stepper motor driver had.
I used pin 8 9 10 and 11
Broken Code:
unsigned long eerst=0;
unsigned long nu=0;
int state=0;
byte vals[8]={0b00000001,0b00000011,0b00000010,0b00000110,0b00000100,0b00001100,0b00001000,0b00001001};//made hardcoderd aray to make sure fault wasn't in the cyclic bitshifting

void setup() {
  //0b76543210 portD <-- direction right is low num left is high num, keep confusing this since it differs on some platforms and not having used arduino for a while
  DDRB=DDRB | 0b00001111;//only set 8,9,10, 11 as output do not change resst.
  PORTB=0b00000000;//simplified from only turning of 8,9,10,11 to turning of all of portb
  delay(1000);
  eerst=millis();
}

void loop()
{
  nu=millis();
  if(nu-20>=eerst)
  {

//forgot to update here
PORTB=vals[state];
state++;
if(state>7)//resets state
{
state=0;
}
}
}
Working Code (might be changed for the long overflow stabilizing), changed variable names to make it clearer for others to read:
unsigned long TimeOfLastStep=0;
unsigned long CurrentTime=0;
int step=0;
byte vals[8]={0b00000001,0b00000011,0b00000010,0b00000110,0b00000100,0b00001100,0b00001000,0b00001001};//made hardcoderd aray to make sure fault wasn't in the cyclic bitshifting

void setup() {
  DDRB=DDRB | 0b00001111;//only set 8,9,10, 11 as output do not change resst.
  PORTB=0b00000000;
  CurrentTime=millis();
}

void loop()
{
  CurrentTime=millis();
  if(CurrentTime-2>=TimeOfLastStep)//increased speed from 20ms delay to 2 ms
  {
    TimeOfLastStep=CurrentTime;//forgot this
    PORTB=vals[state];
    state++;
    if(state>7)//resets state
      {
        state=0;
      }
  }
}

I guess eerst should be the timestamp variable. You need to set this inside the if statement. Currently you are running as fast as the Arduino can, probably too fast for the motor. Also you should handle the if statement line in the BlinkWithoutDelay example if(nu - eerst >= 20). Then inside the if statement do eerst += 20;. Please test this. I will write an answer if that solves it

yes you are right, not long after posting it I saw the problem as well, and my timings were of since I assumed 100 steps per rotation, so a movement would be very slow if it did something. So I know now what I failed, it was one of those typical cases where you think something and think of typing it but then forget you didn't actually type it yet.

@chrisl You mean to edit it directly in the if statement just like you do in a for loop?
or do you mean that thing about the order of how to put the variables for non blocking code to prevent the code from hanging or misbehaving/skipping when the unsigned long flips(passed it's maximum value). if so, then that would be very helpful and why/what value order to use it for infinite amounts without needing a restart to prevent possible problems.

@chrisl the thing you mean in the second thing is  if(nu-eerst>=2), instead of if(nu-2>=eerst). right? I checked it with some mathematics and my precious code indeed was not rollover proof(weird behavior when you go beyond the max value of a unsigned variable and get back to the lowest one.

I found the problem(s) in my design, everything was right but I forgot to add eerst=nu;(first=now;, used a different language because now is used by the arduino ide).
Also I didn't read the datasheet properly and so assume 100step/revolution causing me to use delays which where to large, and so even if it worked the movement would be super slow and possibly missed.
New working code:
unsigned long eerst=0;
unsigned long nu=0;
int state=0;
byte vals[8]={0b00000001,0b00000011,0b00000010,0b00000110,0b00000100,0b00001100,0b00001000,0b00001001};//made hardcoderd aray to make sure fault wasn't in the cyclic bitshifting.
//in PortB you have the pins 8,9,10,11,12,13. you start at the back of the byte, so if 0b00000001 then only pin 8 is on. if 0b00000010, then only pin 9 is on, if 0b00000011 then pin 8 and 9 are on. PortB has 8 bits, but only 6 settable pins, so do not change the first 2 bits. you can do it more secure this should be done when using port D since that one is connected to serial. however for simplicity I did not add that code here, you can ask for it and I will probably respond with it.

void setup() { since it differs on some platforms and not having used arduino for a while
  DDRB=DDRB | 0b00001111;//only set 8,9,10, 11 as output do not change resst.
  PORTB=0b00000000; // disabling all port B outputs
  eerst=millis();//eerstm means first, set first to milis to have delay without pausing the code.
}

void loop()
{
  nu=millis();//nu is now, store this lets the code know for how long the arduino ran in milliseconds, needed for non blocking delay, only one now/nu is needed.
  if(nu-2>=eerst)// if 2 milliseconds have passed(have been waited), execute the following code.
  {
    eerst=nu;//reset the non blocking delay timer
    PORTB=vals[state];//Hardcoded values in the array above, this turns on and off pins and is much faster than digital write, selects item at number [state] of aray.
    state++;//go to next state/step
    if(state>7)//resets state
      {
        state=0;//resets state/back to state 0(1 of 8)
      }
  }
}

edit: solution was also referenced to in the comments below the post. it was really a problem about having it in mind but forgetting to type something down. anyway I will probably soon start to test with that custom driver don't know how to publish it, but will probably link it back here if I remember it. will be open source probably if I find the proper methods.

I have my new driver working, currently my current design costs around 15 cents to make yourself as a hobbyist, and it allows much more than a traditional driver as well as that it can control 2 stepper motors separately and doesn't require as much pins. however I still have to do some tests and improve things a bit to increase the efficiency and such, especially when you replace parts with custom parts. currently it is around as powerful per motor as the normal driver, but in tests I found that I could reach a much greater efficiency than the original one.

with my current setup I could make a working lithography mashine for €1,65(excluding the arduino) In this design I do use scrap parts for things like the frame and lens, the precision of the uv beam can only be changed manually in this design, I calculated it using the prices I paid for the parts, this excludes shipping and I got parts in bigger quantities, however I also included parts in this price which you probably already have laying around like resistors, transistors, a capacitor to stabilize the power,etc. I asumed one to have cables. I will probably publish how to make this thing.


text:
Arduino Uno, does a lower Aref voltage work well for measuring current? without increasing ADC integral non-linearity
I want to measure current using a Arduino Uno and use a very low resistance of 0.1Ohm or lower for the shunt resistor to measure the current(to reduce power waste and heat generation),
as a result resolution wouldn't be good at lower currents, while I do not need a very good resolution better resolution makes it more dependable and more easy to use and more universal.
and it is very unlikely that I would run close to that many amps through it, as for that it would need 10A of current to reach 1V.
my idea to solve this was to set the Aref to a lower voltage of 1.1V by setting it to the internal Aref this would mean it could measure up to 11A of current but also has 5 times as much resolution.
but I noticed people online seemed to never do this, and instead just use higher restance of 1Ohm or such or directly use a external higher resolution ADC(and still only use a small part of it) or some dedicated amp measuring hadware. so I started to wonder does the internal ADC in the arduino behave worse when set to 1.1V aref instead of the default 5V aref despite the datasheet saying it can go down to 1V aref?
setting the Aref inside of the arduino to the internal Aref of 1.1V and using a 0.1 Ohm resistor would give +-10mA resolution(up to 11A), if I where to use a 1 Ohm resistor like most others do it would even give 1ma resolution(up to 1.1A).
is there something I am missing? which is the reason why other people do not change the Aref for this?
does lowering the Aref to 1.1V cause a reduction in the lineairity of the ADC curve(so that at some places the steps are a bigger difference than at some other places) compared to when it is kept to the default 5V Aref?
or as a shorter more TLDR question:
does anyone have graphs or data available about the linearity of the arduino ADC with the ADC Aref at different voltages?
mostly to compare the linearity at a Aref of 1.1V and 5V.
definitions
ADC Linearity in this context refers to integral non-linearity
extra
I already looked into those 4 sources:

Can i supply the AREF pin with an Analog pin from the same board?
https://support.arduino.cc/hc/en-us/articles/360018922239-About-the-AREF-pin
https://www.arduino.cc/reference/en/language/functions/analog-io/analogreference/
https://electronics.stackexchange.com/questions/45664/voltage-limitations-on-aref-for-arduino
https://content.arduino.cc/assets/Atmel-7810-Automotive-Microcontrollers-ATmega328P_Datasheet.pdf?#G1202563

they all seem to confirm exactly what I was thinking with my solution.
but none of them seem to give any info about how actually the Analog to Digital converter works on different Aref voltages, so for example if using a lower Aref might for example make the steps per volt less of a straight line and instead more of a curve or such where steps might all have different voltage difference differences?
the datasheet I found only gave a fixed offset value but not how or if it was affected by the used Aref voltage, and neither any form or graph or such of the typical integral non-linearity.
only one value that it has a integral non-linearity of 0.5LSB
things people mentioned

apaerently the arduino ADC indeed has some non linearity, but no actual values are given and neither if it also depends on the Aref voltage, people mention/reffer that the arduino ADC should be most efficient at the middle value of the ADC https://arduino.stackexchange.com/a/69390/70020
to reduce energy wasting and maintain higher resolutions people recommend adding in a differential amplifier which would allow using even lower shunt resistors and still a good resolution. in theory this should do the same as changing the Aref, but then allowing even more sensitivity since the Aref can only go down to 1v so 5 times amplificaton

It may be impossible to answer without being in the heads of the people you mention. My guess is that they were simply unaware that Aref can be changed. You may want to measure the conversion noise with INTERNAL, but I doubt it could be larger (in real voltage) than with DEFAULT.

With respect to answerability, like Edgar Bonet said. They and you are potentially going down the wrong path anyway. The most essential part of what I would say about that has been said by somebody else in this answer or its comments.

is there a reason or do they just all follow and clone similar guided - we can't really explain why some people are not doing something. This sounds a bit like an XY problem to me. You say resolution is bad at lower currents. Why do you need good resolution? What are you actually trying to achieve? Even a poor resolution solution could detect if a motor is drawing too much current. The Uno isn't really designed as a high-precision instrumentation device. Having said that, using a lower voltage on AREF could help in your situation.

@NickGammon I don't actually need such good precission or accuracy indeed, as long as it is roughly right,
it is for a simple project where it needs to generate output currents in between +-100ma to around +-1A perhaps more in some cases but this is the main usage, it would need steps of around 50ma at most.
the main reason for wanting improved resultion is because with such a arduino setup I doubt many people will actually use high enough currents to not make changing Aref worth it since going over 10A with such a setup doesn't seem smart in general, and most people use it much lower anyway

@EdgarBonet it was indeed surrounding how it would affect such noice and offset in the curve of steps per volt as if they stay lineair or not.
I was thinking about testing it, perhaps wouldn't be the best way, but I thought about using a voltage divider and then comparing the 3.3v to the 5v or comparing some known voltage divider options which might perhaps show some curve shape difference when plotted, for the noise I wouldn't know how to properly test that safely since when it is connected it seems to not be to noisy anyway.

@timemage the comment you linked actually was somewhat usefull, using a opamp might be usefull even though not needed in my case probably, but it would be usefull for using way lower resistance shunts.
it also confirmed the thing I doubted about, about if there are non linearities,but it doesn't show any data or graphs on them or if changing the Aref alters that.
I shall edit my question to be more direct.

for people who don't know, they often don't know what they don't know. For those who know, they thought it is common sense, so not really talk about unless been explicitly asked for. Many nowadays prefer to read internet articles or tutorials instead of reading datasheet or application note, such as this one which talk about things like Ref source.

If you used the 3.3 volt pin as external AREF a 1.5Ω resistor would drop 3V @ 2 Amps, 3V would produce an ADC value of 930 or 2.15mA per ADC count.
If you use the 1.1V internal AREF, a 0.5Ω resistor would drop 1V @ 2A, ADC values would be the same.

Hi, that was the thing I thought as well, my question was a little unclear at first however.
but essentially in my question I more meant to ask about if I change the Aref will that change the accuracy at which the real hardware follows the calculations.
since the calculations asume each step is a fixed voltage difference but at different voltages it might be that the hardware would become less consistent in that, so I mostly wanted to know if that was the case for the arduino uno, if the consistency with which the ADC follows the calculations would change decently at a different Aref


text:
String or unsigned char to uint8_t
I'm attempting to save a string to EEPROM of an ESP8266 radio and then read it back before I encrypt the data (evenutally I would like to save the encrypted data but I'm simplifing things at the moment). Here is the source code:
#include <Arduino.h>
extern "C"
{
    #include "cryptoauthlib.h"
}
#include "aes_cbc.h"
#include <EEPROM.h>
// Key Slot number
uint8_t KEY_SLOT = (uint8_t)9;

ATCAIfaceCfg cfg;
ATCA_STATUS status;

void writeStringToEEPROM(int addrOffset, const String &strToWrite)
{
  byte len = strToWrite.length();
  EEPROM.write(addrOffset, len);
  for (int i = 0; i < len; i++)
  {
    EEPROM.write(addrOffset + 1 + i, strToWrite[i]);
  }
}

String readStringFromEEPROM(int addrOffset)
{
  int newStrLen = EEPROM.read(addrOffset);
  char data[newStrLen + 1];
  for (int i = 0; i < newStrLen; i++)
  {
    data[i] = EEPROM.read(addrOffset + 1 + i);
  }
  data[newStrLen] = '\0';
  return String(data);
}

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

    // Init the constuctor for the library
    cfg.iface_type = ATCA_I2C_IFACE;  // Type of communication -> I2C mode
    cfg.devtype = ATECC608A;          // Type of chip
    cfg.atcai2c.slave_address = 0X30; // I2C address of the Adafruit Breakout Board
    cfg.atcai2c.bus = 1;
    cfg.atcai2c.baud = 100000;
    cfg.wake_delay = 1500; // Delay of wake up (1500 ms)
    cfg.rx_retries = 20;
    atca_trace_config(stdout);
}

void loop()
{
    ATCA_STATUS status = atcab_init(&cfg);
    if (status != ATCA_SUCCESS)
    {
        Serial.println(F("atcab_init() failed : Code -> 0x"));
        Serial.println(status, HEX);
    }
    writeStringToEEPROM(0, "test");
    String retrievedString = readStringFromEEPROM(0);
    uint8_t plaintext = atoi(retrievedString.substring(1,3).c_str());
    uint8_t iv[IV_LENGTH_CBC];
    uint8_t cypherdata[sizeof(plaintext)];

    Serial.println("Beginning of the encryption !");
    status = aes_cbc_encrypt(&cfg, plaintext, sizeof(plaintext), iv, cypherdata, KEY_SLOT);
    if (status == ATCA_SUCCESS)
    {
        Serial.println("encrypted");
    }
    else
    {
        // See file atca_status.h for the code Error
        Serial.print(F("Impossible do the encryption | Code Error 0x"));
        Serial.println(status, HEX);
        return;
    }
}

and here is the error message:

EDIT**:
Found out that the "Save to EEPROM" portion of my code wasn't working so I corrected that. Here is the new code:
#include <Arduino.h>
extern "C"
{
    #include "cryptoauthlib.h"
}
#include "aes_cbc.h"
#include <EEPROM.h>
// Key Slot number
uint8_t KEY_SLOT = (uint8_t)9;

ATCAIfaceCfg cfg;
ATCA_STATUS status;

void setup()
{
    Serial.begin(74880);
    // Init the constuctor for the library
    cfg.iface_type = ATCA_I2C_IFACE;  // Type of communication -> I2C mode
    cfg.devtype = ATECC608A;          // Type of chip
    cfg.atcai2c.slave_address = 0X30; // I2C address of the Adafruit Breakout Board
    cfg.atcai2c.bus = 1;
    cfg.atcai2c.baud = 100000;
    cfg.wake_delay = 1500; // Delay of wake up (1500 ms)
    cfg.rx_retries = 20;
    atca_trace_config(stdout);
}

void loop()
{
    ATCA_STATUS status = atcab_init(&cfg);
    if (status != ATCA_SUCCESS)
    {
        Serial.println(F("atcab_init() failed : Code -> 0x"));
        Serial.println(status, HEX);
    }
    uint addr = 0;
    struct
    {
      uint val = 0;
      char str[16] = "";
    } data;

    EEPROM.begin(512);// commit 512 bytes of ESP8266 flash (for "EEPROM" emulation)
    strcpy(data.str,"test");
    EEPROM.put(addr,data);
    EEPROM.commit();
    EEPROM.get(addr,data);
    Serial.println(String(data.str));

    uint8_t plaintext = atoi(data.str);
    //uint8_t plaintext[16] = "test";
    uint8_t iv[IV_LENGTH_CBC];
    uint8_t cypherdata[sizeof(plaintext)];
    uint8_t decryptdata[sizeof(plaintext)];

    Serial.println("Beginning of the encryption !");
    status = aes_cbc_encrypt(&cfg, &plaintext, sizeof(plaintext), iv, cypherdata, KEY_SLOT);
    if (status == ATCA_SUCCESS)
    {
        Serial.println("encrypted");
        status = aes_cbc_decrypt(&cfg, cypherdata, sizeof(cypherdata), iv, decryptdata, KEY_SLOT);
        if (status == ATCA_SUCCESS)
        {
            Serial.print("Decrypted text is : ");
            for (size_t i = 0; i < sizeof(decryptdata); i++)
            {
                Serial.print((char)decryptdata[i]);
            }
            Serial.println("");
        }
    }
    else
    {
        // See file atca_status.h for the code Error
        Serial.print(F("Impossible do the encryption | Code Error 0x"));
        Serial.println(status, HEX);
        return;
    }
    delay(1000);
}

Now I'm seeing this in the terminal (no errors on compile!):
encrypted
ERROR Decrypt : ATCA_BAD_PARAMI2C send 1 bytes to addr 0x30: 01

When I change (the aes_cbc_encrypt function expects a length of 16)
sizeof(plaintext)

to
16

I see:
Decrypted text is : ␀␀␀␀␀␀␀␀l��?���?

When I proved that the encrypt/decrypt portion of my code was working, this is what "plaintext" was:
 uint8_t plaintext[16] = "test";

No text as image please. You can copy the error message as text into your question and format it the same way as the code

The function expects a pointer to the data. Try passing it by reference as &plaintext. Though I'm not sure if you really want that. The variable name plaintext suggests, that it should be text. Though it is just a number (8 bit unsigned integer)

Again, you seem to think, that plaintext contains a text message. It does not. sizeof(plaintext) is always 1, since plaintext has only 1 byte. You are encrypting a single "character", though not really a character, but the binary representation of the number. It really doesn't make any sense to me, that you would encrypt a single byte. Why are you doing the atoi() when assigning plaintext? The commented line suggests, that this should be an array containing a c string.

chrisl,
In the other working code, I had
uint8_t plaintext[16] = "test";
Without the EEPROM bit, this worked. When I try replace "test" with data.str, it gives a compile error. If I need to call something other than plaintext, fine. I'm a hardware guy that is trying my best to get better at firmware, so sorry if I'm ignorant about simple things.

The function atoi() tries to interpret a string as a textual
representation of a number written in decimal. For example, atoi("42")
returns the integer 42. Here:
uint8_t plaintext = atoi(data.str);

You are asking it to interpret "test", which does not look like a
number. In such a case, atoi() returns zero. I do not know what was
your intent, but it was probably not this.
Further down, you have
uint8_t cypherdata[sizeof(plaintext)];
uint8_t decryptdata[sizeof(plaintext)];

Given that plaintext is a single byte, its length is one. Thus this is
declaring two arrays of length one. Again, you probably meant something
else.

From you comment, I understand that you want plaintext to represent
the string "test" as an array of uint8_t.
Since both char and uint8_t represent bytes, no conversion is
needed. You can simply use the address of the original char array and
“pretend” it is the address of an array of uint8_t:
uint8 *plaintext = (uint8_t *) data.str;

I just what the string "test" stored in EEPROM and then converted in to uint so it can be placed in the aes_cbc_encrypt function. I changed the atoi command to toInt and still get the same thing. I'll edit the post to explain that in the original aes_ebc_encrypt example, I was using uint8 plaintext[16] = "test"; and that was working

that makes sense. That worked and I just put it 16 for the sizeof(plaintext). That should work for now. Thanks!


text:
Having issues with RS232 UART wiring to a physical PC connection
TL;DR: Attempting to connect UART2 on ESP32-WROOM to a physical PC RS232 results in odd behavior and ESP32 crashes or errors. Suspect electrical design problems. Wondering if I need special consideration for voltages or diodes to avoid feedback to GPIO connectors on ESP side.

Hello! I'm relatively new to the community. I'm attempting to build a tool that will interact with a video conference bridge on its serial port to do room automation (mute/unmute/answer/raise_blinds/dim_lights/etc). Since the bridge interface is serial, I want to have two usable RS232 ports. One to interact with the bridge and the other to act as a console for troubleshooting and configuration.
I've purchased several ESP32-WROOM kits and have a good portion of the rest of the tool built, but I'm now struggling with getting UART2 to talk to my physical serial port on my PC so I can troubleshoot the actual bridge interactions. I've built a test sketch that just sends "Hello!" every second or so to UART2 and echoes anything it receives on UART2 back to UART0. UART0 is set for 115200 and UART2 is set to 9600. I have changed this to match and it made no difference.
Configuration:

UART0 is 115200,8N1 on standard USB console.
UART2 is 9600,8N1 on default GPIO 17/18 (TX2/RX2).
Pin17/18 and ground are wired to an 8 port single row header which is then plugged into a Teansic RJ45 breakout board.
Using Arduino IDE serial monitor to observe. Shows as COM3 on my PC.
UART2 is connected to a StarTech USB to RJ45 adapter made specifically for Cisco consoles (ICUSBROLLOVR) it shows as COM7 and I'm just using Putty to observe.

Sketch:
#include <HardwareSerial.h>

#define RXD2 16
#define TXD2 17
#define Serial0 Serial
#define Serial2 SerialPort

HardwareSerial Serial2(2);

void setup() {
  Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);
  Serial0.begin(115200);
}

void loop() {
  while (Serial2.available()) {
    Serial0.printf("[%012d]      In: ", esp_timer_get_time());
    //Serial0.print(char(Serial2.read()));
    Serial0.print(Serial2.readStringUntil('\n'));
    Serial0.print("\n");
  }
  while (Serial0.available()) {
    Serial2.printf("\n[%012d]  Insert: ", esp_timer_get_time());
    //Serial0.print(char(Serial2.read()));
    Serial2.print(Serial0.readStringUntil('\n'));
    Serial2.print("\n");
  }
  Serial0.printf("[%012d]     Out: ", esp_timer_get_time());
  Serial0.print("Hello!\n");
  Serial2.print("Hello!\n");
  delay(1100);

}

Behaviors:
When I connect my PC up, it receive characters but they are (consistent) garbage of about the right number of characters. It looks like:

▒::
   ▒[▒::
        ▒[▒::
             ▒[▒::
                  ▒[▒::
                       ▒

I sometimes receive phantom characters in from the PC even though I'm not sending anything.
If I loop UART2 back on itself (connect TX to RX at my serial header) I get a perfect response back out UART0 as though the input was coming from the PC.
If I send data from the PC to UART2, it results in crashes/errors similar to the following. The error implies it is rebooting, but it is not:
rst:0x7 (TG0WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1344
load:0x40078000,len:13964
load:0x40080400,len:3600
entry 0x400805f0
[000000011533]     Out: Hello!
[000001111758]      In:
[000002111056]     Out: Hello!

I've observed the electrical output with an oscilloscope and it casually looked like a good RS232 signal. I went so far as to convert my character string to little endian binary and add the start and stop bits and it looks exactly like it should to me except that I am expecting that 0 and 1 should be in the range of -3 to -10 and +3 to +10 and instead the pattern appears to be about +400mV for 1 and markbits and just above zero for a 0 (relative to ground).

I have found very little to reference for RS232 to an actual PC. Almost everything appears to be logic level connections ESP32 to ESP32 or peripheral board to ESP32.
I suspect that this is a case of needing circuitry to convert the logic level voltages to external RS232 +10/-10v ranges and perhaps diodes or something to prevent phantom feedback since TX/RX have a shared ground, but I'm flying blind. I'm hoping someone here has experience with this and can point me to an answer or better reference materials.

I think I found the answer to my own question by Googling around for widgets.
There are a bunch of kits out there that do just this but Sparkfun was kind enough to provide me with a diagram on exactly how to build it.
SparkFun tutorial
I'll leave this out here for others and I'm still looking for feedback, but I think I have my answer.
It wasn't obvious to me (but should have been) that the board is only going to deal with low voltage positive (TTL) signals and the onboard UART doesn't magically make it inverted, higher voltage signals.


text:
Issue with multiple RC522s connected to Arduino Uno

THIS IS NOT A DUPLICATE QUESTION. My main problem is that whenever I
attach the third RC522, the whole system becomes unstable. When I
attach the fourth, suddenly one or two of the modules stop working,
which is completely random. I have attached a capacitor between 3.3v
and GND to regulate the voltage of the modules. There is no voltage
drop in the input. I have changed and used various kinds of wiring.

I'm building a puzzle with four RC522 modules. When I connect more than one RC522 to an Arduino Uno, the device stops working randomly. Initially, everything seemed fine. I began adding the modules one by one, but suddenly, without any apparent reason, the whole system stopped functioning.
I attempted to locate the issue by disconnecting all the RC522 modules. When only one RC522 is connected, everything works correctly. However, when I attach the MISO and MOSI pins of the second RC522 to the Arduino, the first device stops working. Additionally, when I tried using the DumpInfo example of the library, the output after adding the second device is as follows:
    Card UID: 33 6C E8 F6
    Card SAK: 08
    PICC type: MIFARE 1KB
    Sector Block   0  1  2  3   4  5  6  7   8  9 10 11  12 13 14 15  AccessBits
      15     63   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
             62  MIFARE_Read() failed: A MIFARE PICC responded with NAK.
             61  MIFARE_Read() failed: Timeout in communication.
             60  MIFARE_Read() failed: Timeout in communication.
      14     59  PCD_Authenticate() failed: Timeout in communication.
      13     55  PCD_Authenticate() failed: Timeout in communication.
      12     51  PCD_Authenticate() failed: Timeout in communication.
      11     47  PCD_Authenticate() failed: Timeout in communication.
      10     43  PCD_Authenticate() failed: Timeout in communication.
       9     39  PCD_Authenticate() failed: Timeout in communication.
       8     35  PCD_Authenticate() failed: Timeout in communication.
       7     31  PCD_Authenticate() failed: Timeout in communication.
       6     27  PCD_Authenticate() failed: Timeout in communication.
       5     23  PCD_Authenticate() failed: Timeout in communication.
       4     19  PCD_Authenticate() failed: Timeout in communication.
       3     15  PCD_Authenticate() failed: Timeout in communication.
       2     11  PCD_Authenticate() failed: Timeout in communication.
       1      7  PCD_Authenticate() failed: Timeout in communication.
       0      3  PCD_Authenticate() failed: Timeout in communication.

It's noticeable that whenever I remove the MISO and MOSI pins of the second RC522, everything works.
I've tried using six different Arduinos and eleven different RC522 modules. Initially, they workef correctly, but after some time, everything went wrong, similar to the issue described above. I've experimented with different codes, considered power drop issues, and even added a 2 A power supply. I've used both 3.3 V and 5 V supplies and attempted to add pull-up resistors to each CS line. I also made sure that every connection is correct by using the multimeter. I also tried to add decoupling cap on the VCC. I used shared and separated RST pins.
Two sample programs are below, the simple one just to test the modules:
#include <SPI.h>
#include <MFRC522.h>

#define RST_PIN         3         // Configurable, see typical pin layout above
#define SS_PIN          10         // Configurable, see typical pin layout above

MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance

void setup() {
    Serial.begin(9600);     // Initialize serial communications with the PC
    while (!Serial);        // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
    SPI.begin();            // Init SPI bus
    digitalWrite(SS_PIN, HIGH);
    mfrc522.PCD_Init();     // Init MFRC522
    delay(4);               // Optional delay. Some board do need more time after init to be ready, see Readme
    mfrc522.PCD_DumpVersionToSerial();  // Show details of PCD - MFRC522 Card Reader details
    Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));
}

void loop() {
    // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
    if ( ! mfrc522.PICC_IsNewCardPresent()) {
        return;
    }

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

    // Dump debug info about the card; PICC_HaltA() is automatically called
    mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
}

My own code:
#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN_A 10
#define RST_PIN_A 3

#define SS_PIN_B 9
//#define RST_PIN_B 7

#define SS_PIN_C 8
//#define RST_PIN_C 5

#define SS_PIN_D 7
//#define RST_PIN_D 6

#define RELAY_PIN 4  // Pin connected to the relay

MFRC522 mfrc522Array[] = {
  MFRC522(SS_PIN_A, RST_PIN_A),
  MFRC522(SS_PIN_B, RST_PIN_A),
  MFRC522(SS_PIN_C, RST_PIN_A),
  MFRC522(SS_PIN_D, RST_PIN_A)
};

String MasterTagA = "336CE8";
String MasterTagB = "336CE8";
String MasterTagC = "336CE8";
String MasterTagD = "336CE8";

String MasterMainTag = "MASTER_TAG"; // Replace with the main master tag

String tagIDA = "";
String tagIDB = "";
String tagIDC = "";
String tagIDD = "";

bool accessGrantedA = false;
bool accessGrantedB = false;
bool accessGrantedC = false;
bool accessGrantedD = false;

bool mainMasterTagDetected = false;

MFRC522::MIFARE_Key key;

unsigned long activationTime = 0;  // Time of last activation
unsigned long debounceDelay = 4000;  // Delay for relay activation (4 seconds)

// Function declarations
void activateRelay();

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

  pinMode(RELAY_PIN, OUTPUT);
  digitalWrite(RELAY_PIN, HIGH);  // Ensure relay is initially deactivated

  for (int i = 0; i < 4; i++) {
    mfrc522Array[i].PCD_Init();
  }

  Serial.println("Scan a MIFARE Classic card");

  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }
}

void loop() {
  for (int i = 0; i < 4; i++) {
    if (getID(&mfrc522Array[i], i)) {
      if (mainMasterTagDetected) {
        activateRelay();
        mainMasterTagDetected = false; // Reset main master tag detection flag
      } else {
        switch (i) {
          case 0:
            checkAccess(tagIDA, MasterTagA, accessGrantedA, "A");
            break;
          case 1:
            if (accessGrantedA) {
              checkAccess(tagIDB, MasterTagB, accessGrantedB, "B");
            }
            break;
          case 2:
            if (accessGrantedA && accessGrantedB) {
              checkAccess(tagIDC, MasterTagC, accessGrantedC, "C");
            }
            break;
          case 3:
            if (accessGrantedA && accessGrantedB && accessGrantedC) {
              checkAccess(tagIDD, MasterTagD, accessGrantedD, "D");
            }
            break;
        }
      }
      printAccessControlStatus();
    }
  }

  // If all access granted and relay not activated yet
  if (accessGrantedA && accessGrantedB && accessGrantedC && accessGrantedD && millis() - activationTime >= debounceDelay) {
    activateRelay();
    // Reset access granted flags
    accessGrantedA = false;
    accessGrantedB = false;
    accessGrantedC = false;
    accessGrantedD = false;
  }
}

boolean getID(MFRC522* mfrc522, int moduleIndex) {
  if (!mfrc522->PICC_IsNewCardPresent()) {
    return false;
  }
  if (!mfrc522->PICC_ReadCardSerial()) {
    return false;
  }

  String tagID = "";
  for (uint8_t i = 0; i < 3; i++) {
    tagID.concat(String(mfrc522->uid.uidByte[i], HEX));
  }
  tagID.toUpperCase();
  if (tagID == MasterMainTag) {
    mainMasterTagDetected = true; // Set main master tag detection flag
  }
  storeTagID(tagID, moduleIndex);
  mfrc522->PICC_HaltA();
  return true;
}

void storeTagID(String tagID, int moduleIndex) {
  switch (moduleIndex) {
    case 0:
      tagIDA = tagID;
      break;
    case 1:
      tagIDB = tagID;
      break;
    case 2:
      tagIDC = tagID;
      break;
    case 3:
      tagIDD = tagID;
      break;
  }
}

void checkAccess(String tagID,
String masterTag, bool& accessGranted, String moduleName) {
  Serial.println(tagID);

  if (tagID == masterTag) {
    accessGranted = true;
    Serial.print("Access Granted to Module ");
    Serial.println(moduleName);
  } else {
    accessGranted = false;
    Serial.println("Access Denied!");
  }
}

void activateRelay() {
  digitalWrite(RELAY_PIN, LOW);  // Activate relay
  delay(2000);  // Wait for 2 seconds
  digitalWrite(RELAY_PIN, HIGH); // Deactivate relay
  activationTime = millis(); // Update activation time
}

void printAccessControlStatus() {
  Serial.print("Access Control Status: ");
  Serial.print("Module A: ");
  Serial.print(accessGrantedA ? "Granted  " : "Denied  ");
  Serial.print("Module B: ");
  Serial.print(accessGrantedB ? "Granted  " : "Denied  ");
  Serial.print("Module C: ");
  Serial.print(accessGrantedC ? "Granted  " : "Denied  ");
  Serial.print("Module D: ");
  Serial.println(accessGrantedD ? "Granted  " : "Denied  ");
}

this is the method which I connected the modules:

UPDATE 1:
I added 1 sec delay before accessing each rc522 but did not solve the problem.
UPDATE 2
When the 1st module is connected to arduino and its SDA pin connected to the pin 10, the output of DumpInfo code is as follow
Card UID: 23 FC A0 FD
Card SAK: 08
PICC type: MIFARE 1KB
Sector Block   0  1  2  3   4  5  6  7   8  9 10 11  12 13 14 15  AccessBits
  15     63   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         62   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         61   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         60   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
  14     59   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         58   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         57   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         56   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
  13     55   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         54   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         53   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         52   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
      12     51   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
             50   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             49   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             48   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
      11     47   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
             46   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             45   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             44   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
      10     43   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
             42   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             41   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             40   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
       9     39   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
             38   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             37   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             36   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
       8     35   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
             34   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             33   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             32   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
       7     31   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
             30   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             29   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             28   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
       6     27   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
             26   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             25   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             24   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
       5     23   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
             22   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             21   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             20   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
       4     19   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
             18   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             17   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             16   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
       3     15   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
             14   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             13   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
             12   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
       2     11   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
             10   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
              9   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
              8   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
       1      7   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
              6   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
              5   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
              4   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
       0      3   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
              2   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
              1   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
              0   23 FC A0 FD  82 08 04 00  62 63 64 65  66 67 68 69  [ 0 0 0 ]

But when I connect the second one to the arduino (2nd SDA: Pin9) the output for the first one would be similar to this one:
Card UID: 23 FC A0 FD
Card SAK: 08
PICC type: MIFARE 1KB
Sector Block   0  1  2  3   4  5  6  7   8  9 10 11  12 13 14 15  AccessBits
  15     63   00 00 00 00  00 00 FF 07  80 69 FF FF  FF FF FF FF  [ 0 0 1 ]
         62   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         61   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
         60   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]
  14     59  MIFARE_Read() failed: The CRC_A does not match.
  14     58   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  [ 0 0 0 ]  Inverted access bits did not match!
         57  MIFARE_Read() failed: Timeout in communication.
         56  MIFARE_Read() failed: Timeout in communication.
  13     55  PCD_Authenticate() failed: Timeout in communication.
  12     51  PCD_Authenticate() failed: Timeout in communication.
  11     47  PCD_Authenticate() failed: Timeout in communication.
  10     43  PCD_Authenticate() failed: Timeout in communication.
   9     39  PCD_Authenticate() failed: Timeout in communication.
   8     35  PCD_Authenticate() failed: Timeout in communication.
   7     31  PCD_Authenticate() failed: Timeout in communication.
   6     27  PCD_Authenticate() failed: Timeout in communication.
   5     23  PCD_Authenticate() failed: Timeout in communication.
   4     19  PCD_Authenticate() failed: Timeout in communication.
   3     15  PCD_Authenticate() failed: Timeout in communication.
   2     11  PCD_Authenticate() failed: Timeout in communication.
   1      7  PCD_Authenticate() failed: Timeout in communication.
   0      3  PCD_Authenticate() failed: Timeout in communication.

Thanks for replay, I added 1sec delay between accessing modules., but did not work.

Did you check the documentation or source code of the MFRC522 library that it supports multiple devices?

Try to follow the ReadUidMultiReader example.

@thebusybee yes, it supports multiple devices.

@hcheung thanks for your help. It sometimes works sometimes not. I turned off my pc and when I turned it on, it stopped working. I also use new board and new RC522 with new cables.

@hcheung I think it might be related to rst pin.


text:
Adafruit_NeoMatrix / Adafruit_GFX / Print class - how does printing text work here
I am entirely new to Arduino and have not coded in C/C++ for quite a few years. I'm looking through a NeoMatrix library which extends upon NeoPixel class. That class extends Adafruit_GFX class which extends Print class. The NeoMatrix class provides a lot of logic for different configurations of NeoPixel strands. Adafruit_GFX provides a drawChar method and that's the last bit that's clear to me.
From the examples one is supposed to call print method, which is inherited from the Arduino core's Print class (as I understand this). I've been looking through the source file and for the life of me I cannot understand how this works. In the Print class there are no calls to anything that would print characters, I cannot see any of the methods overriden anywhere higher up in the Class inheritance hierarchy. Can you help me put on the write track on figuring out what's the call stack here - if I call a print method on Adafruit_NeoMatrix instance how does it finally print the text? I imagine there must be code somewhere which does call the drawChar method, checks the character width, advances the cursor - but I cannot seem to locate it :)
Here are the libraries in question:
https://github.com/adafruit/Adafruit_NeoMatrix
https://github.com/adafruit/Adafruit_NeoPixel
https://github.com/adafruit/Adafruit-GFX-Library

please edit your post and add a link to the library

To be precise, it's C++ not C.

Linked the libs.
It is C++ true.

Nick Gammon's answer is correct. You left a comment on it indicating you needed some detail:

... The libraries I've
mentioned do not seem to override any of the Print class's methods.

You will see that it does as linked and described in #3 below. And that is the analogous part to the virtual size_t write (const byte c) shown in Nick Gammon's answer.

I'm also not sure how just overwriting write as you've mentioned
works.

The write(uint8_t) in Print is pure virtual. Full treatment of (pure) virtual functions would fill chapter (or maybe two) in a C++ book. But briefly: This is a function declaration in Print without an implementation. It's essentially a hole intentionally left in Print for a byte-writing-type-thing to be filled in by a derived class, which in this case is Adafruit_GFX. If you try to instantiate a variable of type Print (literally like Print myPrint;) you will see an error mentioning write(uint8_t) because it is still yet missing from the complete type.  If you know what a callback is using a function pointer, a pure virtual function is a bit like that. When Adafruit_GFX overrides Print and supplies its own definition for write(uint8_t) (as you'll see below) it effectively registers that as a callback that is used anytime anything tries to use Print's write(uint8_t) on the Adafruit_GFX object (or in this case, that part of the larger Adafruit_NeoMatrix object). That includes the other parts of Print (the other overloads of print/println that understand how to numbers or whatever else) that use write(uint8_t) directly or indirectly. If you really want to know more about what that looks like in typical generated code look up how vtables work.

I call a print method, something should iterate through all the
characters and call the write methods - I'm looking for that code,
trying to understand the whole flow of the printing process.

You can dig through the code and find all the places that it does that. Here's one example of far too many. It's an internal helper function for printing an integer that you'll find used from some of the publicly accessible print() functions that deal with numbers. As you can see, it uses write(uint8_t).
As you dig around in whatever core, you will find that everything funnels toward calls to that function.
But you can also just observe that the only pure virtual function in Print is the one for writing individual bytes.
You'll notice that there is also nothing similar; e.g. there's no function to register a callback.  So, in the general case of Print-capable things (LiquidCrystal, SD.h files, Serial, etc) the pure virtual single-byte handling overload of write() is the necessary and sufficient thing for making a class derived from Print.
It can optionally have specific behavior around flushing. It can optionally have an override of write that handles multiple characters; that would reduce call overhead for multiple characters. If you spend a few hours and track down all of the calls in ArduinoCore-API's or ArduinoCore-AVR's Print internals you will find that they all boil down do calls to the pure virtual write(uint8_t) (in the absence of a subclass overriding the block-form of write). So this one (or nearly one) pure virtual function simply is the mechanism by which the generic stuff in Print causes the use-case-specific stuff in the derived class to happen.
Your specific case
The below shows a sequence of events including where the implementation of write(uint8_t) is specific to your case.

There's only so much to say about this. You're calling some print function. So you're calling directly into the Print code, not anything in Adafruit's code yet. But, keep in mind you're doing this on an object for which Print has been completed with a definition of write(uint8_t) inside Adafruit_GFX, linked below.

There's not note specific thing to understand this part except to say that there are only a handful of pure virtual functions in Print. The only one of note here is write(uint8_t). It's technically possible for derived from Print to implement the block-accepting form of write(). But Adafruit_GFX like most things does not do that and instead relies on the default implementation of the block-accepting overload for write() to defer to overload that handle individual bytes.

Here Adafruit_GFX is pushing the work from its write(uint8_t) to drawChar() I've only highlight one place where it does that call.

drawChar() offloading work to writePixel()

writePixel() calls drawPixel(). There's a note above that apparently speaks to a potential distinction between write vs draw for things that override writePixel. NeoMatrix does not override writePixel(). So, no distinction.

drawPixel() is pure virtual in Adafruit_GFX. Its implementation  for NeoMatrix calls into the NeoPixel class.

The sketch call to show() just goes right into the NeoPixel part o the object to send the wire payload per usual. It's not overridden by NeoMatrix to do anything additional.

Nicely explained, very good!

If you derive a class from the Print class then all you have to do is override the write function to write to the device in whatever way you want. For example, using SPI, I2C, Neopixels, or whatever.
This lets you leverage off the things Print lets you do (print integers, characters, strings) and all you have to do is supply a function that outputs a single character.
Here's an example from my web page about doing Arduino debugging:
 class tSPIdebug : public Print
  {
  public:
    virtual size_t write (const byte c)
      {
      digitalWrite(SS, LOW);
      SPI.transfer (c);
      digitalWrite(SS, HIGH);
      return 1;
      }  // end of tSPIdebug::write
  }; // end of tSPIdebug

Notice how I've made a class derived from Print and all it does is override how write handles output. All the rest then is handled by Print and all my class has to do is actually do the printing of one byte.

I understand how this is supposed to work. The libraries I've mentioned do not seem to override any of the Print class's methods.
I'm also not sure how just overwriting write as you've mentioned works. I call a print method, something should iterate through all the characters and call the write methods - I'm looking for that code, trying to understand the whole flow of the printing process.

Timemage has explained in a lot more detail. Adafruit_GFX.cpp implements size_t Adafruit_GFX::write(uint8_t c) which is the very function (write) that I mentioned. That class is derived from Print: class Adafruit_GFX : public Print.