text:
Pan and tilt bracket move to sound, control servo motors using microphone sound sensors
I'm trying to code the pan and tilt bracket to turn based on where I speak, I know how to move the servo motors, but I really need help with the sound sensing. This is the code I've got currently:
#include <Servo.h>
Servo myservo;  // create servo object to control a servo
     Servo myservo2;           // a maximum of eight servo objects can be created
int sound1;
int sound2;
int pos = 0;    // variable to store the servo position

void setup()
{
  Serial.begin(9600);
  myservo.attach(5);  // attaches the servo on pin 9 to the servo object
  myservo2.attach(6);
}

void loop()
{
  sound1 = analogRead(A0);
  sound2 = digitalRead(7);

  if (sound1 > 50)
  for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees
  {                                  // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees
  {
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }

   if (sound2 > 50)
   for(pos = 0; pos < 180; pos += 1)  // goes from 0 degrees to 180 degrees
  {                                  // in steps of 1 degree
    myservo2.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
  for(pos = 180; pos>=1; pos-=1)     // goes from 180 degrees to 0 degrees
  {
    myservo2.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15ms for the servo to reach the position
  }
}

I've been working on this for some time, but for some reason, whenever I try to code the sound sensor, it always ends up being ignored, so for example, If my code says, if sound sensor number 1 detects sound, move 90 degrees vertically or horizontally, it always ignores that if statement and just continuously moves 90 degrees to wherever. I need it to follow my voice, or if that's too advanced, it's fine if it just follows any sound. So if I more 30 degree to the right on the pan and tilt bracket, and speak, I need it to turn and face me. Also, the kind of sound sensor I'm using is KY-037, the red variation with 4 pins. Any advice would be really helpful, thanks.

Why do you use digitalRead() for sound2? It will return only 0 or 1. So if(sound2 > 50) will never be true. Also currently your code tells the servo to move 180 degrees back and forth. Nothing with 90° or following you. What sound sensors do you have? I don't quite understand what you want to achieve. Do you want the servos to follow you linearily (so for example moving to 30° when you talk from 30°)? Or do you want it to change between 2 positions? What should happen if both sensors detect a loud enough sound?

What you are trying to achieve is not easy. Expect to spend a lot of time
developing, testing and tuning it.
The first step would be to work the acoustics of your device. The sound
sensors are not sensitive to the direction of the incoming sound, so you
will to have to use two of them facing different directions, like the
ears on your head face different sides. It would help to have the polar
plot of your microphones: if they are not directional enough, you may
have to build some kind of sound obstacle between them (the “head”
between the ears, or maybe even a pair of “auricles”) to improve the
angular selectivity. With cardioid microphones, you may get away with
just facing them 180° apart.
Getting this right can take significant effort. A two-channel
oscilloscope and a sinusoidal sound source would help a lot: watch the
signals coming out of both mikes, and see how their amplitudes change as
you turn the head. You want them to be sensitive enough to that
orientation. Then, adjust the potentiometers within the sound modules in
order to have the same amplitudes when the head is facing the sound
source.
Next you will have to sample these signals with your Arduino. The
default Arduino sampling rate (analogRead() in a tight loop) is about
8.93 kHz for a single channel, or 4.46 kHz per channel if
alternating between two channels. This may be enough for getting a rough
estimate of the intensity of voice, but it is kind of borderline too
low. You may want to increase the sampling rate: the way to do so has
been discussed here, and is only a search away.
With analogRead(), the sampling rate is also inconsistent and
dependent on what the sketch is doing: the more the CPU works, the
slower the sampling rate. I would strongly recommend letting the ADC
work in free running mode, and retrieve the samples from an interrupt
service routine. For this, you will have to first read and understand
the chapter on the ADC from the datasheet of the microcontroller.
Next, you have to estimate the intensities from the samples you read. In
principle, this means low-pass filtering the square of the AC part of
the signal. If that is too much work, you may get away with a simple
peak-detection.
You may want to take a look at this sound-meter sketch for
inspiration. It uses the free-running ADC technique and estimates a
sound amplitude using the proper “low-pass filtering the square of the
AC part of the signal”. It is single channel though, and you will have
to adapt it for tracking two channels. This would involve changing the
multiplexer setting within the ISR.
Lastly, you will have to make the pan servo respond to the difference in
intensities between the two ears. That is the easy part, it could
roughly go like this:
void loop() {
    float intensity_right = get_sound_intensity(RIGHT_MIKE);
    float intensity_left = get_sound_intensity(LEFT_MIKE);

    // Only move the head if we actually hear sound.
    if (intensity_right >= intensity_threshold
            || intensity_left >= intensity_threshold) {

        float difference = intensity_right - intensity_left;

        // Only move the head if the intensity difference is
        // significant.
        if (fabs(difference) >= difference_threshold) {
            if (difference > 0 && servo_position < 180) {
                servo_position += 1;
                servo.move(servo_position);
            } else if (difference < 0 && servo_position > 0) {
                servo_position -= 1;
                servo.move(servo_position);
            }
        }
    }
}

I'm trying to run this code, and "get_sound_intensity" has an error, it says it's not declared in this scope, how to define this?
Also, do you have a private email? I want to send you more details about what I'm doing. I need to finish this before 9th April, and I really need an experts help right now

@KevinZefi: Re “how to define [get_sound_intensity]”: most of my answer is about how to define it. Did you go through it? I would rather not give my private e-mail.

Ok, the thing with the oscilloscopes, I can't actually use them for the project, my project is a voice tracking camera system, the main objectives of this project is to code the servo motors and to track my voice AND my face, I managed to complete the face tracking. If what I asked for is too advanced then I can just get a simpler code, I need the code to have this kind of logic: If sound reaches sensor 1 first, turn 90 degrees, something like that. I need the project to be portable if that makes sense, I will need to present this to my professors, and I can't hook it up to an O scope.

The end result will be, to create one box which contains everything inside, so I can't have the project depend on hooking it up with oscilloscopes whenever I turn it on.
"I would rather not give my private e-mail" Ok, I'm sorry I asked, is there any other way I can send you details of my project?

Also, with the face tracking, I managed to code the servos spin based on where my face is, this was just a hunch, but can I just add the sound sensing variation on to that code?

@KevinZefi: The oscilloscope is only for the development phase, not to be kept as part of the project.

The human (and other animals) brain does far more than just look at different sound intensities to calculate angle and distance of a sound. It also compares the phase difference, something exploited by "3D sound" from stereo speakers / headphones. Incidentally it's hard to work out direction from a higher pitched and sweeping sound, which is why blackbirds use such a sound as an alarm call for airborne predators - other birds know what it means, but the hawk overhead can't work out where the call is coming from...


text:
Circular buffer implementation and Serial.print()
I am trying to implement the simplest circular buffer in Arduino. I think I am able to implement it because my push and pop functions do not return any errors. However, when I want to print the data in the buffer using Serial.print(), the code goes into an infinite loop. Here is my code:
#include <stdio.h>

typedef struct circular_buffer
{
    int buffer_arr[5];
    int head;
    int tail;
} circular_buffer;

void setup()
{
  Serial.begin(9600);
  Serial.println("Circular buffer started");
}

void loop()
{
  circular_buffer *cb;
  cb_init(cb);
  if(Serial.available()){
    char instruction = Serial.read();
    Serial.println(instruction);
    if(instruction == 'a'){
      if(Serial.available()){
        char instruction = Serial.read();
        Serial.println("here");
      }
      char key = Serial.read();
      cb_push_front(cb, key);
      Serial.print(String(key));
      Serial.println("    is entered");
    }
    else if(instruction == 'd'){
      cb_pop_back(cb);
      Serial.println("last item removed");
    }
//    for(int i=0; i<5; i++){
//      Serial.print(cb->buffer_arr[i]);
//
//    }
    Serial.println("-");
  }
}

void cb_init(circular_buffer *cb)
{
    // cb->buffer_arr = {0,0,0,0,0};
    for(int i=0; i<5; i++){
      cb->buffer_arr[i] = 'c';
//      Serial.print(sizeof(*cb));
    }
//      Serial.print(cb->buffer_arr[0]);
    cb->head = 0;
    cb->tail = 0;
}

void cb_push_front(circular_buffer *cb, char item)
{
    cb->head++;
    cb->buffer_arr[cb->head] = item;
}

void cb_pop_back(circular_buffer *cb)
{
    cb->tail++;
    cb->buffer_arr[cb->tail] = 0;
}

The for loop which I commented out is the problematic one - or at least what I believe. My problem can be very much related to my poor C-language skills. I thought that cb->buffer_arr = {0,0,0,0,0}; code piece in the initialization function should have worked (thinking very much Python-ic way) but it didn't.
So, if anyone can see the issue and help me fixing it, I'd be very much appreciated.
Thanks in advance.
EDIT
After Majenko's answer I have updated the code like that. I still have issues how to print though. I am not sure whether I am printing the address of the circular buffer as ASCII in this way. I tried to pass the cb to a print function in two ways. None seems to work, though...
#include <stdio.h>

typedef struct circular_buffer
{
    int buffer_arr[5];
    int head;
    int tail;
} circular_buffer;

circular_buffer cb;

void setup()
{
  Serial.begin(9600);
  cb_init(cb);
  Serial.println("Circular buffer started");
}

void loop()
{
  if(Serial.available()){
    char instruction = Serial.read();
    Serial.println(instruction);
    if(instruction == 'a'){
      Serial.print("a pressed");
      cb_push_front(cb, instruction);
    }
    else if(instruction == 'd'){
      Serial.print("d pressed");
    }
    else{
      Serial.print("UNKNOWN");
    }
    Serial.println("-");
  }
}

void cb_init(circular_buffer &cb)
{
    for(int i=0; i<5; i++){
      cb.buffer_arr[i] = 'c';
    }
    Serial.println("here init");
    cb_print1(&cb);
    cb_print2(cb);
    cb.head = 0;
    cb.tail = 0;
}

void cb_push_front(circular_buffer &cb, char item)
{
    cb.head++;
    cb.buffer_arr[cb.head] = item;

    cb_print1(&cb);
    cb_print2(cb);
}

void cb_pop_back(circular_buffer &cb)
{
    cb.tail++;
    cb.buffer_arr[cb.tail] = 0;
}

void cb_print1(circular_buffer *cb)
{
  Serial.println("here print1");
  for(int i=0; i<5; i++){
    Serial.print(cb->buffer_arr[i]);

  }
}

void cb_print2(circular_buffer cb)
{
  Serial.println("here print2");
  for(int i=0; i<5; i++){
    Serial.print(cb.buffer_arr[i]);

  }
}

And the returned output is like that:
here init
here print1
9999999999here print2
9999999999Circular buffer started
a
a pressedhere print1
9997999999here print2
9997999999-
a
a pressedhere print1
9997979999here print2
9997979999-

Thats not really a circular buffer. The indexes need to wrap around at the limit of the buffer (5). Otherwise you will write outside of the buffer with messages long enough.

You might find this useful: https://github.com/MajenkoLibraries/CircularBuffer

Thank you very much for the help. I sure have issues with how I pass the addresses and point to the variables. You are correct about limiting the buffer size but in this particular application, there is no way to fill the buffer - unless I code wrong :) That's why I wanted to keep as simple as possible.

You create a variable that can point to a circular buffer (*cb) but at no point do you actually point it at a circular buffer.
Either you need to create a new circular buffer or don't create a pointer, but create a statically allocated circular buffer. The latter is the preferred method.
Simply remove the * from your cb declaration, which makes a standard struct variable, then take the address of that (with &) to pass as a pointer to your other functions. Or change the other functions to pass by reference.
For example:
circular_buffer *cb;

becomes
circular_buffer cb;

And then
cb_init(cb);

becomes:
cb_init(&cb);

As do all the other functions that you pass the cb variable to.
Also every time you pass through loop() you will be wiping and making a new circular_buffer variable. Instead cb should really be global and the cb_init() call should be in setup().

Thank you for the answer. I have updated the code according to your answer. However, it seems that I still have issues with printing. Sorry to bother with those beginner questions.

There are multiple issues with this code. Majenko already showed the
main one, I will add a few more here.
First, about the circular buffer implementation. As has been stated in a
comment, for the buffer to be considered circular, the indices should
wrap around. I would add a small nitpick: it is customary, in C++, to
start filling an array from index 0. Thus you should post-increment
(rather than pre-increment) the indices:
void cb_push_front(circular_buffer *cb, char item)
{
    cb->buffer_arr[cb->head] = item;
    cb->head++;                            // post-increment
    if(cb->head == circular_buffer_size)   // with wrap-around
      cb->head = 0;
}

There is still an issue though: the buffer can overflow. You should only
add an item if there is room to do so. And you should only remove an
item if the buffer is not empty. You know that the buffer is empty when
tail=head, but how do you know when it is full? If you completely fill
the buffer and the indices wrap around as they should, you end up with
head=tail, and you cannot tell the difference between a full buffer and
an empty buffer. There are two ways around this:

You can keep an extra variable in the struct that helps you tell the
difference. This could be a count of the elements in the buffer, or a
boolean that tells you when the buffer is empty, or a boolean that
tells you when it is full.

You can refrain from completely filling the array and consider that
the buffer is full when it has been filled to its full capacity, where
the “capacity” is defined as the size of the array minus one. Then the
buffer is full when
(head + 1) = tail [modulo array length].

Here is an implementation of the second strategy:
void cb_push_front(circular_buffer *cb, char item)
{
    int next_head = cb->head + 1;          // increment
    if(next_head >= circular_buffer_size)  // with wrap around
      next_head = 0;
    if(next_head == cb->tail){
      Serial.println("buffer overflow");
      return;
    }
    cb->buffer_arr[cb->head] = item;
    cb->head = next_head;
}

int cb_pop_back(circular_buffer *cb)
{
    if(cb->tail == cb->head) {
      Serial.println("buffer underflow");
      return -1;
    }
    char item = cb->buffer_arr[cb->tail];
    cb->tail++;
    if(cb->tail >= circular_buffer_size)
      cb->tail = 0;
    return item;
}

Note that there is no point in cb_pop_back() overwriting the buffer.
On the other hand, it is often very useful for this function to return
the item that has just been popped.
Now, a few random comments:

Rather than hard-coding the array size (5) in multiple places,
define a constant at the beginning of the program
(circular_buffer_size in my examples) and use it everywhere. This
makes it clearer what the number means, and makes it easier to change
the size if you ever need to.

Since you are storing characters, use an array of char.

Your code for handling Serial does not cope well with the situation
where there is a small delay between the 'a' instruction and the
character to be added. If you can afford blocking code, the simplest
solution is to block until the user provides the character:

if(instruction == 'a'){
  while(!Serial.available())
    ;  // wait for the key to be entered
  char key = Serial.read();
  cb_push_front(&cb, key);
  Serial.print(key);
  Serial.println(" is entered");
}

Very important points, thank you! I've been struggling with passing the cb properly to the functions so I didn't put much effort on -optimization- so to say. I still have some issues in printing. I've updated the question. But I will implement these points after it. Thank you so much.

Re “I will implement these points after it”: that's not a good idea. Fix these issues right now, then you program will work as expected. Or, if it doesn't, then it will be much easier to understand what is going wrong.

source: Stack Exchange

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

sort: votes


text:
Type S Automotive underglow LEDS not responding to program in FastLEDS library
hey y'all first post here so my apologies if I'm a bit of a NEWB, I'm currently trying to control a set of individually addressable 3-pin led strips I got from the  type S formula drift LED kit model number LM532654-1. Ive used FastLEDS for a few projects now but this one is stumping me. I may have the wrong type maybe or there could be a special line of code I need to enter to talk to the chip-sets. Any help would be greatly appreciated. Also thank you all so much here on the forum, its saved my tail on so many occasions.

//#include <WS2812Serial.h>
//#define USE_WS2812SERIAL
#define FASTLED_INTERNAL
#include <FastLED.h>
#include <FastLED_NeoPixel.h>
FASTLED_USING_NAMESPACE

#define DATA_PIN1           2
#define DATA_PIN2           3

#define COLOR_ORDER         GRB
//#define LED_TYPE            WS2812SERIAL
#define LED_TYPE            SM16703
#define NUM_LEDS_1 50
int i=NULL;

CRGB leds_1[NUM_LEDS_1];
FastLED_NeoPixel_Variant strip(leds_1, NUM_LEDS_1);

void setup(){
  //pinMode(DATA_PIN1,OUTPUT);
  Serial.begin(9600);
  FastLED.addLeds<LED_TYPE,DATA_PIN1,COLOR_ORDER>(leds_1, NUM_LEDS_1)
        .setCorrection( TypicalLEDStrip );
        FastLED.addLeds<LED_TYPE,DATA_PIN2,COLOR_ORDER>(leds_1, NUM_LEDS_1)
        .setCorrection( TypicalLEDStrip );

}

void loop(){

  strip.begin(FastLED.addLeds<LED_TYPE, DATA_PIN1, GRB>(leds_1, NUM_LEDS_1));

  for(i=0; i<NUM_LEDS_1; i++){
    leds_1[i] = CRGB :: Green;
    FastLED.show();
    }

    for(i=0; i<NUM_LEDS_1; i++){
    leds_1[i] = CRGB :: Green;
    FastLED.show();
    }

No code as image please. Copy and paste the code as text into the question and format it correctly as code. Also please provide the link to that product page

probably not individually addressable

https://typesauto.com/products/type-s-formula-drift-pro-series-smart-led-exterior-lighting-kit-lm532654

Added the code in the description and posted the link above.

Ive gotten other Type S LEDS to function as Individually Addressable so as far as im aware these should function the same. But I am willing to test them out if you know of a way.

Now please format the code correctly. For that edit your question, select the code in the editor and them click the {} bitton.

How do you know that the LED-TYPE is correct? How do you even know, that the FastLED library can control them? The product page that you linked doesn't say anything about the used driver chips

I think that did it, I don't know the LED type, that's one of the things that I'm trying to figure out. The page I listed is unfortunately the only thing I have to go on. WS2812B worked for previous strips but ive mostly been shotgunning the different types that FastLEDS can support. Im currently searching the IC Chip smd5050 16703 amacrw1

https://viaisled.en.made-in-china.com/product/mjKxXShvlBVz/China-SMD5050-Addressable-Digital-16703-LED-Strip.html
the search leads me to some cheap chinese LEDS that run the same chip and those give some odd LED types Ws2811/Ucs1903/Sm16703

until you determine the exact model of the LEDs, this question is unrelated to the Arduino

Very well, Appreciate the help.

if i zoom in on the image of the strip showing the chip, it looks like it says xws28xx. Since you have the strip in-hand, search for the chip ids and that will tell you what led type you can feed fastled.

16703 amacrw1 is the chip ID, but it really doesnt bring up much on google. The link is above to some cheap LEDS that run the same chip.

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


text:
Scrambled Text on SSD1306 Using ESP32-S2
SSD1306 OLED display connected to an ESP32-S2 over hardware I2C. I noticed that the text will sometimes get scrambled or lag during a screen update. When left running long enough, the screen will get stuck and stop updating, despite serial monitor continuing to function. Does anyone know how to fix this? Here is a video of the laggy behavior: https://youtu.be/9OYW00cE24U

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
unsigned long drawState = 1;
unsigned long previousTime = 0;
unsigned long eventInterval = 4000;

#define OLED_ADDR 0x3C
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() {
  Serial.begin(115200);
  Wire.setClock(400000);
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;
  }
}

int screenSwitchLast = millis();

void loop() {

  if (millis() - screenSwitchLast >= eventInterval) {
    screenSwitchLast = millis();

    switch (drawState) {
      case 1:
        drawTemp(); //draw Temperature
        break;
      case 2:
        drawHum(); //draw Humidity
        break;
    }

    drawState++;
    if (drawState > 2) {
      drawState = 1;
    }
  }
}

void drawTemp() {
  Serial.print("Temp ");
  Serial.println(millis());
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 12);
  display.print("Temp: ");
  display.print("10");
  display.print("F");
  display.display();
  delay(1);
}

void drawHum() {
  Serial.print("Hum ");
  Serial.println(millis());
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 12);
  display.print("Hum: ");
  display.print("20");
  display.print("%");
  display.display();
  delay(1);
}

I saw this post which recommends running screen update code on the second core but the ESP32-S2 only has 1 core. I'm at odds with how I'd get this to work reliably on a single core ESP32.
Board: Adafruit ESP32-S2 Feather- 4M Flash and 2M PSRAM
Display: 128x32 12C OLED - Ox3C

Arduino Settings:
   - USB CDC on Boot: Enabled
   - CPU Frequency: 240mHz (WiFi)
   - Core Debug Level: None
   - USB DFU on Boot: Disabled
   - Erase All Flash Before Sketch Upload: Disabled
   - Flash Frequency: 80mHz
   - Flash Mode: QIO
   - Flash Size: 4MB (32Mb)
   - USB Firmware MSC on Boot: Disabled
   - Partition Scheme: Minimal SPIFFS 1.9MB APP with OTA/190KB SPIFFS
   - PSRAM: Enabled
   - Upload Mode: Internal USB
   - Upload Speed: 921600

You are constantly clear the screen as clear screen is a relatively "time-consuming" process, plus the i2c buffer for display is quite small (32-bytes if I remember correctly). Move display.clearDisplay();, display.setTextSize(2); and display.setTextColor(SSD1306_WHITE); to the setup() function as all those only need to be setup once in your application, and also move the delay(1) to the main loop, this will  help to address the lagging issue. You may need to print an extra space after "%" as "% " to overwrite the "F" previously print by the temperature string though.

I tried the changes you suggested, but the lack of 'display.clearDisplay();' leaves the "Temp: 10F" text in place and when the "Hum: 20%" gets printed, it simply overlaps it. See photo here: https://jmp.sh/23oUnVHW

You're using Adafruit's library; have you tried running their example code to see if it works for you?

Sorry, I mixed up with another library SSD1306Ascii which does not need to call display.clearDisplay() every time. BTW, I tested your original code with a 128x32 oled, and don't see the lagging your experienced, on both Adafruit library and SSD1306Ascii, but I use a classic ESP32 Dev kit.

@hcheung I switched over to a regular ESP32 as well and it's working fine. I'm really curious to find out what is causing the issue with the S2 variant, so I'm going to try the example code like romkey mentioned. I'm also going to try disabling the radios to see if that helps.


text:
Help in Frequency Conversion in ArduinoRP2040
Having a bit of a problem with the Arduino Nano RP2040. I'm trying to use the onboard microphone to read the frequency of a sound and then use that variable for calculations. However, while I can get the mic to respond to audio stimulus, I'm not sure what the values being recorded actually are. I want to be able to play for example a note at 80 Hz. I need to be able to identify a note.

Your last sentence does not make sense to me. Are you trying to play a note, or to identify a note?

install Audacity on your computer  record a sound and examine the recorded data ... https://www.audacityteam.org/


text:
ESP32 Potentiometer issue: Resolution mismatch of the potentiometer with unlimited resolution and reading the values with Wire.h
I have the problem, that the potentiometer goes from the range of 0 Volts to 3,3 volts. But within this range the measured value goes from about 0 to 65535 multiple times (over 10 cycles).
When I change the code from my ADC library to 32 bit I get 32 bit values (0 - 4294967296) but the same error with the beginning at 0 multiple times within the potentiometer range occurs.
Hardware:
Board: ESP32
ADC: MAX11613 (12 bit adc)
https://www.mouser.de/datasheet/2/256/MAX11612-MAX11617-1508955.pdf
Potentiometer: 3046L - 3 - 203 https://www.mouser.de/datasheet/2/54/3046-776396.pdf
Part of the code that reads the adc values:
uint8_t MAX11613::MAX11613_ADC_Read(structMAX11613* chip, uint8_t channel, uint16_t* val){

    uint8_t configurationByte = ( (channel<<1) & 0x0e) | 0x61;
    MAX11613_Configuration(chip, configurationByte);

    Wire.beginTransmission(chip->devAddress);
    Wire.requestFrom(chip->devAddress, (byte) 2);    // request 2 bytes from slave device wireIface
    while (Wire.available()) { // slave may send less than requested
    //char c = Wire.read(); // receive a byte as character

    uint16_t value = 0;
    value =  Wire.read();
    value |= Wire.read() << 8;

    //This also works:
    /*uint32_t buf1;
    size_t actually_read = Wire.readBytes((uint8_t*)&buf1, 2);
    *val = actually_read;
    //Serial.println(value);*/

    *val = value;
    }
    if (Wire.endTransmission() != 0){
    return 1;
    }
    return 0;

}

The MAX1161x are 12-bit ADCs, so the problem is not related to an uint16 overflow as you seem to assume.
The ADC transmits most significant bits (MSB) first as can be seen in figure 10 on page 17. To account for that you need to change
value =  Wire.read();
value |= Wire.read() << 8;

to
value = Wire.read() << 8;
value |=  Wire.read();

Youre absolutely right. In addition I had to edit the first byte transmitted, because it only transfers the first 4 digits (4 bits + 8 bits = 12 bits):

value = (Wire.read() & 0x000f) << 8;
value |=  (Wire.read() & 0x00ff);


text:
How to do multiple serial.read()
first of all im new here and im really sorry if there's some mistakes when im making this question. So im trying to make a program to calculate using serial read, and im going to input a lot of values.
These are the codes that im trying to upload, but it wont shows the input.
int PpmNeed;
int Ppmpertank;
int nyala;
int tangki;
int sensor;
int mlkeluar;
int perlakuan;
void setup() {
  Serial.begin(115200);
  Serial.setTimeout(10);
}

void loop() {
    Serial.println("Besar Tangki");
    while(Serial.available() == 0){}
    tangki = Serial.parseInt();

    Serial.println("Kadar Dari Sensor");
    while(Serial.available() == 0){}
    sensor = Serial.parseInt();

    Serial.println("Data Perlakuan");
    while(Serial.available() == 0){}
    perlakuan = Serial.parseInt();

    Serial.print("Besar Tangki : ");
    Serial.println(tangki);
    Serial.print("Kadar Dari Sensor : ");
    Serial.println(sensor);
    Serial.print("Data Perlakuan : ");
    Serial.println(perlakuan);
}

What data are your writing for the program to parse?

While your way to read the input from user is sub-optimal, to make it work you have to read the new line characters Serial Monitor sends (if line ending are selected in the drop down box).
The new line characters are available on Serial after the digits, so they make
while(Serial.available() == 0){}

to end immediately.
You can patch it up by reading the trailing line ending characters.
int PpmNeed;
int Ppmpertank;
int nyala;
int tangki;
int sensor;
int mlkeluar;
int perlakuan;
void setup() {
  Serial.begin(115200);
  Serial.setTimeout(10);
}

void loop() {
    Serial.println("Besar Tangki");
    while (Serial.available()) {
      Serial.read();
    }
    while(Serial.available() == 0){}
    tangki = Serial.parseInt();

    Serial.println("Kadar Dari Sensor");
    while (Serial.available()) {
      Serial.read();
    }
    while(Serial.available() == 0){}
    sensor = Serial.parseInt();

    Serial.println("Data Perlakuan");
    while (Serial.available()) {
      Serial.read();
    }
    while(Serial.available() == 0){}
    perlakuan = Serial.parseInt();

    Serial.print("Besar Tangki : ");
    Serial.println(tangki);
    Serial.print("Kadar Dari Sensor : ");
    Serial.println(sensor);
    Serial.print("Data Perlakuan : ");
    Serial.println(perlakuan);
}

Thankyou, it works but i change it a little bit to make it looks more neat

Your problem is that humans are slow. Very slow.
Functions like Serial.parseInt() etc are designed for reading data from sensors. As such they expect data to arrive fast. They have a timeout whereby they will abort if data doesn't arrive in a timely fashion.
That's not conducive to interacting with a human that likes to take their time typing in numbers.
Instead you will need to write a routine (or find one online, such as the one I show here) which stops and waits for input to be provided before then parsing the given data and continuing.
If you're interacting with a serial terminal rather than the Arduino IDE's serial "monitor" then it can also be good to echo back the characters as they are received so the person typing can see what they have typed. Line editing (or at least basic backspace handling) would also be useful in that situation too.

but the Serial Monitor sends the line at once and there is while(Serial.available() == 0){}

@Juraj I didn't mention the fact that parseInt() doesn't consume line endings...

but it "Looks for the next valid integer in the incoming serial"

I tested it. \n causes while(Serial.available() == 0){} skip

a short function to read user Inputs.
do not wort if user sends multiple numbers at once
USE ONLY FOR HUMAN INPUT.
#define NOP __asm__ __volatile__ ("nop\n\t")

//Read next number
int nextNumber() {
  int input = 0;

  //wait for next Byte
  while (Serial.available() == 0) {NOP;}

  /read number
  input = Serial.parseInt();

  //Give some time for bytes to get over Serial bus, then remove it
  delay(1);
  while (Serial.available() > 0) {
    int incomingByte = Serial.read();
  }
  return input;
}

There is no use for the NOP.


text:
breadboards and accurate voltage measurments
I am trying to setup a thermistor(PT1000) to work with arduino. For that I used voltage divider and 5V pin as the voltage source. I was getting very unstable results so I removed the thermistor and used 2 1kOhm resistors instead.
I was still getting results ranging from very close to true value of 1kOhm to 1.2kOhm. For reference, 4 Ohms are equivalent temperature change of 1 degree celsius.
I measured the voltage drop of each resistor and was surprised that it is far from equivalent. Check the video of full setup and the closeup wiring of the voltage divider - https://easyupload.io/5fctxm

I cannot explain the 0.3V voltage drop difference between two resistors of the same rating (resistance of 1000 Ohm +-0.5% was verified by multimeter) in any other way but that the breadboard contacts and jump wires are not suitable for accurate voltage measurement. Can someone with more experience confirm if my breadboard is broken or is such behaviour intended.

Have you measured the resistance of each resistor? That they are rated with the same resistance doesn't mean they have the same resistance. Depensing on what exactly you have you can get +-5% or +-1%

Welcome to Arduino:SE.  This looks like a question about electronics / electrical engineering, rather than Arduino.

Exactly where are you measuring a voltage that is 0.3V different (less than?  more than?) from what you expect?  Bread boards are good for saturated circuits (i.e. digital) but not great for some analog.  And terrible for high frequencies.  Values for resistor dividers are picked high enough to limit current (i.e. mitigate power requirements and unwanted voltage drops) and low enough to mitigate noise.  I would try to remove any oxides by repeated insertions and measure again.

@chrisl Resistors were also measured and are within 0.5% tolerance.

@st2000 The voltage is measured across the 5V pin and first resistor in one case and  across second resistor and the ground in the other case. The video shows more than the image.

".. the video ..." Thank you for uploading a video to an external server.  But the point of stack exchange is to preserve questions & answers so that others can in the future benefit from your question and provided answers.  Since the video will expire .. well ... it would be much better if you included a schematic directly into your question instead.  Or a picture where the resistor color bands and connections were more clear.

@st2000 I agree. What tool is commonly used to create and share schematics?

"What tool is commonly used..." I usually include pictures.  But there is an ICON in the stackexchange tool bar available when editing a Question or Answer.

In order to assess the stability of analog readings on a breadboard, I
did an experiment very similar to yours. I plugged two 1 kΩ
resistors on a breadboard, connected in series between my Arduino's GND
and +5V. I connected the middle point to A0 and made an histogram of one
million consecutive calls to analogRead(A0).
Here is my test code:
const int histo_length = 64;
const long histo_count = 1000000;
long histo[histo_length];
int histo_start;

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

    // Center the histogram on the average reading.
    int sum = 0;
    for (int i = 0; i < 16; i++)
        sum += analogRead(A0);
    int average = sum / 16;
    histo_start = average - histo_length/2;

    // Fill the histogram.
    Serial.println("Ouliers:");
    for (long i = 0; i < histo_count; i++) {
        int x = analogRead(A0);
        if (x >= histo_start && x < histo_start + histo_length)
            histo[x - histo_start]++;
        else
            Serial.println(x);  // print oulier
    }

    // Print it out.
    Serial.println("Histogram:");
    for (int i = 0; i < histo_length; i++) {
        Serial.print(histo_start + i);
        Serial.print(" ");
        Serial.println(histo[i]);
    }
}

void loop() {}

Note that the full histogram would not fit in the memory of my Uno,
hence the trick of printing out the outliers instead of recording them.
And here is the resulting histogram:
508 0
509 39386
510 960567
511 47
512 0

All other histogram bins were empty (no outliers).
As you can see, 96% of the calls returned 510. Most of those that
did not return 510 returned 509, and less than 0.005% of them
returned 511. The RMS dispersion of the readings is about
0.04 ADC steps.
I can hardly imagine anything more stable than this.

Very cool, thank you.  I later deduced that my breadboard has faulty connectors. 1kOhm measured with multimeter is evaluated at 996 Ohms. When connected to breadboard it was from 1000 to 1200 Ohms. This was my first time using breadboards so it caught me completely off guard.

Schematics even for such a question are indispensable.
Assuming from the following:

I cannot explain the 0.3V voltage drop difference between two
resistors of the same rating

... means the voltage across each of 2 different resistors both labeled 1K Ohms in series with the same 2.1K Ohm resistor connected to 5V and 0V is different by 0.3V.

simulate this circuit – Schematic created using CircuitLab
If the two 1K Ohm resistors are assumed to be 0.5% (5th color band green) and the 2.1K Ohm resistor is perfect as well as the 5V potential.  Then a 1K Ohm resistor of, say, 0.5% less impedance would be 995 ohms.  And another, say, 0.5% more impedance would be 1005 ohms.  The voltage across the 1st in this resistor divider circuit would be 1005 x ( 5 / (1005 + 2100)) or 1.62V.  And the 2nd would be 995 x (5 / (995 + 2100)) or 1.61.  This is a difference of 0.01V.  That is less then the measured difference between the two different 1K Ohm resistors given the maximum possible percent error of 0.5%.
So the the 0.3V difference between voltage readings of the two different 1K Ohm resisters are difficult to account for.  Perhaps cleaning the connections may improve the measurements.

Thank you. Both resistors are 1kOhm with 0.5% tolerance, verified by multimeter. I omitted the breadboard from all the connections and now the resistance readings are as expected.

I few days ago, when I was connecting lcd, I experienced a similar problem. If I touched the wires a little, the display went "crazy". For this one, I made a gif :D https://im.ezgif.com/tmp/ezgif-1-eabc871208.gif

Note, you may find most resistors are at the extreme edge of their specified tolerance.  This is likely due to the manufacture filtering out the more precise resistors for a higher price. You were updating the LCD constantly making it more susceptible to intermittent connections.  It might be if you stopped updating it and touched the wires, less or nothing would happen.

Nuts, there's an error in the Answer and the difference is no where near 0.3V.

Ok, fixed it. But it does indicate the measured difference of 0.3V was unexpected and could not be accounted for!  Good thing you figured it out by eliminating the breadboard.

Thank you again. Will use CircuitLab in the future question, now that I am aware of it's existence.

So breadboards contacts should have 0 Ohm resistance or is it common for them to have cause a few ohms, even at arduino current and voltage?

It is likely more random than consistently a few ohms.   This is why I initially said breadboards are good for saturated circuits (i.e. digital) and not so great for some analog and bad for high frequencies.  Again, if important, use clean wires and work any oxidation off.  Also, I didn't realize you were basing your ADC measurements off of 1 sample.  This is usually never done because of noise.  As this is embedded software (limited memory) I suggest using exponential averaging.


text:
Problem with messuring capacitance with 50 Arduinos connected by I²C
I want to measure changes in capacitance over time. One Arduino is used per capacitance sensor. There is one anode per Arduino and a total of one common cathode (see the picture)
With four Arduinos connected in series via an I²C master-slave connection, successful results were obtained.
With more than four Arduinos, all measurement results were 0, because no voltage is measured at the input pin anymore.
I then lowered the reference voltage for analogRead. So 10 Arduinos in series were possible. However, the measured values are clearly lower. However, no absolute values are to be measured, but any difference in the capacitance is sufficient. Finally 50 Arduinos should be used.
I have thought of the following possibilities:

reduce the reference voltage further, but this may reduce the measurement results further, so that no deflection is measured.
increase the output voltage at the Arduino via an operational amplifier to compensate the voltage drop.

How could I proceed to get a usable result with all 50 Arduinos? The code I used is to be found below.

Master
#include <Wire.h>

volatile byte x1, x2;
volatile int val_slave;

const int OUT_PIN = A0;
const int IN_PIN = A2;

#define nodeMax 10
#define nodeStart 2

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

  pinMode(OUT_PIN,OUTPUT);
  pinMode(IN_PIN,OUTPUT);

  Serial.begin(9600);
  // put your setup code here, to run once:

}

  void loop() {

    pinMode(IN_PIN,INPUT);
    digitalWrite(OUT_PIN,HIGH);

    int val = analogRead(IN_PIN);

    digitalWrite(OUT_PIN,LOW);
    pinMode(IN_PIN,OUTPUT);

    Serial.print(val);
    Serial.print(",");

      delay(10);

    for (int node = nodeStart; node <= nodeMax; node++) {

        // Ask the slave to release the input pin.
        Wire.beginTransmission(node);
        Wire.write(0);
        Wire.endTransmission();
        delay(10);  // give it time to do so

        // Charge the capacitors.
        digitalWrite(OUT_PIN, HIGH);

        // Ask the slave to read val.
        Wire.requestFrom(node, sizeof(val));

        // Discharge.
        x1 = Wire.read();
    x2 = Wire.read();

    val_salve = (int)x1 << 8 | (int)x2;

        Serial.print(val_slave);
        Serial.print(",");

        digitalWrite(OUT_PIN, LOW);
        delay(10);

    }
    Serial.println();
    delay(50);
}

Slave
const int IN_PIN=A2;

#include <Wire.h>
#define node 10

void setup() {
    // ...
    analogReference(DEFAULT);
    Wire.begin(node);
    Serial.begin(9600);

    pinMode(IN_PIN,OUTPUT);

    Wire.onReceive(receiveEvent);
    Wire.onRequest(requestEvent);

}

// Release IN_PIN when the master sends a message.
void receiveEvent(int byte_count) {
    pinMode(IN_PIN, INPUT);
    while (byte_count--)
        Wire.read();  // discard the received message
}

void loop ()
{
}

void requestEvent() {
    int val = analogRead(IN_PIN);
    // transmit the result... then

    Wire.write(highByte(val));
    Wire.write(lowByte(val));

    pinMode(IN_PIN, OUTPUT);  // discharge
}

You will need to massively reduce the pullup resistors on your I2C bus to counteract the increased gate capacitance of the number of devices. The more devices you have the lower the pullup resistors. After a while it becomes impractical to reduce the pullup resistors any more and you hit a limit on how many devices you can have on the bus. I would say 50 devices is far more than any sensible bus could cope with.

Is there any reason you are using 50 Arduinos rather than 4 Arduinos connected to 8-port multiplexers? That would reduce cost and also avoid your problem.

"Finally 50 Arduinos should be used" - why? Isn't this creating the problem you are trying to solve?

The cathode line is being shared by all the Arduinos' OUT_PIN. When
one of them tries to set the pin HIGH, all the others are trying to
hold it LOW. This is a short-circuit condition that can damage the
Arduino's outputs. Even if they do survive, the voltage on the line will
be significantly below 5 V because of those Arduinos pulling the
line LOW. The more of them pull the line LOW, the lower the voltage
will be.
The simple solution would be to change the protocol such that only the
Arduino that is currently making a measurement can pull that line, while
the others keep their OUT_PIN in high-impedance mode (i.e. INPUT).
This is fragile because... bugs happen, and you may still be making a
short-circuit. A more robust solution would be to connect only the
master to the cathode, and give it the responsibility to drive the line
HIGH and LOW.
Now, a coupe of unrelated comments:

A float is four bytes: there is no point in transmitting ten bytes.

You can measure up to four capacitors with each Arduino (pins A0
through A3, you can use a digital pin for OUT_PIN), it is wasteful
to use one Arduino per capacitor.

Edit: If only the master controls OUT_PIN, then some communication
protocol is needed in order to synchronize it with the slaves, so that
they can release IN_PIN at the right time. The simplest protocol I can
think of is the following: when the master sends something (anything)
to a slave, this message means “please release IN_PIN now”.
Here is some untested code implementing this idea:
master:
void loop() {
    // ...
    for (int node = nodeStart; node <= nodeMax; node++) {

        // Ask the slave to release the input pin.
        Wire.beginTransmission(node);
        Wrire.write(0);
        Wire.endTransmission();
        delay(10);  // give it time to do so

        // Charge the capacitors.
        digitalWrite(OUT_PIN, HIGH);

        // Ask the slave to read the capacitance.
        Wire.requestFrom(node, sizeof(capacitanceSlave));

        // Discharge.
        digitalWrite(OUT_PIN, LOW);

        // ...
    }
}

slave:
void setup() {
    // ...
    Wire.onReceive(receiveEvent);
    Wire.onRequest(requestEvent);
}

// Release IN_PIN when the master sends a message.
void receiveEvent(int byte_count) {
    pinMode(IN_PIN, INPUT);
    while (byte_count--)
        Wire.read();  // discard the received message
}

void requestEvent() {
    int val = analogRead(IN_PIN);
    // transmit the result... then
    pinMode(IN_PIN, OUTPUT);  // discharge
}

In an I2C configuration no-one sets the output high. The pull-up resistors do that.

@NickGammon: I am talking about the line labeled “cathode” in the drawing, not about the I2C SDA.

OK. The "circuit diagram" wasn't all that clear.

@Eggar Bonet: First of all thanks for the answeres,
i tried your suggestion by only connecting the master to the cathode and changing the code, but it didnt work. the sensor conected to the master gives a way better capacitance output, but the slaves output is "nan".
I have to use one arduino per Sensor because in previouse scientific works two sensors interferre on one Arduino and the results are bad.

@Imogdia: There must be something wrong with either your updated circuit or your updated code. You may want to update the question in order for it to reflect the current circuit and code.

@Imogdia: With the updated code, the slaves are still pulling down on OUT_PIN. And they release IN_PIN after the master has set OUT_PIN to HIGH, which is too late. You need a more elaborate communication protocol, where the master tells the slave when to release IN_PIN.

And how do I can do this?
Im totally new to arduinos and i have no programming experience

@Imogdia: See expanded answer.

I´ve tested your code (see updated threat), but the outcome is still the same.
i´ve tested your code on 10 arduinos and the results are these:
only the master gets a messurement
12:22:21.472 -> 1.38,45,nan,nan,nan,nan,nan,nan,nan,nan,nan,
12:22:21.710 -> 1.38,45,nan,nan,nan,nan,nan,nan,nan,nan,nan,
12:22:21.947 -> 1.41,46,nan,nan,nan,nan,nan,nan,nan,nan,nan,
12:22:22.186 -> 1.38,45,nan,nan,nan,nan,nan,nan,nan,nan,nan,
12:22:22.426 -> 1.38,45,nan,nan,nan,nan,nan,nan,nan,nan,nan,
12:22:22.700 -> 1.38,45,nan,nan,nan,nan,nan,nan,nan,nan,nan,

@Tizian: 1. Your slaves are still driving OUT_PIN. 2. They are not sending anything (my comment // transmit the result... was meant to be replaced by your result-transmitting code). 3. Why call Wire.onRequest() twice? 4. Try sending a fixed value (e.g. 12.34) to rule out a communication problem. 5. Why not send the raw ADC reading instead of the computed capacitance?

@EdgarBonet I´ve updated my code again. Thanks for your help! im gonna test it tomorrow and can tell you if it worked.

@EdgarBonet It worked perfectly, thank you for your help!

The I²C bus was never intended as a distribution bus between many computers. The outputs are not designed to drive long wires. With a lot of kludging you may get this to work, but it is definitely not repeatable or reliable.
Consider something else. CAN can do maybe 60 nodes, depending on the transceiver chosen. It is relatively inexpensive.

You might want to consider using a RS485 protocol. Unlike I2C this uses "balanced" wiring so is more suitable for longer cable runs.
I described a way of coding a number of Arduinos using a "rolling master" protocol here - this lets you connect a considerable number of Arduinos to the two wires, and they take turns to send the data.
However in your case, since you are measuring capacitance (not capacity?) then each of your Arduinos can measure 6 (or possibly more) analog readings, so you don't need 50, you need 50/6 = 8.33 Arduinos (OK, nine).
The Arduino Micro, for example, has 12 analog input channels, so you would only need 4 (to get 48 inputs) or 5 (to get 60 inputs). Then you could stick to I2C.

I recommended CAN because of the 50 nodes, RS485 has a limit of 32. To extend beyond that repeaters are needed.


text:
Will many nrf24L01 radio modules running at the same time cause interference?
I am working on a battle bot type of project where their will be 4 transmitters communicating with 4 receivers attached to the robots in the 4 foot x 4 foot playing field. Are their any complications that will arise when trying to run many radio modules at the same time? Like relating to interference or noise? If so, what solutions or work-arounds exist for this problem?

their means belonging to them ... i think that you wanted to use there

my battle strategy would involve trying to jam the enemy's RF, blinding it with IR LEDs, and tasering it in case they didn't shield.

According to HowToMechatronics, the NRF24L01 module can use 125 different channels which gives a possibility to have a network of 125 independently working modems in one place. Each channel can have up to 6 addresses.
I believe that as long as you agree a channel allocation amongst competitors there shouldn’t be problems.
For more information on channel setting see NRF24l01 Channel switching

Welcome Rishikesh, there is a great possibility they will have problems. Because I do not know the environment or what the hardware is configured I cannot properly answer your question without a lot more information. I can suggest Look here for some information: https://forum.arduino.cc/t/nrf24l01-transmission-problem/526158/3 Here is another link that will help: https://devzone.nordicsemi.com/f/nordic-q-a/38005/nrf24l01-communication-is-interfered-by-wifi I hope this helps.

Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference.


text:
Stream data using Firebase Realtime Database rest api with nodeMCU client
I have data on firebase rtdb, which i want to listen in my nodemcu. I know there are libraries available like this one which provides listeners, but i want to do it using REST API streaming as mentioned in firebase documentation for rest api streaming.
So far i have successfully tested with curl on cmd as shown
My curl command is:
curl -v https://<name of rtdb>.firebaseio.com/SD0001/Up.json -H "Accept:text/event-stream"

I want to do the same thing on ESP8266 using ESP8266HTTPClient library. The firebase documentation states "Set the client's Accept header to text/event-stream" (which i added in header), "Respect HTTP Redirects, in particular HTTP status code 307" (which i am still struggling).
So far, my code is somewhat like this
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>

const uint8_t fingerprint[20] = {<<<<fingerprint of rtdb database>>>>};
HTTPClient https;
std::unique_ptr<BearSSL::WiFiClientSecure>client(new BearSSL::WiFiClientSecure);
void setup()
{
  Serial.begin(115200);
  WiFi.begin("SSID", "PASSWORD");
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP()); // successful Connection of ESP8266,

  client->setFingerprint(fingerprint);

  if (https.begin(*client, "https://<name of rtdb>.firebaseio.com/SD0001/Up.json"))
  {
    https.addHeader("Accept", "text/event-stream", false, true);
    https.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);
    int httpCode = https.GET();
    Serial.println(httpCode);

    Serial.println(https.getString());
    //    Serial.println(https.getLocation());
    //    Serial.println(https.header("Location"));
    //https.end();
  }

}

void loop()
{
  //  Serial.println(https.getStream());
  //  Serial.println(https.getString());
  //  Serial.println(https.getLocation());
  //  delay(1000);
}

My code GETs the respone with 200 code, but there is no "Location" to redirect in the response header (at least i can't find any). Should i do http GET in the loop everytime? If so, where will i get my redirection url?
It would be really helpful if any solution is provided or any documentation to guide me in the right way.
Edit: I have put the text versions of curl command and the code in the post alongwith the screenshots. This is my first post here, so please bear with me.

please remove the screenshot of the code and replace it with the code text ... do the same with the first screenshot also

@jsotola i have put the actual code in text form. Please look into it. any help is appreciated as i am completely at sea here


text:
ESP32 WIFI error when trying to initialize WIFI after stopping and deinit WIFI driver
I have a firebeetle ESP32 board and I use VScode with platformIO. My platform is espressif32 v5.0.0 and the framework is arduino.
I am currently implementing a WIFI connection as follows:
bool init_wifi_STA()
{
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        Serial.print(".");
    }
    return true;
}

When I do not need WIFI anymore, I am calling the following sequence:
esp_wifi_disconnect();
esp_wifi_stop();
esp_wifi_deinit();

When I want to connect to wifi again using my init_wifi_STA() function I get the following error:

[489781][E][WiFiGeneric.cpp:1053] mode(): Could not set mode! 12289
[489781][E][WiFiSTA.cpp:227] begin(): STA enable failed!

I already found this github issue, but checking my library, it looks like the bug was removed (code section from WiFiGeneric.cpp - mentioned by the github issue):
static bool wifiLowLevelDeinit(){
    if(lowLevelInitDone){
        lowLevelInitDone = !(esp_wifi_deinit() == ESP_OK);
    }
    return !lowLevelInitDone;
}

However, I am still getting this error. Any idea where it comes from and how to avoid it?


text:
ArduinoJson buffer corruption
I have a very wierd behavior using two different ArduinoJson (6.17.3) objects on my ESP32. I was not able to reproduce it in a small example but could track it down to some extent.
From MQTT I receive a json string payload (actually it is a const char*) looking like this:
{"getLog": {"BOOL": false}, "restartESP": {"BOOL": false}, "config": {"M": {"cRI": {"N": "1200000"}, "cST": {"N": "120000"}, "SSID": {"S": "smartabell"}, "cAL": {"BOOL": true}, "PW": {"S": "smartabell"}}}, "OTA": {"S": "99"}, "time": {"S": ""}, "updateConfig": {"BOOL": false}, "MAC": {"S": "84:CC:A8:00:E7:94"}}

I store it in
DynamicJsonDocument mqttJsonDoc(MY_MQTT_MAX_PACKET_SIZE);
deserializeJson(mqttJsonDoc, payload);

for further parsing, which works fine at the beginning. However, when I call the following function to ACK the MQTT package (it is called in the same function where mqttJsonDoc is created):
bool ackDDBAction(const char *new_val, const char *ack_pub_topic)
{
    /* JSON settings */
    DynamicJsonDocument ackJsonDoc(MQTT_MAX_ACK_SIZE);
    ackJsonDoc["MAC"] = MAC_str;
    ackJsonDoc["ACK"] = "";
    ackJsonDoc["updateConfig"] = new_val;
    /* Calculate buffer length */
    size_t jsonSize = measureJson(ackJsonDoc) + 1;
    char jsonBuffer[jsonSize];
    /* Serialize json object into a char array */
    serializeJson(ackJsonDoc, jsonBuffer, jsonSize);
    /* Send ack */
    ack_success = client.publish(ack_pub_topic, jsonBuffer);

    return ack_success;
}

Somehow my original json object mqttJsonDoc is corrupted and looks like:
{"getLog":{"BOOL":false},"restartESP":{"BOOL":false},"config":{"M":{"cRI":{"N":"1200000"},"cST":{"N":"120000"},"SSID":{"S":"smartabell"},"cAL":{"BOOL":true},"PW":{"S":"smartabell"}}},"OTA":{"S":"99"},"time":{"S":""},"updateConfig":{"BOOL":false},"MAC":{"S":"84:CC:A8:00:E7:94"}}{"ub{\"MAC\":\"84CCA800E794\",\"ACK\":\"\",\"getLog\":\"0\"}0000":{"\":\"84CCA800E794\",\"ACK\":\"\",\"getLog\":\"0\"}0000":false},"CCA800E794\",\"ACK\":\"\",\"getLog\":\"0\"}0000":{",\"ACK\":\"\",\"getLog\":\"0\"}0000":false},"\":\"\",\"getLog\":\"0\"}0000":{"etLog\":\"0\"}0000":{"Log\":\"0\"}0000":{":\"0\"}0000":"0\"}0000"},"cST":{"N":"120000"},"SSID":{"S":"smartabell"},"cAL":{"BOOL":true},"PW":{"S":"smartabell"}}},"OTA":{"S":"99"},"time":{"S":""},"updateConfig":{"BOOL":false},"MAC":{"S":"84:CC:A8:00:E7:94"}}

The beginning is similar, but in the middle, fragments of the other jsonDocument ackJsonDoc appear. Besides, it is full of escape chars \. After some debugging, I found out that only when the line serializeJson(ackJsonDoc, jsonBuffer, jsonSize); is executed mqttJsonDoc gets corrupted.
I played around with dynamic and static json document but it didnt change the behavior, besides out of curiosity, I created another json object to see if somehow there was a memory overlap.
    DynamicJsonDocument mqttJsonDoc2(MY_MQTT_MAX_PACKET_SIZE);
    deserializeJson(mqttJsonDoc2, payload);

But this additional dynamic json document holding the payload as well, is corrupted when ackDDBAction() is called, too. Increasing any of the json objects by size did not lead to an improvement as well.
I was looking for known issues and cavities but didnt find anything in the documentation https://arduinojson.org/v6/api/json/serializejson/.
But maybe someone has an idea or faced this issue before - I could do some work arounds but they would be ugly and I would like to understand what is happening here.


text:
Functions downgraded in the I2S library using an ESP32
I am following the instruction to setup a microphone with an esp32 with arduino cli.
Here is the tutorial

https://dronebotworkshop.com/esp32-i2s/#Resources
https://www.youtube.com/watch?v=m-MPBjScNRk&t=915s

As pointed out in the video (timestamp 14:30 to 15:05), it seems that some functions of the I2S library were downgraded. And, indeed, when I compile the code, I get the following error message:
/Users/me/Documents/cs/microcontrollers/ESP32/microphone/microphone.ino: In function 'void i2s_install()':
/Users/me/Documents/cs/microcontrollers/ESP32/microphone/microphone.ino:33:47: error: 'I2S_COMM_FORMAT_STAND_I2S' was not declared in this scope
     .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_I2S),
                                               ^
Used platform Version Path
esp32:esp32   1.0.6   /Users/me/Library/Arduino15/packages/esp32/hardware/esp32/1.0.6

Error during build: exit status 1

Here is the code:
/*
  ESP32 I2S Microphone Sample
  esp32-i2s-mic-sample.ino
  Sample sound from I2S microphone, display on Serial Plotter
  Requires INMP441 I2S microphone

  DroneBot Workshop 2022
  https://dronebotworkshop.com
*/

// Include I2S driver
#include <driver/i2s.h>

// Connections to INMP441 I2S microphone
#define I2S_WS 25
#define I2S_SD 33
#define I2S_SCK 32

// Use I2S Processor 0
#define I2S_PORT I2S_NUM_0

// Define input buffer length
#define bufferLen 64
int16_t sBuffer[bufferLen];

void i2s_install() {
  // Set up I2S Processor configuration
  const i2s_config_t i2s_config = {
    .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
    .sample_rate = 44100,
    .bits_per_sample = i2s_bits_per_sample_t(16),
    .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
    .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_I2S),
    .intr_alloc_flags = 0,
    .dma_buf_count = 8,
    .dma_buf_len = bufferLen,
    .use_apll = false
  };

  i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
}

void i2s_setpin() {
  // Set I2S pin configuration
  const i2s_pin_config_t pin_config = {
    .bck_io_num = I2S_SCK,
    .ws_io_num = I2S_WS,
    .data_out_num = -1,
    .data_in_num = I2S_SD
  };

  i2s_set_pin(I2S_PORT, &pin_config);
}

void setup() {

  // Set up Serial Monitor
  Serial.begin(115200);
  Serial.println(" ");

  delay(1000);

  // Set up I2S
  i2s_install();
  i2s_setpin();
  i2s_start(I2S_PORT);

  delay(500);
}

void loop() {

  // False print statements to "lock range" on serial plotter display
  // Change rangelimit value to adjust "sensitivity"
  int rangelimit = 3000;
  Serial.print(rangelimit * -1);
  Serial.print(" ");
  Serial.print(rangelimit);
  Serial.print(" ");

  // Get I2S data and place in data buffer
  size_t bytesIn = 0;
  esp_err_t result = i2s_read(I2S_PORT, &sBuffer, bufferLen, &bytesIn, portMAX_DELAY);

  if (result == ESP_OK)
  {
    // Read I2S data buffer
    int16_t samples_read = bytesIn / 8;
    if (samples_read > 0) {
      float mean = 0;
      for (int16_t i = 0; i < samples_read; ++i) {
        mean += (sBuffer[i]);
      }

      // Average the data reading
      mean /= samples_read;

      // Print to serial plotter
      Serial.println(mean);
    }
  }
}

I also tried to install the I2S library with:
arduino-cli lib install I2S

but got the following error message:
Error installing I2S: Library 'I2S' not found

How can I solve the problem?
EDIT 1
After the comments I tried to Upgrade the ESP32 package. For this I went to Tools -> Boards -> Board Manager, typed ESP32 and got the following window:

It seems to me that I cannot upgrade beyond version 1.0.6 (under Arduino IDE 1.8.19)
What am I doing wrong?
EDIT 2
Ok I followed the installation instruction on the espressif website and it worked
https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html

It is not that the library has been downgraded, the message shows that you had very old version of ESP32-Arduino package installed (1.0.6), the current version is 2.0.8.. Goto Tools -> Boards -> Board Manager to upgrade your ESP32 package. You don't need to manually install driver/i2s.h as it is part of the esp-idf as the foundation of Arduino ESP32 Core.

Many thanks for your comment @hcheung. I tried to Upgrade the ESP32 package. For this I went to Tools -> Boards -> Board Manager, typed ESP32 and got the window displayed in the edited question at the end. It seems to me that I cannot upgrade beyond version 1.0.6 (under Arduino IDE 1.8.19). What am I doing wrong?

Ok I followed the installation instruction on the espressif website and it worked https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html


text:
4x3 keypad not providing any output and the output it does provide is incorrect
I am trying to figure out how to use a 4x3 keypad and just want to receive the key numbers I select on the serial monitor. The problem I am getting is that some of the keys I type don't give me any output and then the keys that do provide output do not match their corresponding number. For example key 1 does not provide any output, whereas keys 3 and 4 give an output of 4 and 9 respectively. I have attached pictures of how the keypad is connected
The code that I am using is below:
#include <Keypad.h>

// Constants for row and column sizes
const byte ROWS = 4;
const byte COLS = 3;

// Array to represent keys on keypad
char hexaKeys[ROWS][COLS] = {
  {'1', '2', '3'},
  {'4', '5', '6'},
  {'7', '8', '9'},
  {'*', '0', '#'}
};

// Connections to Arduino
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3};

// Create keypad object
Keypad customKeypad = Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);

void setup() {
  // Setup serial monitor
  Serial.begin(9600);
}

void loop() {
  // Get key value if pressed
  char customKey = customKeypad.getKey();

  if (customKey) {
    // Print key value to serial monitor
    Serial.println(customKey);}
}

I just need help identifying where I am going wrong and how I can fix the problem I am having. Thanks.

Your pictures are useless to me, post a real schematic as to how you have it wired. I know first hand the keyboards will work if connected correctly to a good UNO. Be sure to show the keyboard in the schematic and properly label rows and columns.

Are those pins soldered onto the keypad? The connection looks a bit dodgy from the photo.

Hi Gil, I have included a schematic, however, I could only find a 4x4 keypad so just ignore the connection to pin 2. Hi Nick, yes they are soldered onto the keypad.

I determined where I was going wrong. The keypad has a different wiring compared to the traditional way of doing it. I found this this article helpful. The changes made to the code are as follows:
byte rowPins[ROWS] = {8, 3, 4, 6};
byte colPins[COLS] = {7, 9, 5};

As can be seen, the rows and columns pins need to be changed.


text:
Ramping servo motor taking longer than calculated
I'm learning how to code a "BOE Shield bot" with a partner at my university (first year). To clarify for those that do not know: a BOE Shield bot is a small robot equipped with 2 servo motors, a battery pack and an Arduino Uno. If you google the name you'll find plenty of pictures.
We were tasked to code a program that would make the robot accelerate the continuous rotational servo motors according to a given velocity-time graph in RPMs and seconds. We wrote the code, followed a pretty logical method, and passed the assignment. However one thing, and I spent days on trying to fix it, is still confusing me. The code is ahead, I've tried to make it as readible as possible. The RPM to PWM conversion for the motors is:  PWM = 2 \times RPM + 1500
#include <Servo.h>

class motor {
public:
  double Speed = 0;  //The actual speed of the servo in RPM
public:
  Servo servo;

  //returns true if the desired speed "newSpeed" is reached, otherwise increments the current speed and returns false.
  //increment is the calculated speed increase based on the differance in time (interval) and the acceleration which is constant.
  bool accel(double increment, double newSpeed) {
    if (abs(Speed - newSpeed) < 0.1) {
      return true;
    }

    Speed += increment;
    return false;
  }

  void writeMS(double value) {
    servo.writeMicroseconds(value);
  }
};

motor servoLeft = motor();
motor servoRight = motor();

void setup() {
  Serial.begin(9600);
  servoLeft.servo.attach(11);   //vänster -2 * speedLeft + 1500
  servoRight.servo.attach(10);  //höger 2 * speedLeft + 1500
}

//This nested array contains instructions for both servo motors: the desired speed, how long it should take to accelerate to it and how long
//the instruction duration is. The first instruction starts from the second row. The first row is skipped and only used for calculations.
//The columns are in the following order: {instruction length in ms, speed of the left motor in RPM, speed of right motor in RPM, acceleration time}.
double instructions[7][4] = {
  { 0, 0, 0, 0 },
  { 3000, 25, 25, 500 },
  { 2550, 50, 10, 500 },
  { 3000, 25, 25, 500 },
  { 2850, 10, 50, 500 },
  { 3000, 25, 25, 500 },
  { 3000, 15, -15, 500 },
};

//time stuff
unsigned long currentMillis;
unsigned long previousMillis = 0;
unsigned long lastInstructionMillis = 0;
const double interval = 20;

//i is the index for the instructions.
int i = 0;
bool updateL = false;
bool updateR = false;

//the speed increments for each servo. Calculated in the loop.
double incrementL;
double incrementR;

void loop() {
  //This is to help keep track of the time so we can calculate the increments. It essentially means the speeds are only updated ever 20ms.
  currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    //if the desired speed is reached, stop updating. This is just to optimize code.
    if (updateL)
      updateL = !servoLeft.accel(incrementL, instructions[i][1]);

    if (updateR)
      updateR = !servoRight.accel(incrementR, instructions[i][2]);
  }

  //this runs only once after each instruction.
  if (currentMillis - lastInstructionMillis >= instructions[i][0]) {
    lastInstructionMillis += instructions[i][0];
    i++;

    //exit program after all instructions have been completed.
    if (i == 7)
      exit(0);

    //the increments are calculated like such: increment = acceleration * interval
    //where constant acceleration = (newSpeed - oldSpeed) / accelerationTime
    incrementL = (instructions[i][1] - instructions[i - 1][1]) * interval / instructions[i][3];
    incrementR = (instructions[i][2] - instructions[i - 1][2]) * interval / instructions[i][3];

    updateL = true;
    updateR = true;
  }

  Serial.println((String)servoLeft.Speed + " " + (String)servoRight.Speed + " " + (String)currentMillis + " " + (String)i);

  //the actual ms signlas sent to the servos.
  servoLeft.writeMS(2 * servoLeft.Speed + 1500);
  servoRight.writeMS(-2 * servoRight.Speed + 1500);
}

For some reason the acceleration is taking longer than specified in the instructions. For example, the first instruction specifies that both servos will accelerate from 0 to 25 RPM within 500ms. But printing out the speeds and time to the serial monitor shows that it actually takes around 860ms. That is if interval is set to 20. If it's set to 50, it takes 560ms.
Suspected causes were:

Void loop taking longer than the interval

Not the case as measuring it with micros() proved it never took longer than 0.26ms; this was the done with complete program as well.

Rounding errors

Not the case as switching pretty much all the number types to double still didn't fix anything. And double is more than enough precise for this program.

millis() not being accurate enough

I don't believe this is the case. I researched how accurate it actually is, and while it's nowhere near perfect, it should be accurate enough for the program. I tried using micros() instead and that lead to the same result, I do not know if that means something.
Other than that I have no idea what the cause could be. The code itself runs fine, and the robot actually seems to be following the instructions perfectly with no errors. It's just that the speeds and accelerations aren't accurate for some reason.

Have you seen this? https://forum.arduino.cc/t/use-of-exit-0/210352

Are you sure you are properly driving the motors and that they are not slipping?

From Arduino reference on double: "On the Uno and other ATMEGA based boards, this occupies 4 bytes. That is, the double implementation is exactly the same as the float, with no gain in precision."

When you call the accel() method of your class, you provide first the second and third element of the array describing the instruction. These are the target speeds according to your comment. Then as second parameter you are providing incrementL or incrementR. So first target speed, then increment. But the function definition has this the other way round: First the increment, then the new speed. Please try switching the parameters at either the function definition or the function calls. Does it work correctly then?

@VE7JRO I do not think that is the issue. While I am aware how "taboo" exit is, it is only used at the end of the program. It has no effect on anything else.

@Gil well see, the values are not actually dependent on the motors. In other words when I run the program with the servos turned off, it still works. The speed variable within the motor class doesn't read the actual speed of the servos. It just contains the calculated value that we then use to write to the servos. So this issue is not at all caused by the servos.

@chrisl Isn't that precise enough for double? I printed the increments to the serial monitor and they were correct so I do not think that's the problem. The speeds are increasing correctly the only problem is it's taking longer than planned.
As for your second comment, sorry that's just a typing mistake. I will edit the question so it's correct. I rewrote bits of the code and cleaned it up for the question so it would be more readable. I guess I mistakenly switched the values. That would still not have been the issue because the robot wouldn't have worked at all.

Yes, float precision should be enough. Are you sure about the duration of loop()? Currently you are pretty much spamming the Serial interface. At only 9600 baud that will take some time (as priting waits until enough space is free in the buffer)

There are two things going on here.
You are printing too much to the serial port. After the first second
(between 1000 and 9999 ms), each line you print is 20 bytes, including
the CRLF terminator. At 9600 b/s, each bytes takes 1.04 ms (1 start bit,
8 data bites and 1 stop bit). This is about 20.8 ms for the whole line,
which is slightly longer than interval. You should either print less
often (say, every other loop iteration) or faster. Just moving to the
next standard speed (19200 b/s) will be enough to ensure you do not miss
any interval. You can go faster though.
The second issue is the way you keep track of previousMillis:
if (currentMillis - previousMillis >= interval) {
  previousMillis = currentMillis;
  // ...
}

This is prone to accumulating errors. The test will most likely not
happen exactly at previousMillis + interval, mostly because of the
serial port. You are a little bit late and, by updating previousMillis
this way, these errors are cumulative. You can avoid this by updating
previousMillis as:
previousMillis += interval;

You will still have timing errors, but these will manifest themselves in
the form of jitter, not as a systematic timing drift.
Interestingly, you are updating lastInstructionMillis the right way!

Edit: Here are some extra comments about your question and your
sketch, not necessarily related to the problem you are seeing.
You wrote:

measuring [loop()] with micros() proved it never took longer than
0.26ms.

It seems you measured incorrectly. Maybe you measured a version of the
program that was not printing so much to the serial port. Or maybe you
looked only at the first iterations of the loop, where
Serial.println() is fast because the output buffer hasn't filled yet.
The following code is fragile:

bool accel(double increment, double newSpeed) {
  if (abs(Speed - newSpeed) < 0.1) {
    return true;
  }
  // ...
}

The value 0.1 is arbitrary, and the “right choice” is dependent on the
program timing. I suggest something more robust, like:
bool accel(double increment, double newSpeed) {
  if (increment > 0) {
    Speed = min(Speed + increment, newSpeed);
  } else {
    Speed = max(Speed + increment, newSpeed);
  }
  return Speed == newSpeed;
}

Note that, although it is generally recommended to not test floating
point numbers for exact equality, in this case it is safe, because
min() and max() return exactly one of their arguments.
The optimization consisting of calling motor::accel() only during the
acceleration phase is futile: this methods takes an very tiny fraction
of the loop() time. In the same vein, there would be no harm in
calling Servo::writeMicroseconds() on every loop iteration, even if
some of the calls turn out to be useless.
The code would be more readable if instructions was an array of
struct rather than an array of arrays: this way the fields of each
instruction could have evocative names rather than numeric indices.
You are using too much floating point here. Most of the data fields,
including all the contents of instructions, could be integers of
suitable length.

I do not currently have access to the robot, it's with my partner. But I'm very excited to try out this solution. I think you may have found the problem. @chrisl already hinted toward the serial interface spamming with the short speed. All your other suggestions are appreciated and insightful as well. I will try to get my hands on the robot as quickly as I can. In the meantime I will accept your answer as I'm pretty sure you solved it. If not, I will get back to you. It's the end of of the semester so I might not be able to access the robot and I don't want the question left unanswered.


text:
Detecting an approximate angle/location of a light source using phototransistors
Note: [I am approximately two weeks into learning Arduino and hence have little experience with utilizing Phototransistors.]
My plan revolves around placing four identical Phototransisors which are spread approximately 10cm apart on a breadboard in a V configuration. Each Phototransistor is connected to one of the "analog In" pins respectively (I am using the Arduino Uno), with the long leg attached to 5V while the short leg is connected to ground via a 220-ohm resistor. In the center of this setup, I plan to place a servo that will face the direction of the light beam emitted from a flashlight.
(I want this project to be allocated in a dark room with any external lighting calibrated),The idea is to identify the phototransistor which has the highest analog value (closest to the light source). With this information, I want to be able to compute an approximate angle of the light source to then write it on my servo.
You can find the attached datasheets below (All the components are from the Arduino starter kit :) ).
[Datasheet for the Phototransistor]
[Datasheet for the Servo motor]
[Datasheet for the 220 ohm Resistor]
Here is what I have so far for the code:
#include <Servo.h>
Servo myServo;
const int transistorPin1 = A0;
const int transistorPin2 = A1;
const int transistorPin3 = A2;
const int transistorPin4 = A3;
void setup() {
  myServo.attach (10);
  Serial.begin (9600);
}
void loop() {
 int reading1 = analogRead (transistorPin1);
 int reading2 = analogRead (transistorPin2);
 int reading3 = analogRead (transistorPin3);
 int reading4 = analogRead (transistorPin4);
 int reading [] = {reading1, reading2, reading3, reading4}; //This is an array for the values:
 int maxReading = reading [0], maxSensor = 1; // I am setting the maximum reading and the Phototransistor that corresponds to it:
   for (int i = 1; i <= 3; i++){ //Setting this for the other three phototransistors:
     if (reading[i] > maxReading){
     maxReading = reading[i];
     maxSensor = i + 1;
     }
   }
}

So my question is: What is the most efficient way to compute the angle of the lighsource? And is my method even relevant for this application?
Thank you for taking you time to read this! Your support will be very much appreciated!
Edit 1:
Explanation of my hardware setup:
This project is allocated on two connected breadboards which means that there are no moving parts. The only moving component is the one single servo that is fixed in position.
The phototransistors, (as mentioned above), are placed in a V configuration which too are stationary. The servo is allocated behind the phototransistors and can only rotate 180 degrees. (You can see the attached illustrations below, I apologize in advance for any technical errors or my horrible drawings.)

As you can visualize on the first image, I do not plan on a complete 360 degree rotation which probably complicates the issue further. Any suggestions on how I can code this would be greatly appreciated! Once again thank you for your time.

See this  https://www.instructables.com/Arduino-Sunflower-an-Electronic-Sundancer/ or google for Arduino Sunflower or solar tracker for more examples. I believe the most effective ones have the light sensors mounted on the panel which the servos moves. The servos continues to position the panel until all photosensors deliver exactly the same measurement. Can you say something about the physical construction of your project.

Thank you for your reply, the link you sent me was quite helpful however I have noticed that the project mentioned utilizes two servo motors for a full 360 degrees rotation (covering all three x, y, and z coordinates). I, unfortunately, have to resort to utilizing one servo motor which only provides me with 180 degrees. Another issue I have noticed is that the light sensors are not stationary and are rotated by a robot "chassis". Due to my project being entirely based on breadboards the method used will not work for my application. I hope my edit will clarify the idea a little bit better.

Your efforts are well thought out, but make use of others before you, e.g., https://arduino.stackexchange.com/questions/36597/detecting-the-light-source-location-using-multiple-photoresistors (yes, I know they are LDRs, but the task is similar). Also, make some effort to calibrate your phototransistors, even if it is just to check the levels when a light source is 6 inches away - they need to be as identical as possible and fixed 220s may not be good enough. Finally, remember you only have 1 ADC and are switching channels, check that you are obeying speed limits, so to speak. // end two cents.

Just to get started, I'd probably look at the photo transistor which gives the strongest light value and use that as the current starting point (0,60,120 or 180 degrees assuming that is how the transistors have been distributed around the servo) then look at the adjacent transistors to work out how much, and in which direction, to bias the result away from the starting point. The result is sent to the servo. Repeat every X ms.  Your hardware configuration is unusual in that all the sensors are static. Most tracking type projects move the sensors towards the light source.

This really helped! It took me a while but I managed to get it to kind of work. The servo is jittery but I am satisfied. I will attach a youtube URL later today to show my results. Thank you guys for replying!

In principle, you only need two phototransistors, a left and a right one. The quotient of the values from the ad-convertor (Vleft/Vright) will tell you where to find the light source. If the quotient > 1 then the light source is at the left side, if the quotient < 1 then the light source is at the right side. Most likely there is no lineair relationship between the quotient and the angular position of the light source. This relationship depends on the housing and the positioning of the diodes in their housings. One possibility is to do a calibration beforehand and use a lookup table during operation. The calibration could be done by placing the breadboard with photodiodes on a rotating platform with the light source in front and then record Vleft and Vright at various angles (in 1 degree steps?) of the platform in relation to the light source.
If two photoresistors don't give you the required precision and/or range, you can use more photoresistors and use the pair which is best 'looking' in the direction of the light source.

The value could also be subtracted, and the sign gives the direction. In any case both light sensors should have the same sensitivity.


text:
GCRduino shows up briefly in the IDE and then disappears
I have two UNO boards from a few years ago. They look the same as far as chip placement goes.
I can plug both in and get flashing lights on them, and when I hit the reset (2x the on-off) button, they both make the same LED "noises".  Since the LEDs on the non-detected board flash the same start-up sequence as a board that is detected, I assume both boards are working.
One of them has "UNO" printed on the circuit board and the other has "GCRduino Rev 1.0" printed on the circuit board. (edited according the comments for clarification)
I'm using Linux Mint 21 and Arduino IDE 2.0.3.
On hardinfo (the linux program), both of them are listed in Devices->USB Devices as "QinHeng Electronics CH340 serial converter."
The one that has UNO printed on the board is detected and I can load software onto it. The one that say GCRduino is not detected by the IDE and no new entry shows up in /dev.
The GCRduino is detected for a split second and then disappears again.  check this video: http://100wires.com/arduino.mp4

Welcome to SE/Arduino! Please take the [tour] to learn how these SE sites work. -- Are you sure that the GCRduino has a compatible boot loader? Please [edit] your question and tell us what your research on the device has revealed so far.

Arduino clones that use the CH34x chips generally do not show list the IDE or hardware lists as being a particular board, because the necessary information to positively identify them is not provided by the CH34x chip.
So, I'm skeptical that "one says UNO is detected" and "both of them are listed as...CH340...". are both true. Make sure the information in your question is correct.

@timemage Presumably "says UNO" means that the word "UNO" is printed somewhere on its circuit board. ;-) Therefore I don't think the OP wanted to say that Linux reports "UNO". Technical terms are difficult for casual users.

Yeah, I'm stumbling on the grammar I guess. Anyway, I take your point.

i've updated the post for accuracy.

did you try it on a different computer?

No.  same computer.  see my answer.

so yes I see you answer. and you didn't try it on a different computer before asking a question here. and the problem is with the computer not with the arduino

yes, that's why i mentioned the LED noises, although i didn't specify that the noises seem to indicate that it's working.  i've updated my question again for clarity.

I found the problem with dmesg.  When I insert the card and it shows up very briefly, it gets kicked by another device:
[  167.032321] input: BRLTTY 6.4 Linux Screen Driver Keyboard as /devices/virtual/input/input25
[  172.660038] usb 3-3: new full-speed USB device number 9 using xhci_hcd
[  172.809032] usb 3-3: New USB device found, idVendor=1a86, idProduct=7523, bcdDevice= 2.62
[  172.809038] usb 3-3: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[  172.809041] usb 3-3: Product: USB2.0-Serial
[  172.810938] ch341 3-3:1.0: ch341-uart converter detected
[  172.811372] usb 3-3: ch341-uart converter now attached to ttyUSB0
[  173.349731] input: BRLTTY 6.4 Linux Screen Driver Keyboard as /devices/virtual/input/input26
[  173.655257] usb 3-3: usbfs: interface 0 claimed by ch341 while 'brltty' sets config #1
[  173.656203] ch341-uart ttyUSB0: ch341-uart converter now disconnected from ttyUSB0
[  173.656275] ch341 3-3:1.0: device disconnected

I can see the device on lsusb:
Bus 003 Device 008: ID 1a86:7523 QinHeng Electronics CH340 serial converter
That same device serial number is listed in
grep 1a86 /usr/lib/udev/rules.d/85-brltty.rules
ENV{PRODUCT}=="1a86/7523/*", ENV{BRLTTY_BRAILLE_DRIVER}="bm", GOTO="brltty_usb_run"

So when it connects, it gets kicked off by it being detected as another device.
So I just comment out that line in /usr/lib/udev/rules.d/85-brltty.rules, restart, and the board can now be detected.

Seems to be the same as this issue.

It is, thanks.  I've updated my question with more keywords/descriptions so maybe other's can more easily find the problem.


text:
How to send multiple bytes with Wire without copying
When I need to send multiple bytes via Wire, for example a long int, I cast it to a byte array and specify a length
long int i;
Wire.write((byte*)&i, 4);

But if I want to send bytes from more than 1 variable I need to create a buffer
byte i;
byte j;
byte message[2] = {i, j};
Wire.write(message, 2);

If I want to send them without copying the data I can put them in a struct
struct message {
  byte i;
  byte j;
};
Wire.write((byte*)&message, 2);

But this would require me to refactor existing code.
Is there any c voodoo that I can perform to send bytes of different places of my code over Wire without copying them in a buffer and without refactoring the code?

No, this function overwrite of Wire.write() is meant for buffers, meaning connected spaces in memory, which can be covered by simply incrementing the buffer. That is not the case for distinct variables.
But that begs the question, why you want to do that in one call to Wire.write() in the first place. This function does not do any communication on the I2C lines, it just writes to the libraries internal buffer. The data gets actually send in Wire.endTransmission() or in the onRequest interrupts in the background (depending on where you have those write statements). Thus you already have a buffer and don't need another one. Just call Wire.write() multiple times, once for each variable. That will build up the data sequentially inside the internal buffer.

Well my device is operating in slave mode and my Wire.write() gets called (perhaps not directly but down the line) from an onRequest handler. In my experiments I found that once I call Wire.write() I can not call it again or I get rubbish. Is it possible to use multiple writes in my case?

I got to the bottom of it! But it was too long for a comment so I added an answer. Thanks again!

No, you cannot.
C does not guarantee any allocation properties of variables. Even if you write one variable definition right after another, both variables can have addresses assigned that have other memory in between.
So, if you want a "packet" sent via Wire that contains values of multiple variables, you need to fill a buffer with these values.
Even though C maintains the order of members of a structure, please be aware that depending on the target's architecture there can be gaps between the members for alignment. However, some compilers have language extensions to tackle this issue.

// Written by Nick Gammon
// May 2012

template <typename T> unsigned int I2C_writeAnything (const T& value)
  {
  Wire.write((byte *) &value, sizeof (value));
  return sizeof (value);
  }  // end of I2C_writeAnything

template <typename T> unsigned int I2C_readAnything(T& value)
  {
    byte * p = (byte*) &value;
    unsigned int i;
    for (i = 0; i < sizeof value; i++)
          *p++ = Wire.read();
    return i;
  }  // end of I2C_readAnything

Then in the body of your code you can:
I2C_writeAnything(message);

Similarly your other end can I2C_readAnything.
There is a small amount of refactoring required, changing the function call.

I think there may be issues with struct padding or endianness mismatch in this code if you are unlucky, but maybe it works most of the time.

As @chrisl said, there is an internal buffer so the best I can do is just use multiple Wire.write calls, but in my case that wasn't working. I got only the last written value or rubbish data.
I dug through the source of the Wire library and found that the version in github (as of this writing) makes it possible to use multiple writes by appending to the buffer:
// set length and copy data into tx buffer
for(i = 0; i < length; ++i){
  twi_txBuffer[twi_txBufferLength+i] = data[i];
}
twi_txBufferLength += length;

But the one I have installed locally looks like this:
// set length and copy data into tx buffer
twi_txBufferLength = length;
for(i = 0; i < length; ++i){
  twi_txBuffer[i] = data[i];
}

So that explains a lot.
In case someone else also has this problem, you just need to update.
I was even too lazy to update, so I just replaced the function. Probably not the best decision, but it works!
Thanks!

fixed 6 years ago

@Juraj yeah I got curious and checked it too. Probably someone else was also as lazy as me and didn't update! I can't remember where I got my arduino sdk from but it was about 2 years ago, so definitely plenty of time has been had for updates, lol.


text:
Can I power Lilygo TTGo T-display from 5v and still use USB for communication?
I have a project which needs a 7-9V power source.  I use a battery, and plan to use a small regulator to supply 5V to a Lilygo TTGO T-Display V1.1 (1.14 inch display) via the 5V and GND pins.
I need to connect the Lilygo to USB from time-to-time to upload data.  Will there be any conflict between the USB power and the 5V supply ?
I have peered for a long time at the schematic, and I see that there are MOSFETs doing some kind of protection, but I do not understand it well enough to be sure.
Schematic: here

Q5 appears to disconnect the battery (VBAT) from +5V when the USB is
connected.
Q4 also seems to disconnect the battery (BAT) from +5V when the USB
is connected.  What is the difference between VBAT and BAT ?
VBUS (the USB power) is connected to +5V via a Zener diode.  This
appears to allow the USB to supply 5V, but prevent current flowing
back to the PC.  I think there could be an issue with high current
through the Zener if my 5V regulator gave a voltage that was lower
than the USB.

is that the official schematic diagram? ... it is sloppily drawn

What do you mean "via the 5V and GND pins"? Do you mean directly to the traces or do you mean by hooking up the regulated battery voltage to the battery input pins? Do note that the board expects a 3.7-4.2V input for the battery, 5V is too much; take a look at the charger datasheet (TP4054). Also, next time use the Electrical Engineering SE as it's more relevant to these kinds of questions, rather than the Arduino one.

a zener between usb and 5v doesn't makes sense, sure it's not a Schottky? How do you even upload data over the USB connector anyway? Why not just use wifi so you don't risk your device or computer?

@dandavis it is a Schottky, yeah, even after reading the datasheet I came back to the post to write "Zener" in my answer hahaha. The USB is connected to the USB-UART chip, which in turn is connected to the ESP32's UART #0. Using WiFi would be fine, but you still have to power it and looking at the company's website and the schematic, they did not design the board with the intention of it being powered by anything other than the USB or the battery.

I just looked at datasheet for the charger, TP4054.  I see that Vin is given as 4.5 - 6.5V (with absolute max rating of -0.3 - 10V).  It is connected to VBUS in the schematic,  which I believe is nominally 5V.  BAT is rated as -0.3 - 7V, so I am thinking applying 5V to the battery input should be safe. Maybe I am looking at the wrong datasheet.

@elpidiovaldez5 huh, okay, for some reason I thought it said Vcc-0.6 for the input battery; either I was looking at a different part yesterday or I made it up :) Glancing at it again, yeah, applying the 5V to the battery input should be a viable way to do what you're looking to do. Just make sure that the current that the regulator provides isn't over the specs and if you do connect the USB while powering it from the 5V regulator, just double-check that it can potentially sink the current from the charger. It shouldn't initiate the charging sequence because Vbat > Vfloat, but just in case :)

What are you trying to achieve? For how long is the board supposed to function? The simplest solution in this case is to simply get a 4.2V battery for the LilyGO board itself, most likely not just in terms of effort, but economically.
From your edits, I (now) assume you want to use the 5V pin on the board? I don't think that'll work the way you'd want it to, as it doesn't seem that it was intended for that (if it was, the VIN pin would've been brought out).

Q5 appears to disconnect the battery (VBAT) from +5V when the USB is connected.

Yeah, that makes sense to me as well.

Q4 also seems to disconnect the battery (BAT) from +5V when the USB is connected. What is the difference between VBAT and BAT ?

Yes, looking at the datasheet for the battery charger and the schematic for the LilyGO board, VBAT is the batteries voltage, while the BAT terminal is the one coming out of the charger and the one that usually supplies the current to both charge the battery and to possibly drive the system load.

VBUS (the USB power) is connected to +5V via a Zener diode. This appears to allow the USB to supply 5V, but prevent current flowing back to the PC. I think there could be an issue with high current through the Zener if my 5V regulator gave a voltage that was lower than the USB.

Yeah, it prevents the current going back into the USB port if you have the battery connected. You need a pretty substantial voltage to overcome that Schottky* barrier.
One issue you'll probably encounter is that if you connect a 5V source to that pin, the system will think it's powered on by a battery and you can damage the BAT terminal. If you have more than 1 of those boards and you're willing to experiment, you could try cutting the trace to BAT terminal altogether and connecting the 5V source and seeing if that works.
Another issue is that for safety reasons, it'd be prudent to switch that source off when you're connecting the USB; you'd also want to protect that 5V source from being damaged by the VUSB once it's on. There are probably ways you could keep the 5V on if you desolder the USBC connector and try to manually attach a probe to the datalines and ground the two together, but dealing with USBC is not easy and you're rapidly venturing into territory where it's just easier to get a different board and the screen separately or just use a LiPo battery to power the board in the first place (you could probably find a way to use multiple LiPo packs if you need your application to last longer as well).
Note: I didn't spend too much time looking at the schematic and it is a bit confusing, so a possible good exercise would be to simulate those two circuits in a SPICE program. And again, these types of questions are covered more-so by the EE SE. If you'd have posted it there, I'm sure you'd get more (and most likely, better) answers.

Thanks for putting in so much effort.  My project needs 9V to power some other equipment, so I want to power the ESP32 from the same battery - hence the idea of using a 5V regulator.  Sorry about mix-up over Zener/Schottky - I checked Google and a lot of sources use the same symbol for Zener.  The circuit diagram is not 'official'.  I have not been able to find any official documentation for this board. I will post another question on the other site you mentioned.

@elpidiovaldez5 that's okay, that's why looking at the datasheets helps - that one is a Schottky indeed!