text:
Bluetooth module(HC 05) issues
I am trying to make a Bluetooth controlled 4WD robot. i was following a tutorial i found online (https://howtomechatronics.com/tutorials/arduino/arduino-robot-car-wireless-control-using-hc-05-bluetooth-nrf24l01-and-hc-12-transceiver-modules/). After successfully connecting my 2 HC 05 Bluetooth module i used the script from the tutorial and modified it slightly so it would work for my set up.
The code for the robot:
//Code for Slave
#define enA 9
#define in1 8
#define in2 7
#define enB 10
#define in3 6
#define in4 5
int xAxis, yAxis;
unsigned int  x = 0;
unsigned int  y = 0;
int motorSpeedA = 0;
int motorSpeedB = 0;
void setup() {
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
  Serial.begin(9600); // Default communication rate of the Bluetooth module
}
void loop() {
  // Default value - no movement when the Joystick stays in the center
  x = 510 / 4;
  y = 510 / 4;
  // Read the incoming data from the Joystick, or the master Bluetooth device
  while (Serial.available() >= 2) {
    x = Serial.read();
    Serial.print("X: ");
    Serial.println(x);
    delay(10);
    y = Serial.read();
    Serial.print("Y: ");
    Serial.println(y);
  }
  delay(10);
  // Convert back the 0 - 255 range to 0 - 1023, suitable for motor control code below
  xAxis = x*4;
  yAxis = y*4;
  // Y-axis used for forward and backward control
  if (yAxis < 470) {
    backMov;
    // Convert the declining Y-axis readings for going backward from 470 to 0 into 0 to 255 value for the PWM signal for increasing the motor speed
    motorSpeedA = map(yAxis, 470, 0, 0, 255);
    motorSpeedB = map(yAxis, 470, 0, 0, 255);
  }
  else if (yAxis > 550) {
    fowardMov;
    // Convert the increasing Y-axis readings for going forward from 550 to 1023 into 0 to 255 value for the PWM signal for increasing the motor speed
    motorSpeedA = map(yAxis, 550, 1023, 0, 255);
    motorSpeedB = map(yAxis, 550, 1023, 0, 255);
  }
  // If joystick stays in middle the motors are not moving
  else {
    motorSpeedA = 0;
    motorSpeedB = 0;
  }
  // X-axis used for left and right control
  if (xAxis < 470) {
    // Convert the declining X-axis readings from 470 to 0 into increasing 0 to 255 value
    int xMapped = map(xAxis, 470, 0, 0, 255);
    // Move to left - decrease left motor speed, increase right motor speed
    motorSpeedA = motorSpeedA + xMapped;
    motorSpeedB = motorSpeedB - xMapped;
    // Confine the range from 0 to 255
    if (motorSpeedA > 255) {
      motorSpeedA = 255;
    }
    if (motorSpeedB < 0) {
      motorSpeedB = 0;
    }
  }
  if (xAxis > 550) {
    // Convert the increasing X-axis readings from 550 to 1023 into 0 to 255 value
    int xMapped = map(xAxis, 550, 1023, 0, 255);
    // Move right - decrease right motor speed, increase left motor speed
    motorSpeedA = motorSpeedA - xMapped;
    motorSpeedB = motorSpeedB + xMapped;
    // Confine the range from 0 to 255
    if (motorSpeedA < 0) {
      motorSpeedA = 0;
    }
    if (motorSpeedB > 255) {
      motorSpeedB = 255;
    }
  }
  // Prevent buzzing at low speeds (Adjust according to your motors. My motors couldn't start moving if PWM value was below value of 70)
  if (motorSpeedA < 70) {
    motorSpeedA = 0;
  }
  if (motorSpeedB < 70) {
    motorSpeedB = 0;
  }
  analogWrite(enA, motorSpeedA); // Send PWM signal to motor A
  analogWrite(enB, motorSpeedB); // Send PWM signal to motor B
}
void fowardMov(){
  digitalWrite(in2,HIGH);
  digitalWrite(in4,HIGH);
  digitalWrite(in1, LOW);
  digitalWrite(in3, LOW);
}

void backMov(){
  digitalWrite(in1,HIGH);
  digitalWrite(in3,HIGH);
  digitalWrite(in2, LOW);
  digitalWrite(in4, LOW);
}

The code for the Controller:
#define Xaxis A0
#define Yaxis A1

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

void loop() {
  // put your main code here, to run repeatedly:
 Serial.write(analogRead(Xaxis)/4);
 Serial.write(analogRead(Yaxis)/4);
 delay(20);
}

After uploading the code i tried to move it but it wasn't working so i put print statements to see the value of X and Y. initially it didn't work so i swapped the Bluetooth modules i had and reconnected them. i also changed this line.
 while (Serial.available() >= 2)

To this
 if (Serial.available() > 0)

i started to receive values from the master to the slave but  i noticed the values were the same for x and y so i searched for another tutorial on the internet and found this (https://create.arduino.cc/projecthub/andriy-baranov/arduino-4wd-rc-car-639953?ref=similar&ref_id=18369&offset=3) reading his code i wondered how did the slave work. According to the official Arduino documentation Serial.read() does not take in any arguments but i still tried it and it didn't work. I decided to retry the code from the first tutorial i checked this time it looked like it was working so i tried moving the joystick and the serial monitor printed correct values for both at first then it swaps their values then freezes. How can i stop it from freezing and swapping the values? Also why doesn't the while loop run forever isn't the amount of data in the serial buffer always higher than 2? Thank you.

There is an issue with the way in which the data is sent and received because it assumes the transmission will remain perfectly synchronised for the lifetime of the programme. Consider what would happen if one byte were to be dropped due to a communication error – the x and y data would be swapped for further transmissions.
Original Sender
void loop() {
  // put your main code here, to run repeatedly:
 Serial.write(analogRead(Xaxis)/4);
 Serial.write(analogRead(Yaxis)/4);
 delay(20);
}

Original Receiver
void loop() {
  // Default value - no movement when the Joystick stays in the center
  x = 510 / 4;
  y = 510 / 4;
  // Read the incoming data from the Joystick, or the master Bluetooth device
  while (Serial.available() >= 2) {
    x = Serial.read();
    Serial.print("X: ");
    Serial.println(x);
    delay(10);
    y = Serial.read();
    Serial.print("Y: ");
    Serial.println(y);
  }
  delay(10);
  . . .
}

Therefore, there needs to be a way to synchronise to the first byte of the message. This can be achieved by using message packets where the start and end of the message are delimited with unique characters, e.g. { and }, similar to the JSON format.
As another example, the NMEA GPS standard uses $ and \n to delimit messages, and , to delimit fields. It also has a checksum at the end.
Here is a non-blocking algorithm which builds upon Majenko's readline() example and the Blink Without Delay example to read a packet. ReadPacket() returns true when incoming data has been accumulated into a valid packet. The LED is flashed to indicate that the MCU hasn't frozen.
New Sender
void loop()
{
    Serial.print("{");                  // First character delimiter.
    Serial.print(analogRead(Xaxis));    // Full resolution. No need to divide by 4.
    Serial.print(",");                  // Field delimiter.
    Serial.print(analogRead(Yaxis));    // Full resolution. No need to divide by 4.
    Serial.print("}");                  // Last character delimiter.
    delay(20);
}

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

    //
    // TASK 2: Read and parse data packet.
    //
    static char packet[100];
    const byte NUM_FIELDS = 2;
    unsigned int fields[NUM_FIELDS];
    static unsigned int x = 512;   // Full resolution. No need to divide by 4.
    static unsigned int y = 512;   // Full resolution. No need to divide by 4.
    bool new_x = false;
    bool new_y = false;
    if (ReadPacket(Serial, packet, sizeof(packet)))
    {
        Serial.print(F("Received packet >"));
        Serial.print(packet);
        Serial.println(F("<"));

        // Parse the packet for x and y values at full resolution.
        const char delimiters[] = "{,}";
        char* field;
        int i = 0;
        field = strtok(packet, delimiters);
        while (field != NULL && i < NUM_FIELDS)
        {
            Serial.print("field = ");
            Serial.println(field);
            fields[i] = atoi(field);
            Serial.print("fields[");
            Serial.print(i);
            Serial.print("] = ");
            Serial.println(fields[i]);
            field = strtok(NULL, delimiters);
            i++;
        }
        if (i == NUM_FIELDS)
        {
            if (x != fields[0])
            {
                new_x = true;
                x = fields[0];  // Full resolution. No need to multiply by 4.
                Serial.print("New x = ");
                Serial.println(x);
            }
            if (y != fields[1])
            {
                new_y = true;
                y = fields[1];  // Full resolution. No need to multiply by 4.
                Serial.print("New y = ");
                Serial.println(y);
            }
        }
    }

    Serial.print("x = ");
    Serial.println(x);
    Serial.print("y = ");
    Serial.println(y);

    //
    // TASK 3: Process x and y values.
    //
    if (new_x || new_y)
    {
        Serial.println("Processing new values.");

        . . .
    }
}

bool ReadPacket(Stream& stream, char *const packet, const unsigned int SIZE)
{
    const char FIRST = '{';
    const char LAST = '}';
    static bool read_until_last = false;
    static unsigned int i = 0;
    char ch;

    if (stream.available())
    {
        ch = stream.read();

        if (ch == FIRST)
        {
            Serial.println(F("Received FIRST."));
            i = 0;
            packet[0] = ch;
            read_until_last = true;
            return false;
        }
        if (read_until_last)
        {
            i++;
            if (i > SIZE - 2)
            {
                Serial.println(F("Buffer overrun. Resetting to look for next packet."));
                i = 0;
                read_until_last = false;
                return false;
            }
            if (ch == LAST)
            {
                Serial.println(F("Received LAST."));
                packet[i++] = ch;
                packet[i] = 0;
                read_until_last = false;
                return true;
            }
            else
            {
                Serial.print(F("Received char >"));
                Serial.print(ch);
                Serial.println("<");
                packet[i] = ch;
                return false;
            }
        }
    }
    return false;
}

Your setup is WAY too complex!  Simplify your setup to the point where it only deals with just the piece that is giving you problems; in your case serial port comms between master and slave.  Solve JUST THAT problem, and then move on

I have simplified my setup by removing everything  except the master and slave Bluetooth devices . i made a simple sketch to send data from the master to the slave. it still does the  same thing. it freezes then after a while it prints out all the data sent by the master device. i noticed when i increase the delay for the master to 1 second it works a lot better but won't a delay of 1 second cause a noticeable time lag when controlling the robot? Thank you

Glad to hear you simplified things, and are starting to get some encouraging results.  If increasing the Master's delay to 1sec works a lot better, then you may be on to something.  Try increasing the delay even further (2sec, 10 sec) and see if that allows the master/slave response to look more like 'real time'.  If so, you may find that the master/slave serial rate is too low, and the 1 second delay is required to get all the bytes through the channel

In any case, take your time, go very slowly, write everything down, and ONLY CHANGE ONE THING AT A TIME.  At some point you will look at your results and your notes and say "Of course, why didn't I think of that earlier" ;-).

I did what you said and noticed something. i started the masters delay from 2 secs and started gradually decreasing it by half. At 125 millisecond it was still receiving serial data normally but with a little noticeable lag sometimes. the lag doesn't last up to a second though. I'm going to modify the code for the robot slightly so it doesn't need to send as much data. in the first tutorial the baud rate he uses is 38400 but i use 9600 do you think that could be the solution to my problem? thank you

The old 9600 baud rate is ancient. Try 115200 or 230400

I tried changing the baud rate.but it didn't improve things

If you have a 'freeze' that isn't affected by baud rate, then maybe your code sets up and then dismantles the connection each time through the loop, instead of setting it up once and then keeping it open throughout the life of the program.  There HAS to be a reason, and careful experimentation and result recording WILL reveal it.

Do you think the problem i have is with hardware? because i made my code as easy as possible by sending numbers 1-255 from the master with a for loop and then receiving and printing out the received data in the Serial monitor yet it still freezes. using a baud rate of 23400 i only got what looked like random numbers. i noticed that if remove the delay entirely from the master it doesn't freeze although some data is lost.

in general, hardware is almost never the problem


text:
Deriving the exact relationship between PWM and steering
I am using a L298n driver to make a basic RC car. I realise that PWM is used to control the speed of the motors and that the car would turn when the wheels on one side of the car have a rpm different from the other side. I am taking user input from the x-axis of a joystick.
However, I am not sure how to arrive at an exact relationship between rpm and the angle by which the car turns.
My approach so far :

If the car is turning left, the wheels on the left side are turning in a smaller arc and hence the inner wheels have a lower rpm. The sharper the turn the slower the inner wheels turn.

PWM is used to control the speed of the motors.

Each angle of turning corresponds to circles of different radii. Hence a sharper turn would correspond to a circle with a very small radius.

So I need to map the x-axis values of the analog stick to angles by which I want the car to turn. Once I know the relation between rpm and the angle by which the car turns, I can map the joystick values to PWM values.

This question has already been asked here and the consensus seems to be that some sort of feedback mechanism is required for an exact calibration.
I have two questions :

Where do I learn more about this feedback mechanism?
Purely from a physics perspective, considering an ideal environment, how do I derive a relation between rpm and the steering angle?

Regarding #1, the turn angle won't be just a factor of the inner wheel RPM. Nor will it be a simple ratio of the 2 wheels RPM. The wheel speed (RPM * wheel circumference) is a better measure. The side-to-side distance between the wheels is also important. You want the ratio of inner to outer wheel speeds to match the ratio of desired inner to outer wheel turn circumference. That would give you a smooth turning circle with no wheel slippage. If the ratio of wheel speeds does not match a ratio inner-to-outer wheel turn circumferences, one or both sets of wheels will slip.

Where do I learn more about this feedback mechanism?

It depends on the kind of feedback. You can have absolute or relative feedback. Relative would be, for example, to use an encoder on each wheel to find out how much it has turned. Absolute would be using a compass to know exactly what direction the vehicle is facing at any time.

Purely from a physics perspective, considering an ideal environment, how do I derive a relation between rpm and the steering angle?

If you know how much each wheel has turned then it is really just simple trigonometry. You have two arcs that are the same proportion around the circumference of two circles. The circles must have the same centre point. Well, I say "simple" - that's a relative term. And of course it depends if you are moving like a car (i.e., turning while moving forwards) or like a tank (turning on the spot) as to whether such calculations are particularly meaningful.
But then of course that's only if you actually know the RPM. Which requires feedback.
There is no easy relationship between PWM and the angle turned. This is because PWM does not define the RPM:

PWM defines the current
The current defines the torque
The torque defines the acceleration (and ultimately maximum speed) under different loads and conditions.

Those loads and conditions change depending on lots of factors. With no way to change the angles of the wheels they will need to slip on the surface as you turn. That adds friction and varies depending on both the speed at which you turn, the angle you turn through, and the surface you are driving on at the time. A high friction surface will both increase the power transfer and at the same time require more power to turn. A sharper turn angle will slip more and require more power to overcome the friction.
It's a very complex relationship with far too many variables. Which is why cars have steering mechanism to change the angle of the wheels, and some vehicles have rear-wheel steering as well to change the angle of the rear wheels to reduce slip and friction (such as the Porsche 911 and many large heavy vehicles), and why London cabs use "Ackermann" steering which gives each wheel a different angle while turning to increase the angle the vehicle can turn through so it can turn in the road easier.
So all in all if you want to know what direction you are pointing at any time, although it's harder to interface with and use, and may be a little more expensive, a compass or other absolute rotation sensor is the way to go.
If you want to turn to a specific angle, (or turn through a specific angle, which is just a relative change between two specific angles) then it's a case of "move a bit" then "see what angle I'm at" then "move a bit more" and "see what angle I'm at".
You could either use a simplistic approach where you always move in discrete steps, or use a PID to calculate what would be a good amount to turn to get you closer and closer to the desired angle depending on how far you turned last time.

source: Stack Exchange

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

sort: votes


text:
Understanding NRF24L01 specifications
I was reading this tutorial about the NRF24L01 and came across a few terms which I did not clearly understand.

It uses the 2.4 GHz band

Does this refer to the frequency of the EM waves that the device uses to communicate?

If used in open space and with lower baud rate its range can reach up to 100 meters.

I know baud rate refers to how many "groups of bits" are transmitted per second. I don't quite understand why the range increases for a lower baud rate.

The 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, or each unit can communicate with up to 6 other units at the same time.

Here, does a channel mean a single frequency? How is the range of possible channels decided (why 125) and how is the smallest detectable resolution decided (smallest change in frequency which would cause a change in channel)? So does a single unit work on only one frequency or could the same unit communicate at different frequencies at the same time and so be a part of different networks simultaneously? In effect, I am not able to make sense of this paragraph!

It uses the 2.4 GHz band

Does this refer to the frequency of the EM waves that the device uses to communicate?

Yes. It generates (and receives) radio waves in the region of 2.5GHz.

If used in open space and with lower baud rate its range can reach up to 100 meters.

I know baud rate refers to how many "groups of bits" are transmitted per second. I don't quite understand why the range increases for a lower baud rate.

Think of it like talking to someone. If you're stood right next to them you can speak nice and fast and they can understand you. Your speech comes across nice and clear.
However if you're the other side of a quarry you have to shout really loud, and if you talk too fast they can't understand you. You. Have. To. Shout. Slowly. so that they can understand you.
The environment makes a lot of difference to how your speech propagates. In large areas there's lots of echo and other things.  It's similar with RF communications. There's more noise and things that can interrupt communication. By having lower baud rates you're giving the receiver more time to understand what it's receiving and make sense of the data.

The 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, or each unit can communicate with up to 6 other units at the same time.

Here, does a channel mean a single frequency? How is the range of possible channels decided (why 125) and how is the smallest detectable resolution decided (smallest change in frequency which would cause a change in channel)? So does a single unit work on only one frequency or could the same unit communicate at different frequencies at the same time and so be a part of different networks simultaneously? In effect, I am not able to make sense of this paragraph!

There's a number of different factors at play here. First there is the "Bandwidth" of the channel. This is the maximum amount of data that can be squeezed into a particular carrier frequency with a particular amount of "space" around the signal. You can think of the channel width as the diameter of a pipe. The wider the pipe the more water can be pushed through the pipe per second.
You want to slice the RF allocation up into enough channels to give enough concurrent access to lots of devices, but at the same time you want to have enough bandwidth per channel that you can transfer reasonable amounts of data.
It's all a balancing act.
Nordic decided 125 channels was the optimal balance for their application.
One nRF24L01+ can work at one frequency at a time. That's not to say you can't instruct it to change frequencies at any time, but it can only be listening on the one frequency at once. Just like a normal FM radio - you can only listen to one radio station at a time.
But the nRF24L01+ protocol uses addresses within that one chosen channel, so lots of devices can all be on the same channel to talk together, and each is distinct by its address.
The protocol also includes the concept of "pipes" which are virtual wireless circuits between two physical devices. Once you have configured a pipe with an address any other device can communicate with that pipe. You can configure up to 6 pipes, so up to 6 devices can send to the same target at the same time and each devices data is kept separate and distinct from the others. It's kind of like having 6 serial ports all connected to different devices at once.

Not sure where you get the 100 MHz (min? max?) from. Most users of the band use very different bandwidths: 22 MHz (802.11b), 20 MHz (802.11g), 40 MHz (802.11n), 1 MHz (Bluetooth), 2 MHz (BLE), 2 MHz (802.15.4 / Zigbee / Thread)... 100 MHz is the total size of the 2.4 GHz ISM band, but in many regions it's actually slightly smaller than that.

Wikipedia on the ism page. But I probably misunderstood it. It's badly written.

Yes. They call it a band, because the nRF24L01 can operate on frequencies from 2.400GHz to 2.525GHz

It's like talking slower to someone. It makes it easier to distinguish the signal from the noise.

Kind of. Every channel is 1Mhz apart from the next (2.4Ghz + (125 * 1Mhz) = 2.525GHz which is the range specified above). This difference is chosen more of less arbitrarily. The 125 channels is because it has to stay inside the ISM band 2.4-2.5Ghz. Note that the different channels can still interfere with each other, unless they are far enough apart from each other. Just like with WiFi where you had 11 channels, but were advised to only use channels 1, 6, or 11. The NFR can only run at one frequency/channel at a time. You can however change channels while it's running. But its better to have all running on the same channel and use the NRFs pipes to create separate "networks". Or even use the same pipe, but have the packet contain the info on what kind of data it contains.

Note that not all channels may be usable. In the EU (ETSI) region for instance, the 2.4 GHz ISM band stop at 2.4835 GHz, so you can only use channels 1-83 at 1 MHz (up to 1 Mbps) and only half of those at 2 MHz.

@jcaron good point. I wanted to include this, but I couldn't find a good source. It looks like north america is even more restrictive, with a max of 2.473GHz. You definitely want to stay within these limits, and not risk fines or jail.

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


text:
Are breadboads available in EasyEDA?
So far I have been using TinkerCAD which has them but I am unable to find them on EasyEDA Library. Are connectors supposed to do the same thing? I get this empty rectangle in the EasyEDA library which I am unable to make sense of.

look at your arduino board ... do you see connectors for every single pin of every component?

you are supposed to draw a schematic diagram ... here is an example ... https://electronics.stackexchange.com/questions/523839/atmega328p-development-board

@jsotola Thanks for responding! I am still confused. When it comes to the Arduino, where do I type the code in order to simulate (TinkerCAD has a side window to do this)? As for the breadboard issue, do header pins work in the same way (ie do all the header pins on a single header have the same potential, much like a row on a breadboard)?

again, look at the header pins on your arduino board ... do they look connected all together?

I think that EasyEDA can simulate electronic circuits ... it does not simulate programming in devices

I think I get it. So in EasyEDA the "rows" of a breadboard would be redundant as you can just sketch regular parallel wires wherever needed or label the "nodes" which are meant to be at the same potential with the same term (?). But what about the power rails? Would tagging all the nodes which use the same power source as ##V_cc## do the trick?

EasyEDA is not designed for diy prototypes like TinkerCAD is.  EasyEDA's purpose is to simulate electronic circuits and design circuit boards for those circuit designs.  Because of this they don't have a breadboard object because there would be no point in having one, since you can just connect virtual wires in the schematic mode and wire traces in the board design mode.
Furthermore, it doesn't support simulating a full Arduino board with code.

So if a number of wires were to be connected to a node, for a breadboard I would connect them all to each hole in a row as all points in a row have the same potential and are connected to each other. For EasyEDA, would labelling all the points with the same label also work? So if a bunch of components were to be connected in parallel to a voltage source (V1), would labelling the relevant points with a node called V1 be the same as drawing parallel connections with wires? Thank you for helping!

If you are drawing an electrical schematic then the practice of labeling to signify a common connection point is common.  For example you'll see multiple GND labels on schematic diagrams.  On a circuit board layout, however, you wouldn't want to do this because the whole point of a circuit board layout is draw all the physical traces and connection points that will be make the circuit design function when made into a physical circuit board.


text:
How do I reset the recently used commands in Arduino IDE 2?
I am recording videos on Arduino IDE version 2. In one of the videos I want to explain how to enable a specific setting via the advanced properties. This requires using Ctrl+Shift+P (command palette).
However, my Arduino IDE now shows some commands I have used recently (sorry, screenshot is in German).

That's not the default. If someone has just installed Arduino IDE, he would need to scroll until he finds the entry. How do I reset the recently used items, so that I can record a proper video which requires scrolling?
Resetting the workbench layout does not help.

open the command palette
search and choose Preferences: Open Settings (UI)
in the preferences window, search for the setting workbench.commandPalette.history
set that value to 0 and it will not save the recent commands


text:
Arduino IDE 1 interfering with Arduino IDE 2?
In our electronics tinker club, we had installed Arduino IDE 1.8 including drivers + the Holtek UART bridge (vendor ID 04D9, product ID B534) for the Elegoo Smart Car Kit 3.0 Plus (product link). The board is an Arduino Uno clone.
We now installed Arduino IDE 2.0.3 in parallel and tried that one, because its features looked promising.
However, in Arduino IDE 2.0.3, we had problems uploading the compiled sketch to the Smart Car Board. When I checked, it reported a different vendor ID and product ID (sorry, I didn't record which one).
I reinstalled the Holtek UART bridge driver (direct download executable) and tried again. The vendor ID and product ID were correct this time, but uploading was still not going well in Arduino IDE 2.0.3.
Switching back to Arduino IDE 1.8 doesn't help. While the code still compiles (I expected it to), the upload problems now affect Arduino 1.8 as well, which was totally fine before we installed Arduino IDE 2.0.3.
How could I fix this issue?
I'll try to uninstall and reinstall everything, but I'm not sure it will be possible to uninstall all drivers.

You might want to add the command line and output of the call of avrdude.

@thebusybee: thanks. I don't yet know what that is, but I'll inform me about that and post it when I know it.

BTW: I upgraded 4 PCs to Arudino 2.0.4. It seems to work better on 2 PCs (upload works), but the other 2 still have the same problem.

In the IDE you can see in the output view the commands executed and their responses. You might need to set the respective option in the preferences. Copy this output as text into your question, please. -- Avrdude is the program that actually uploads the compiled sketch.

@thebusybee: thank you for this hint. It helped me a lot when diagnosing and comparing the different results. Since I had 9 robots and 8 noteboks, I had so much output and text for debugging purposes, I was reluctant to put it into the question. I have now posted an answer on this question.

I spent more time (almost 20 working hours) to isolate this problem by

testing the behavior with all of our 9 robot hardware in the club
testing the behavior with all of our 8 notebooks in the club
testing with the 6 different implementations we had, bricking and not bricking our robot hardware
testing with an additional notebook that didn't seem affected
combinations thereof

Finally I had a reproducible procedure with which I could "brick" a robot hardware and another procedure which would "unbrick" it.
That way I was able to a) minimize the code that was needed to "brick" the robot and b) compare that to the other codes that didn't have the issue. Finally I could ask this new question and get valuable feedback.
It turned out that this was not related to the new Arduino 2.0.3 or 2.0.4 IDE. It was just a timely coincidence that we wrote a new sketch we never wrote before in this way for this hardware.
That code used Serial.begin() with a "high" baud rate and obviously less delays than we ever used on this hardware before. And it turned out our hardware can't handle speeds higher than 19200 baud (!) without delay() statements. That's so slow!


text:
How to fix the scambled output of the emojis in Arduino IDE 2?
I have relatively simple code printing some emojis:
void loop() {
  // put your main code here, to run repeatedly:
  Serial.println("Hello world ❤♀♂✔");
}

Just in case it doesn't render very well, here's an image on how it looks like in Arduino IDE 2.0.3:

However, the Serial Monitor sometimes displays emojis and sometimes not. It varies from line to line like so:
Hello world �����������������♀�������♂✔����
Hello world ���������������♀♂✔
Hello world ��❤���������������������������������♂���✔
Hello world ❤��������������������
Hello world �������♀��������������✔����
Hello world ��������������♀�������������������
Hello world ��❤���������������������♂�������✔���

Again, there's how it looks like on my Windows 10 machine:

I verified that it's not a mistake in the baud rate. Both, Arduino and PC are set to 9600.
In Arduino IDE 1, the output is not colorful and some emojis are not rendered at all, but the result is much more consistent:

How to fix the scrambled output in Arduino IDE 2?

To be clear, this is a problem with handling any multi-byte UTF-8 encoding and potentially another problem on top of that with handling grapheme clusters. When I encountered this for the first time I think it was in using the degree symbol for a temperature reading (code point 0xB0) that encodes in UTF-8 as 0xC2 0xB0. Your odds of seeing the character correctly improve if you Serial.flush() and wait some time before and after multi-byte encodings and do not delay in the middle. In other words, increasing the odds that the Serial Monitor receive an entire UTF-8 sequence in a single buffer.

This is an issue of Arduino IDE 2.0.3. It was reported as issue 589 and issue 1405.
It was fixed on 9th of December 2022 [PR] and I can confirm it is fixed in nightly build 2.0.4-221229.


text:
Sea level pressure for BMP280
I have a BMP280 and BMP180 pressure sensor and I have both of them connected via I²C to a ESP8266.
For the BMP180, I can get the sea level air pressure when I pass the pressure and altitude like so:
// https://github.com/sparkfun/BMP180_Breakout_Arduino_Library
#include <SFE_BMP180.h>
SFE_BMP180 bmp180;
[...]
Serial.print(bmp180.sealevel(pressure, 800));

Is there a similar thing for the BMP280? Reading pressure and temperature works fine:
#include <Adafruit_BMP280.h>
Adafruit_BMP280 bmp280;
[...]
double temperature = bmp280.readTemperature();
double pressure = bmp280.readPressure() / 100;

It seems this was planned for the Adafruit BMP280 library but not implemented. Looking at Adafruit_BMP280.h we see commented code that has a method seaLevelForAltitude():
/*
class Adafruit_BMP280_Unified : public Adafruit_Sensor
{
  public:
    Adafruit_BMP280_Unified(int32_t sensorID = -1);

    bool  begin(uint8_t addr = BMP280_ADDRESS, uint8_t chipid = BMP280_CHIPID);
    void  getTemperature(float *temp);
    void  getPressure(float *pressure);
    float pressureToAltitude(float seaLevel, float atmospheric, float temp);
    float seaLevelForAltitude(float altitude, float atmospheric, float temp);
    void  getEvent(sensors_event_t*);
    void  getSensor(sensor_t*);

  private:
    uint8_t   _i2c_addr;
    int32_t   _sensorID;
};

*/

In another library, BMP280-arduino-library, I found a function that seems to work:
double BMP280::sealevel(double P, double A)
// Given a pressure P (mb) taken at a specific altitude (meters),
// return the equivalent pressure (mb) at sea level.
// This produces pressure readings that can be used for weather measurements.
{
    return(P/pow(1-(A/44330.0),5.255));
}

First, I just copied that function into my code (without the class name), due to the friendly pizza license. Later I switched to that library and it also worked fine.

thanks, it worked to me as well, and works actually the same way around like the way I suggested, it only defines another method return the sealevel pressure!

@PritamSarkar: sorry, I didn't try your solution, because I have already deployed mine. Yes, it's the same formula.

yeah, both are totally fine @ThomarWeller.

Try this following segment: I used it myself and it worked fine.
As you don't get any default Method for returning the sea-level pressure from BMP280, I had to calculate on my own.
#include <Wire.h>
#include "SPI.h" //Why? Because library supports SPI and I2C connection
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>

//Setup connection of the sensor
Adafruit_BMP280 bmp; // I2C
/*//For SPI connection!
#define BMP_SCK 13
#define BMP_MISO 12
#define BMP_MOSI 11
#define BMP_CS 10
//Adafruit_BMP280 bme(BMP_CS); // hardware SPI
//Adafruit_BMP280 bme(BMP_CS, BMP_MOSI, BMP_MISO,  BMP_SCK);
*/

//Variables
float pressure;       //To store the barometric pressure (Pa)
float temperature;    //To store the temperature (oC)
float SLpressure_mB;
int ELEVATION = 9;  //PUT HERE THE ELEVATION OF YOUR LOCATION IN METERS

void setup() {
  bmp.begin();    //Begin the sensor
    Serial.begin(9600); //Begin serial communication at 9600bps
    Serial.println("Equivalent Sea Level Pressure Test:");
}

void loop() {
  //Read values from the sensor:
  pressure = bmp.readPressure();
  temperature = bmp.readTemperature();
  SLpressure_mB = (((pressure * 100.0)/pow((1-((float)(ELEVATION))/44330), 5.255))/100.0)
  //Print values to serial monitor:
  Serial.print(F("Pressure: "));
    Serial.print(pressure, 2);
    Serial.print(" Pa");
    Serial.print("\t");
    Serial.print(("Temp: "));
    Serial.print(temperature);
    Serial.print(" oC");
  Serial.print("\t");
    Serial.print("Equivalent Sea Level Pressure: ");
    Serial.print(SLpressure_mB, 2);
    Serial.println(" mB");

    delay(5000); //Update every 5 sec
}


text:
Bluetooth HM-10 in central mode bonding with another bluetooth device
I have a bluetooth HM-10 configured in central mode. I have successfully connected it to another bluetooth device (a hexiwear bluetooth wearable). The problem now is that the hexiwear requires me to provide a 6 digit pin before it will bond with my HM-10.
Would anyone know the AT command that I could use to send the 6 digit pin from the HM-10 to the hexiwear?
Thank you.

The manual for the HM-10 can be found here.
Page 11 has the AT command you are interested in: AT+PIN:
AT+PIN123456
OK+Set:123456

By default the PIN is 000000.
(The manual is quite vague about the role of that command, so I assume since it is the only reference to PIN codes that it does what you require).

Thanks for the response. APIN command sets the PIN for the HM-10. My HM-10 is running central mode and I am trying to connect to a hexiwear (www.hexiwear.com) in peripheral mode. I am able to connect the hexiwear by sending AT+CON. After successful connection, the hexiwear pops up a 6 digit pin that I am required to now send from the HM-10. This is where I am stuck because I do not know if there's a AT command that lets me send a pin from central to peripheral.

Have you tried setting both devices to use the same pin?

Not yet, this requires me to hack my peripheral device because the pin it sends is a random number. But I will hack it and report back again soon. Thank you.

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


text:
Broadcasting parallel data from Arduino using router
I'm looking to read data from sensors using an ArduinoUNO in a greenhouse and then access the data wirelessly through a router. Hopefully through a webpage. No need for internet access, just local network access is good enough.
Preferably the only components involved would be the Arduino, the circuit, and a router with OpenWRT/DD-WRT to host the webpage and broadcast the network.
Pretty new to Arduinos in general, would this be possible? And how? The following 2 links from instructables.com seem to be the most relevant, can anyone give their input on how similar/different is this to my project?
http://www.instructables.com/id/PART-1-Send-Arduino-data-to-the-Web-PHP-MySQL-D3js/
http://www.instructables.com/id/Getting-Arduino-data-to-a-web-Page/

with an esp8266 you can run them as hotspots, no need for a router. otherwise, the router will be the same as any other wifi-providing box that happens to have a downed internet connection; p2p/lan use is still fine

Would the esp8266 allow me to host a web page on it?

yes, there's several ways to serve an html page from the esp, mere string building for example. the SPIFFS file web server makes it simple to host static assets, and you can make a quick API from just a few lines of C. fwiw, i've had much better luck pulling data from an esp webserver than with always-on connections like websockets or mqtt, likely because a web server does nothing while waiting, which uses no resources like bandwidth and power

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


text:
Arduino doesn't boot unless I short USB pin 1-2 (VCC/Data -)
I've made my own AVR programmer with an Arduino Nano V3 clone. It has been working fine, but yesterday I was trying to program a faulty board that pulled too much current. Was powering via USB and my OSX laptop told me it had disabled it due to pulling too much power.
After that I couldn't power it anymore, not even from a simple phone charger. I thought I had burnt something, but when testing with a DVM I accidentally shorted pin 1 and 2 of the USB connection:
1 - (red) VDC / plus / +5V
2 - (white) Data -

Then it boots up and is powered as long as I have them connected. Without it wont start with any usb connection, laptop or phone charger. Just to show what I mean:
https://photos.app.goo.gl/rtFj6bp3j4SbuYKr1
Why is this and is there something I can do to save this Nano - it seems to be working fine when usb is shorted like this…
Would hate to have to build up another one while waiting for a new programmer from China :)

Try measuring some voltages. Maybe the solder joint on the USB mini-B connector is broken.

When you plug the board in, the computer enumerates it. The normal device descriptor (IIRC) requests 50mA. If you are (as you most likely are) drawing more than that then the computer is quite within its rights to turn it off.
By shorting those pins you are preventing it from enumerating, so the computer doesn't know the requested amount, so it assumes (probably) 500mA.
You can achieve the same effect by using a cable with no data wires in it.

But it's the same with a phone charger thats rated for 1A and worked before. Something has happened with the Arduino.

Then maybe it's broken. It looks like a cheap chinese clone, so throw it away and get a new one.

It's possible you've blown the voltage regulator.  If you happen to have a source of those, like another dead Nano, you can try replacing it to see if that works.
Shorting the +5 to data is likely going to destroy your computers USB controller, so please quit.


text:
Atmega328p screen + midi, possible?
I'm trying to build this Midi2CV (control voltage for analog synths) using a Arduino Nano:
https://photos.app.goo.gl/3IhhFL3PrLELLODB3
I was hoping to use this Nokia screen too for settings and debugging purposes, but I just realized there's only one hardware serial port on 328p and software serial seemed to be doomed for MIDI:
SoftwareSerial too slow for MIDI?
So I have three peripherals:

DAC (MCP4822)
Nokia 5110 screen
MIDI

I've gotten both the DAC and screen to work fine on normal pins so I'm thinking I'm good with just using the hardware serial for MIDI and the DAC and screen can use software. Or am I in for a world of pain without getting a more powerful chip with more hardware serial ports? And if so, what's the recommendation? (shoestring budget)

Neither the MCP4822 nor the 5110 screen use UART. You only have 1 UART, and you only have 1 "peripheral" that uses UART - so where is your problem? The DAC and screen are both SPI devices.

I guess I have no problem then? I'm noob. I've gotten both to screen and DAC to work over SPI on normal D-pins. So the hardware serial thing on RX/TX is only (needed?) for UART?

For SPI you should be using pins 10-13 plus extras for other CS pins as and when you need them. Pins 0/1 are connected to the USB port through an adaptor chip, but if you don't use USB you can use them for hardware UART (and are the only pins on the Uno that can do hardware UART).

Of your three functions (DAC, screen and MIDI) only one (MIDI) actually uses UART.
The other two devices are SPI devices which, while it is a serial protocol isn't UART (serial is a concept not a protocol).
Connect the DAC and screen to the SPI port (you can share SCK, MOSI and MISO, but select different CS pins) and you have the UART pins (0/1) available for MIDI use - as long as you don't want to use the USB connection which is linked directly to those pins.


text:
Can't burn bootloader through Arduino Nano clone ISP to atmega328p
I'm trying to use a Nano v3 as ISP to program an atmega328p on a board with ISP headers:
I followed the instructions under
https://www.arduino.cc/en/Tutorial/ArduinoISP which I think have been recently updated. I'm simply connecting ISP headers together except for D10 from programmer to reset on the target AVR.

The ISP sketch seems to be working fine as far as I can see the heartbeat pulsing a led. But when trying to burn bootloader with settings:
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x15
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x15

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x14

avrdude: stk500_getparm(): (a) protocol error, expect=0x14, resp=0x01
avrdude: stk500_initialize(): (a) protocol error, expect=0x14, resp=0x10
avrdude: initialization failed, rc=-1
         Double check connections and try again, or use -F to override
         this check.

avrdude: stk500_disable(): unknown response=0x12
Error while burning bootloader.

I noticed something weird though, the 5V and GND on the ISP header on the programmer nano only has around 0.4V. This even without anything external but the usb connected. Is my nano broken or is the usb connection not able to deliver enough power?

If it's down to 0.4 V then there might be an almost-short circuit somewhere.

Turns out I was an idiot when I took that picture and did the measurement. I had simply turned the ISP header upside down :(. I'm at 4.7V which should be fine. Still same error though.

Your slave micro isnt resetting when your master wants it to reset.
Ie: master sends a reset signal before initiating further communication, and it seems that your slave not being reset.
So its not responding.
Once cross check your isp signal lines.

Try adding the 10µF capacitor connected to RESET and GND on the board you are using as programmer (in this case, your Nano). This is required according to the Documentation.

The 10µF electrolytic capacitor connected to RESET and GND of the programming board is needed only for the boards that have an interface between the microcontroller and the computer's USB, like Mega, Uno, Mini, Nano.

I just encountered the exact same error output, and the capacitor solved it.


text:
Errors trying to set fuses on bare Atmega328p
I have an Atmega328p on a board that I want to program using an Arduino programmer. I've got the programmer working to program other Arduino's over ICSP header, but when trying to use the same settings to avrdude to read/set the fuses of the bare MCU with oscillator I get the following:
❯❯❯ avrdude -v -p atmega328p -b 19200 -P /dev/cu.wchusbserial213240 -c stk500v1                                                                                ⏎ master

avrdude: Version 6.3, compiled on Sep 18 2017 at 20:31:51
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "/usr/local/Cellar/avrdude/6.3/etc/avrdude.conf"
         User configuration file is "/Users/viktor/.avrduderc"
         User configuration file does not exist or is not a regular file, skipping

         Using Port                    : /dev/cu.wchusbserial213240
         Using Programmer              : stk500v1
         Overriding Baud Rate          : 19200
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us
         PAGEL                         : PD7
         BS2                           : PC2
         RESET disposition             : dedicated
         RETRY pulse                   : SCK
         serial program mode           : yes
         parallel program mode         : yes
         Timeout                       : 200
         StabDelay                     : 100
         CmdexeDelay                   : 25
         SyncLoops                     : 32
         ByteDelay                     : 0
         PollIndex                     : 3
         PollValue                     : 0x53
         Memory Detail                 :

                                  Block Poll               Page                       Polled
           Memory Type Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
           ----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
           eeprom        65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
           flash         65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
           lfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           hfuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           efuse          0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           lock           0     0     0    0 no          1    0      0  4500  4500 0x00 0x00
           calibration    0     0     0    0 no          1    0      0     0     0 0x00 0x00
           signature      0     0     0    0 no          3    0      0     0     0 0x00 0x00

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

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.08s

avrdude: Device signature = 0x000000 (retrying)

Reading | ################################################## | 100% 0.08s

avrdude: Device signature = 0x000000 (retrying)

Reading | ################################################## | 100% 0.08s

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

avrdude done.  Thank you.

I've checked the soldering as good as I can and it seems to be right. I have a 10K pullup on reset, an oscillator with caps. I'm suspecting I might have fried the MCU when soldering or something - is there anything simple I can check?

All PWR connections check out
I've checked the oscillator with a scope and it isn't oscillating, but I'm thinking that is normal since it's a bare chip that I'm trying to set the fuses to use the external crystal? The oscillator is at least connected correctly.

Try using the "burn bootloader" function inside the IDE. That also sets the fuses.

I've done that too. The first thing that menu item does though is actually calling avrdude just like that - I think I actually looked at the verbose log in the IDE to get the params right.

It turned out it was a bit of bad soldering on the MCU. This same msg you'll get if just leaving the ICSP floating.

I'm glad you found a solution, but could you accept this (your own) answer as the solution?
This question just got bumped to the frontpage and actually is already solved.


text:
Manually added boards doesn't work in 1.8.5…?
I'm trying to manually add board definitions in a boards.txt file in hardware subfolder of my sketches folder as per instructions here for instance: https://www.arduino.cc/en/Tutorial/ArduinoISP
They however do NOT show up in my board selection.
My sketches location where hardware subfolder should be placed:

Board defs:
~/D/Arduino ❯❯❯ cat ~/Documents/Arduino/hardware/boards.txt
##############################################################

atmega328bb.name=ATmega328 on a breadboard (8 MHz internal clock)

atmega328bb.upload.protocol=arduino
atmega328bb.upload.maximum_size=30720
atmega328bb.upload.speed=57600

atmega328bb.bootloader.low_fuses=0xE2
atmega328bb.bootloader.high_fuses=0xDA
atmega328bb.bootloader.extended_fuses=0x05

atmega328bb.bootloader.file=atmega/ATmegaBOOT_168_atmega328_pro_8MHz.hex
atmega328bb.bootloader.unlock_bits=0x3F
atmega328bb.bootloader.lock_bits=0x0F

atmega328bb.build.mcu=atmega328p
atmega328bb.build.f_cpu=8000000L
atmega328bb.build.core=arduino:arduino
atmega328bb.build.variant=arduino:standard

atmega328bb.bootloader.tool=arduino:avrdude
atmega328bb.upload.tool=arduino:avrdude

BUT nothing show here:

I have restarted Arduino IDE.

Alternatively, and if the board is on internet, could not you added by the preference menu using the key combination " CTRL + , "?

Newer versions of the IDE (after 1.5) have a different folder structure where there is additional subfolders for maintainer and architecture.
<Arduino sketch folder>/hardware/<custom name>/avr/boards.txt

https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification


text:
using UART bridge module to have serial communication through usb port of arduino nano
This can be a silly question but I'm having a trouble with serial communication between arduino nano with other serial device. Please help me to handle it.
I'm currently doing a RF communication project using arduino nano and radio telemetry which is using serial communication. I tried to use SoftwareSerial but unfortunately, every pin is being used on arduino nano to control other extra devices. So I decided to have serial communication via usb port of arduino nano
Firstly, I directly connected rx and tx wire of RF device with D- and D+ of B type mini USB. but it did not work
Secondly, I tried to connect rx and tx wire with arduino nano via UART to USB bridge, cp2102 module. I soldered a female USB - male mini USB wire for this connection. but It did not work. the wiring that I build seems like the picture below.
Did I miss something? It doesn't work theoretically anyway?
Please help
Thank you in advance

Why do this rather than just connect it directly?

This is not possible - USB is not an ambidextrous protocol, rather there are distinct Host and Device roles, and while a few chips can switch-hit between them, the USB interface chips commonly used on Nano-style boards are strictly device only, and therefore cannot communicate with another USB device such as a USB-serial adapter.  There may well even be a duplicate here somewhere of a similar question having been asked before.
What you should probably do is just use the ATmega UART that interfaces to the USB chip, to talk to your external device directly (or through level translation and possibly inversion if it requires that).  The transmit side is no problem, however you will need to give some though to the receive side, as only one thing (the USB chip, or your external device) can drive that ATmega pin at a time.  Many of the official Arduino designs have a resistor there, which lets an external driver dominate over the on-board USB serial chip, but your board may or may not have that - if not, you may need to modify it.
And of course such a scheme requires that you disconnect the external device when uploading a new sketch via bootloader.
Another option would be instead of a traditional USB-serial converter, to use some sort of embedded USB host and have that convert to serial - the Kinetis KL25Z chip does this well, as does its close cousin on the Teensy-LC.  But at that point, you might as well just replace the Arduino Nano with a better chip having more pins, or even the ATmega328PB which has a second hardware UART.

Thank you so much Chris. It was really helpful!! after I read your answer, I tried to solder jumper cable from Atmega328 directly but.... I found out that arduino nano's RXI, TXO header pin is sharing the same wire with ft232 FTDI chip... maybe I can use the header pins.

An actual Arduino Nano has 1K resistors RP1B and RP1C between both the RX and TX nets that connect the ATmega pins to the module headers, and the differently named nets that run to the FTDI.  So on an actual Nano you should be able to override the FTDI from the header pins.  If your board is not an actual Arduino Nano, the situation might be different, however, the particular pack of cheap CH340-based boards I picked up for breadboard projects seem to have 1K resistors there as well.


text:
Building your own ESP8266 development board
I was wondering if someone could help me out?
I have been looking for a project that would test my existing skills and force me to learn new ones, and I thought that trying to build my own ESP8266 development board might be the best thing for me to try out.
I got some ESP 12-F boards and some veroboards that support it, it has a space for the ESP-12 and pads that lead to holes you can solder to.
However, I am a little confused at the moment. On a NodeMCU, for instance, you have way more connections than the ESP 12 offers out of the box. Is there a resource or guide that explains how these are broken out so that I can figure out how to provide those connections on my little dev board project? Like on the example here:
https://randomnerdtutorials.com/getting-started-with-esp8266-wifi-transceiver-review/
I get that I need to add the UART logic, I have that on order right now. I am just confused at the moment on how to break out the rest of the pins.
I hope this makes sense, please be gentle on me, this really is my first serious project and I wanted it to be challenging in order to learn.
Cheers,
Rafa

on esp-12 the esp8266 with external flash and supporting circuit is under the metallic cover. NodeMCU has pins which can't be used because the quad SPI for external flash uses them. these pins could be shared only with some SPI devices. the example for this sharing is for LCD.

Take a look at the NodeMCU schematic diagram and compare to ESP-12F module pinout, you will see the differences.


text:
switching power sources
I have a small project I am working on that accepts power from either a 5v DC power source or a USB power source.
Now, I know that both of the power sources are effectively 5v. I have measured the power on both with my meter and can see that the USB supply is at 5.4 and the DC supply is at 5.01v.
I would like to be able to build something that switches over to the USB supply when the cable is connected. However, I have never done this before. I have taken a look around on Google already and have read some things about P Channel MosFETs and PowerPath controllers - but I am a little confused as to whether the two incoming voltages I have are suitable for this?
Would someone be able to give me a little advice on this at all?
Cheers,
Rafa

You might get a useful response here, but this sounds like something that would be better asked on http://electronics.stackexchange.com

Just a side note: 5.4V on a USB supply is outside of specs. It should be 5.25V maximum.

Consider copying the Arduino Uno reference design.  This is part of that schematic showing the MOSFET used to turn on / off the USB power when the barrel jack power source is active:

actually, just the part of picture containing mosfet on the left would suffice.

It's more of a personal preference, but I never liked it when someone post a bit of a schematic and a key net name (in this case "+5V") is missing the source of the signal.  That's why when I copied the schematic I included the 5 volt regulator on the right.


text:
Using Serial.begin() twice
I'm training kids programming Arduino. We're gonna use Serial for debugging purposes, so we started with a simple HelloWorld program. I let them try various stuff, including changing the speed.
Now, one of the outcomes was as simple as
void setup() {
  Serial.begin(115200);
  Serial.println("Hello");
}

void loop() {
  Serial.begin(115200);
  Serial.println("world");
  Serial.begin(9600);
  Serial.println("world");
}

My expectation was, that the Arduino does exactly as written, but the serial monitor of the Arduino IDE will become a bit consufed. When the monitor is set to 115200 baud, I expected to see
Hello
world
_#&%$"    < some garbage
world
_#&%$"    < garbage again
...

However, the real output is only one line
H⸮⸮⸮⸮C

Why is that? Is it impossible to change the baud rate in between?
The official documentation does not say we can use Serial.begin() only once.
I'm using Arduino Uno and Arduino IDE 1.8.9

This is because the output of the serial is buffered. It's still sending the first bit of data while you change the baud rate - and from then on it's just a complete mess.
You need to force it to finish sending before you can change the baud rate by using Serial.flush():
void setup() {
  Serial.begin(115200);
  Serial.println("Hello");
  Serial.flush();
}

void loop() {
  Serial.begin(115200);
  Serial.println("world");
  Serial.flush();
  Serial.begin(9600);
  Serial.println("world");
  Serial.flush();
}

That will wait after each print until all the data is sent out "onto the wire" before changing the baud rate for the next print.

Wouldn't it be better to use Serial.end() to reset the buffer pointer too?

Why? It's a circular buffer - there's no beginning or end to reset it to.

Sorry, I meant the read buffer. The OP is obviously a teacher. As he has to explain it to other people, he should be aware of what is also possible and what is the difference. Using end() will not only flush the write buffer, this also resets the read buffer. This can be important as the speed switch make only sense, if it is negotiated with the communication partner.  If this happens asynchronously, there might be unwanted data in the read buffer. On the other hand, there might be situations when the read buffer should be preserved, so using end()  can be a problem too.

BTW a circular buffer has head and tail pointers. Resetting the pointers in that case means set the head to the tail pointer to clear the buffer data.

You are assuming that is the case everywhere. That functionality is undocumented. Yes, the Arduino core does it, but there are no guarantees that every core does it. Or even every version of the Arduino core does it (for example flush changed from clearing the read buffer to blocking on the write buffer...). Plus disabling and re-enabling the serial port may cause unintended side effects (floating pins) which could cause problems.

The functionality is documented https://www.arduino.cc/reference/en/language/functions/communication/serial/end/ . Your last sentence makes me think. You are right, switching the pins back to common usage can cause problems too. This must be considered in the negotiation process. I think our conversation is very informative. ;-)  At least I have some new aspects to think about.

No the functionality "clear the rx buffer" is not documented.  The function is documented, with barely any information, but nowhere does it say anything about any buffers being cleared, or even flush() being performed.

I guess I would have implemented Serial.begin() in a way that flush() is built-in. But ok, ... I think the official documentation is not perfect yet.

@PeterPaulKiefer: the good thing about teaching is: I always learn something new. Personally, I would never have written such a program, because it was clear to me that the output will be nonsense. But these kids (9 to 12 years) are not limited by their experience yet. They do funny random stuff, sometimes with unexpected outcome like this. And I hope there'll be more questions to be asked :-) I guess I can't explain it to them yet, because the concept of a "buffer" is way beyond their understanding.

I added a change request for the official documentation: https://github.com/arduino/reference-en/issues/711

@ThomasWeller I wish there were more like you. The documentation really needs a lot of work...

@ThomasWeller You are right, younger kids and artists are an unbelievable good source of inspiration. They don't fear about failures. They try things even if they think they wouldn't work.  I believe that is the difference between humans and computers and why computer can be creative. They are intended not to make errors. BTW: if the kids are really interested in MCU programming (for me it seems so) they learn with light speed. And questions about buffers can arise quicker than you think ;-)

Majenko I fully agree with you, that the documentation is in a worse state. I often have to look into the source code to find the information I am looking for. And the documentation is a nightmare for beginners. I often thought about contribute to the documentation after my investigations. But I fear my bad English is not understandable, especially for beginners. Because the documentation is not complete, I do not use it as a reference for my answers here.  "The code is the truth!"  Changes can happen in the code and also in the docs, so it doesn't matter where I based my answers on.


text:
Why can I measure two pins simultaneously?
I would like to do an action if both buttons on my arduino pro micro are depressed simultaneously. I'm getting some strange results:
// Buttons
Bounce button0 = Bounce();
Bounce button1 = Bounce();

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

  pinMode(2, INPUT_PULLUP);
  button0.attach(2);
  button1.interval(1);

  pinMode(3, INPUT_PULLUP);
  button1.attach(3);
  button1.interval(1);

  Serial.println("Setup Complete");
}

void loop() {
  button0.update();
  button1.update();

  if (button0.fell()){
     Serial.println("button0 fell");
  } else if (button0.rose()) {
    Serial.println("button0 rose");
  }

  if (button1.fell()){
     Serial.println("button1 fell");
  } else if (button1.rose()) {
    Serial.println("button1 rose");
  }

  if (button0.fell() & button1.fell()){
    Serial.println("buttons fell");
  } else if (button0.rose() && button1.rose()) {
    Serial.println("buttons rose");
  }
}

Here is the output to the Serial console:
Setup Complete
button0 fell
button1 fell
button0 rose
button1 rose

Why isn't this branch being executed? button0.fell() & button1.fell() For the life of me I cannot figure this out. Thank you!
EDIT
This doesn't work either, which is crazy:
void loop() {
  button0.update();
  button1.update();

  if (button0.fell()) {
    if (button1.fell()) {
      Serial.println("buttons fell");
    }
  }

  if (button0.rose()) {
    if (button1.rose()) {
      Serial.println("buttons rose");
    }
  }
}

EDIT
Thank you for the answers! Unless the person was to push both buttons in the exact same iteration of the loop, my code would never work. Here is what I ended up using:
if ((button0.fell() && !button1.read()) || (button1.fell() && !button0.read())) {

You can test it easily by calling the function twice directly after each other. If the first time a true is returned and the second time a false, the state is internally reset.
But probably because after you call the fell function, the internal state is reset, so after the call not a new fell has been happened.
So store the return value of the fell and rose functions and use those instead.
Update:
I'm not sure if this is the actual implementation but I found for fell/rose and see this:
bool Bounce::rose()
{
    return ( state & _BV(DEBOUNCED_STATE) ) && ( state & _BV(STATE_CHANGED));
}

bool Bounce::fell()
{
    return !( state & _BV(DEBOUNCED_STATE) ) && ( state & _BV(STATE_CHANGED));
}

So as long as the state has not changed it returns false (which is similar/equal as 'resetting the internal state'. Except this reset is done at a different location (but checked in the fell and rose function).
Update:
See remarks from gre_gor below

The fell function doesn't reset the state.

@gre_gor ... it checks if the state has changed, which is functionaly similar.

@MichelKeijzers The state is changed in update. Multiple calls to fell don't affect it.

@gre_gor than it's strange that storing the boolean would work.

https://github.com/thomasfredericks/Bounce2/wiki
I'm not familiar with the Bounce(2) library, but looking at the above site, it looks like "fell" is more of an "instant" thing, where it isn't something that maintains state over the Arduino loop.
Seeing as we are human, we can't (normally) push buttons at the same exact time.  This means that we would usually end up pushing the buttons within milliseconds, plural, of each other, but your simple example could loop multiple times between the first button and the 2nd button being triggered.
Don't forget that the Arduino Uno runs at 16mHz.  This is extremely slow compared to today's computers, but it's still running millions of operations a second.  My first computer, the IBM XT, ran at 4.77 mHz and that was the standard computer for years.
https://en.wikipedia.org/wiki/IBM_Personal_Computer_XT
I suggest putting in a loop counter to help you discover if this is the case.  Trying to display it every loop may slow the loop down, so only display the counter on your current displays.  If your "button0 fell {#}" display shows a different number than your "button1 fell {#}", then you know what's going on.  You may also want to display the actual contents of "button{01}.fell()".
IDK if this library does it, but in app programming, sometimes getting the value of an event like this will cause the event to be flushed and reset the value.  This would mean that calling a method the first time would render a different value than calling it a second time, even if the second time was immediately following the first call.  Setting "button{01}.fell()" to a variable might be a better option than trying to call it twice.

I'm getting some strange results:

your code doesn't really measure the two pins "simultaneously". instead, it measure the two pins sufficiently fast and it appears to be simultaneously.
use input capture for that.

Maybe I missed something but the branch doesn't execute because
button0.fell() & button1.fell()

should be
button0.fell() && button1.fell()

the else if clause also never executes.


text:
Delay only some function
I have code which control thermometer, OLED and nanoservo via MQTT. I want to refresh temperature every 10s. It works but my servo receive command only when temperature is refreshed. How can I configure my loop so my servo can receive MQTT command anytime I send it?
Here in my code (I combined several example codes...):
    #include <ESP8266WiFi.h>
    #include <Servo.h>
    #include <PubSubClient.h>

    #include <OneWire.h>
    #include <DallasTemperature.h>

    #include <Wire.h>
    #include "SH1106.h"
    #include "thermometer.h"

    // Data wire is plugged into pin 2 on the Arduino
    #define ONE_WIRE_BUS 14 // je D5 was 2 (D4)

    // Setup a oneWire instance to communicate with any OneWire devices
    // (not just Maxim/Dallas temperature ICs)
    OneWire oneWire(ONE_WIRE_BUS);

    // Pass our oneWire reference to Dallas Temperature.
    DallasTemperature sensors(&oneWire);

    SH1106 display(0x3c, D1, D2);
    #define DEMO_DURATION 3000
    typedef void (*Demo)(void);

    int demoMode = 0;
    int counter = 1;

    // Update these with values suitable for your network.

    const char* ssid = "******";
    const char* password = "******";
    const char* mqtt_server = "192.168.100.220";     /// MQTT  Broker
    const char* topic_state = "/blinds/state";
    const char* topic_command = "/blinds/command";

    IPAddress my_ip (192, 168, 100, 224);
    IPAddress my_gateway (192,168, 100, 1);
    IPAddress my_subnet (255, 255, 255, 0);

    WiFiClient espClient;
    PubSubClient client(espClient);
    long lastMsg = 0;
    char msg[50];
    int value = 0;

    Servo myservo;
    int state = 0;
    int prevstate = 0;
    int dirc = 0;
    int spintime = 0;
    int servoPin = D4; //CHANGE TO WHATEVETR PIN YOUR USING

    void reconnect();
    void callback(char* topic, byte* payload, unsigned int length);

    void setup() {
      Serial.begin(115200);
      setup_wifi();
      client.setServer(mqtt_server, 1883);
      client.setCallback(callback);

    // Start up the library
      sensors.begin();

    // Initialising the UI will init the display too.
      display.init();
      display.flipScreenVertically();
      display.setFont(ArialMT_Plain_10);

    }

    void servo_move() {
      Serial.println("State Change. Rotating Servo");
      if ( dirc == 180) {
        client.publish(topic_state,"open");
      }
      else if (dirc == 0) {
        client.publish(topic_state,"close");
    }
      myservo.attach(servoPin);
      myservo.write(dirc);
      delay(spintime);
      myservo.detach();

      Serial.println("Returning to main loop");
      return;
    }

    void setup_wifi() {

      delay(10);
      // We start by connecting to a WiFi network
      Serial.println();
      Serial.print("Connecting to ");
      Serial.println(ssid);

      WiFi.setPhyMode(WIFI_PHY_MODE_11N);
      WiFi.config(my_ip, my_gateway, my_subnet);
      WiFi.mode(WIFI_STA);
      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());
    }

    void callback(char* topic, byte* payload, unsigned int length) {
      Serial.print("Message arrived [");
      Serial.print(topic);
      Serial.print("] ");
      for (int i = 0; i < length; i++) {
        Serial.print((char)payload[i]);
      }
      Serial.println();
      char *blindcommand = (char *) payload; // convert mqtt byte array into char array
      blindcommand[length] ='\0';            // Must delimit with 0

      Serial.print(blindcommand);
      if (strcmp(blindcommand,"open") == 0) {
        Serial.println(" 433MHZ OPEN COMMAND RECEIVED");
        dirc = 180; // direction for servo to run
        spintime = 50; // << CHANGE TO WHATEVER TIME YOU NEED TO OPEN YOUR BLINDS
        state = 1; //sets current state
      }
      else if (strcmp(blindcommand,"close") == 0) {
        Serial.println(" 433MHZ CLOSE COMMAND RECEIVED");
        dirc = 0;
        spintime = 150; // << CHANGE TO WHATEVER TIME YOU NEED TO CLOSE YOUR BLINDS
        state = 2; //sets current state
      }
      if (state != prevstate) {
        Serial.println("State change!");
        servo_move();
      }
      prevstate = state;

    }
    char temperatureVonku[15];
    String tempUnit = " °C";

    void temperature(){
      float temperatureFloat;
      sensors.requestTemperatures();
      temperatureFloat = sensors.getTempCByIndex(0);

      dtostrf(temperatureFloat, 7, 1, temperatureVonku);

       client.publish("temp/outside", temperatureVonku);    /// send char
       delay(10000);
    }

    void dispTempVonku() {
        display.drawRect(1, 1, DISPLAY_WIDTH -1, DISPLAY_HEIGHT -1);
        // Font Demo1
        // create more fonts at http://oleddisplay.squix.ch/
        display.setTextAlignment(TEXT_ALIGN_LEFT);
        display.setFont(Roboto_Bold_12);
        display.drawString(5, 5, "Temp: ");

        display.drawXbm(7, 24, Img_width, Img_height, thermometer);
        display.setTextAlignment(TEXT_ALIGN_CENTER);
        display.setFont(Roboto_Bold_28);
        display.drawString(64, 22, temperatureVonku + tempUnit);
    }
    void dispTempVnutri() {
        display.drawRect(1, 1, DISPLAY_WIDTH -1, DISPLAY_HEIGHT -1);
        display.setTextAlignment(TEXT_ALIGN_CENTER);
        display.setFont(ArialMT_Plain_16);
        display.drawString(64, 22, "Hello World");
    }

    Demo demos[] = {dispTempVonku, dispTempVnutri};
    int demoLength = (sizeof(demos) / sizeof(Demo));
    long timeSinceLastModeSwitch = 0;

    void reconnect() {
      // Loop until we're reconnected
      while (!client.connected()) {
        Serial.print("Attempting MQTT connection...");
        // Attempt to connect
        if (client.connect("ESP8266Client", "******", "******")) {

          Serial.println("connected");
          client.subscribe(topic_command);
        } else {
          Serial.print("failed, rc=");
          Serial.print(client.state());
          Serial.println(" try again in 5 seconds");
          // Wait 5 seconds before retrying
          delay(5000);
        }
      }
    }
    void loop() {

     temperature();

      if (!client.connected()) {
        reconnect();

      }
      client.loop();
      // clear the display
      display.clear();
      // draw the current demo method
      demos[demoMode]();

      display.setTextAlignment(TEXT_ALIGN_RIGHT);
      display.drawString(10, 128, String(millis()));
      // write the buffer to the display
      display.display();

      if (millis() - timeSinceLastModeSwitch > DEMO_DURATION) {
        demoMode = (demoMode + 1)  % demoLength;
        timeSinceLastModeSwitch = millis();
      }
      counter++;

     //delay(10000);

    }

Thank you.

please follow the below links, might be useful: https://stackoverflow.com/questions/5452394/best-way-to-perform-an-action-periodically-while-an-app-is-running-handler https://stackoverflow.com/questions/14397973/how-to-read-continuous-data-and-display-it

I assume your servo only receives data when you keep the delay(10000).
The problem is that with a delay, the Arduino does kind of nothing during that time, so it cannot control your servo.
What you want is to call every 10 s the temperature update, but keep the servo control always running.
So keep a last-time-called variable (type unsigned long) that keeps the time of the last call to update the temperature. When 10 s have passed (you can check somewhere in the loop), you call it, and update the last time to the current time.


text:
Arduino as Slave | SPI | Answers too late
I hope you can help me :)
I am communicating between Raspberry Pi 3 and Arduino Uno with SPI. I am using the Arduino as slave and it works pretty fine. The only problem that i have, is the following:
For receiving data from the Arduino, my Raspi sends a byte. But i always have to send 2 bytes for the correct response. Is it even possible for the Arduino to response on the first byte?
Sorry for my english

Can you please post the full code you're using?

Because of the way SPI works, the slave cannot respond to the first byte in a meaningful way. It can send something (eg. 0x00) but not a response.
See my page about SPI. During an SPI transfer each bit is sent, and a bit received, simultaneously, as in this graphic:

You can see that as the first bit is received by the slave, it also has to send a response. There is no way that this response can react to the 8 bits, 7 of which haven't been received yet, by the time it has to send the first bit of response.

But i always have to send 2 bytes for the correct response.

You don't have to send 2 bytes all the time. For example, you can send one byte (eg. "send me the temperature") and then send zeroes after that, while you read back a (say) 4-byte temperature. So in this case you send 5 bytes to get a 4-byte response.

The only way you can respond on the first byte is if the Arduino already knows, and is primed, what to send on that byte before it begins to be clocked into the Arduino.
It is normal to have to send at least 2 bytes - the first is often used as either a register address, or a "read register" command.

Is it even possible for the Arduino to response on the first byte?

Yeah. There is nothing preventing your slave to respind on the first byte, so long as your code allows it.


text:
Ultrasonic Sensor returns com3 false
Im a very beginner with Arduino. Recently started with the blink code. Thats my only experience with these. Ive got an ultrasonic sensor (As in this tutorial http://howtomechatronics.com/tutorials/arduino/ultrasonic-sensor-hc-sr04/). So I setup the connections as trigger to Pin3 , Echo to 4, Vcc to 5v marked pin, GND to gnd next to 5v. Im using Arduino nano clone. When I run the program same as in the above example Im getting the following error. Other than that Im not getting any information.

Im sharing the same program I tried.
// defines pins numbers
const int trigPin = 3;
const int echoPin = 4;
// defines variables
long duration;
int distance;
void setup() {
pinMode(trigPin, OUTPUT); // Sets the trigPin as an Output
pinMode(echoPin, INPUT); // Sets the echoPin as an Input
Serial.begin(9600); // Starts the serial communication
}
void loop() {
// Clears the trigPin
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
// Sets the trigPin on HIGH state for 10 micro seconds
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Reads the echoPin, returns the sound wave travel time in microseconds
duration = pulseIn(echoPin, HIGH);
// Calculating the distance
distance= duration*0.034/2;
// Prints the distance on the Serial Monitor
Serial.print("Distance: ");
Serial.println(distance);
}

Where are you getting that error? That's not like any Arduino error I have ever seen.

I'm doing the code in Arduino web editor. I saw the above message in web console of the Arduino editor

That doesn't look like an error message - "level=info". I've never used the web editor but this page says you need to open the sidebar to see the serial monitor. Did you do that?

@JohnnyMopp Thanks a lot for that. I was using wrong console window. I was using the plugin console instead of the web console by mistake. Thanks a lot for guiding the correct way


text:
Do I need a relay to control a monitor's power with an Arduino?
I'm trying to use an Arduino to switch a monitor's power on and off. I'm going to wire the Arduino to the monitor's power switch. I've tested the power switch with a multimeter, and when pressed, there is a 3.3V current running through it that triggers the power on and off. The monitor itself is takes 12VDC to power. I know that a relay is used when switching larger power sources from a low voltage source so as not to damage the lower voltage source, but since the switch in question only runs at 3.3V would it be safe to use the Arduino without a relay?

I think that behind the switch you tested might be already a relay that switches the 12V.


text:
ESP8266 Soft Access Point: Timeout of request of resource when not responded to in set undocumented time
I'm experimenting with the ESP8266 chip on a Wemos D1 R2 board. I'm trying to write some code which will allow the user to input a username and password in an HTML form then get a response as to what happened with trying to connect to the WiFi as either they connected or the password was wrong. After I've turned setup Access Point and Station mode on the device using:
    // The field here would be global so other functions can access it
    ESP8266WebServer server(80);
    server.on("/connect", handleConnect);
    server.begin();

In my handleConnect function, I check the body of the request and attempt to login:
    if(!server.hasArg("ssid") || !server.hasArg("password")) {
        server.send(200, "text/html", "You didn't submit a ssid and password");
        return;
    }

    auto ssid = server.arg("ssid");
    auto password = server.arg("password");

    WiFi.begin(ssid, password);

    auto status = WiFi.waitForConnectionResult();

    server.send(200, "text/html", String(status));

When the user inputs the correct password, the function returns the request in time and the request responds with 3 (the connection was successful). However, if the password is wrong, the request times out. I've also tried several approaches to either work-around or fix the problem such as:

Using a while loop and calling WiFi.status() and checking it and responding accordingly. This approach ends with the same request timeout if the password is wrong. An example of this would be:
while(true) {
  delay(1000);
  auto status = WiFi.status();

  if(status == WL_CONNECTED) {
    server.send(200, "text/html", "You're connected!");
  }

  if(status == WL_CONNECT_FAILED) {
        server.send(200, "text/html", "You inputted the wrong password! Try again!");
  }
}

Registering another resource to specifically only return what state the WiFi is in and in the original connect function to send back HTML with some javascript in it which calls this other resource and do the decision making of what text to display client-side but this approach always returns 0 (when the WiFi is in process of changing between statuses, quoted from the docs)
server.on("/checkConnection", checkConnection);

// other code

void checkConnection() {
  server.send(WiFi.status());
}

And finally, I have experimented with using a public field to save the state once it has finished in the main function where the original connection tried to be established and then use the checkConnection function to return this state and this SOMEWHAT works, however, the code is messy, hacky and there must be a better way of doing this otherwise this will have to be my solution until the libraries are updated to fix this or something like that:

// public field for the status
      int status = 0;

      // other code

      void handleConnect() {

        // checking ssid and password

        WiFi.begin(ssid, password);

        // use an interval with AJAX or this to get the connection state
        server.send(200, "text/html", "Go to to check the connection");

        while(true) {
          delay(1000);
          auto s = WiFi.status();
          status = s;
          if(s = WL_CONNECTED) break;
        }

      }

      void checkConnection() {
        server.send(200, "text/html", status);
      }

Has anyone encountered this problem and if so, is there a better way of solving it apart from using a public variable which just makes it a pain in the bum to work with? Thank you.

waitForConnectionResult probably doesn't handle errors like you want. 2. WL_CONNECT_FAILED means other things too, so wouldn't you just want to look for anything beside 'connected'? 3. The AP must use the same channel as the STA, so i don't see how this can keep an http connection open while/if that changes.

@dandavis Thanks for replying. Firstly, waitForConnectResult is documented as to wait for the final result of the network and then return the connection state. Secondly, thank you for heads up on the other meanings of the WL_CONNECT_FAILED. I sort of asummed that it may have had some other meanings but now I know but in this case we're assuming the ssid is correct and only the password is wrong. Finally, the esp8266 has a WiFi mode called WIFI_AP_STA which allows the device to be an access point and a station, very handy if you want to do something like this so I don't think that is the cause.

yes, in WIFI_AP_STA, the wifi channels must match between the two. if your AP booted a different channel than the STA you're connecting to, you (afaik) won't be able to keep an http connection open during the AP's (unexpected/undocumented) channel change, no matter the password validity.

WifiMulti wifiMulti;//declare global.
wifiMulti.addAP(ssid,pass);//instead of WiFi.begin();
int i = 0;
//add below to wait for connection.
while (i < 20)
  {
    if (wifiMulti.run() == WL_CONNECTED)
    {
      return (20);
    }
    delay(500);
    Serial.println(WiFi.status());
    i++;
  }

Make the WiFi.begin outside the WebServer handler. In the handler store the ssid and password into variables and send a response. In loop() then make the WiFi.begin. For the result, pool from the browser with javascript.
Example


text:
Is it possible to use CCMP as cipher type on ESP32's softAP mode?
Currently I'm starting softAP mode on ESP32 with WPA2_PSK as auth type(as WPA3 is not supported for softAP). When I am trying to connect my iPhone to the softAP, iOS gives a warning that WiFi security is weak as it is using WPA2(TKIP). Instead it is asking to configure the AP to use WPA2(AES). I learnt that I need to use CCMP as cipher type instead of TKIP. But I cannot find any API to set cipher type for softAP. Is it supported? Or should I use only TKIP as encryption type? Thanks in advance!


text:
storing 600 unsigned int values in an array and find minimum and maximum values
I am reading an ASCII serial data values from a sensor and storing it in an unsigned integer variable. The values are ~45000 to 50000 range. I need to store 600 values and then find the minimum and maximum. after 600 values reached the oldest value is being replaced with the new value. The array size required is 600 which is approx.1200Bytes of the size of storage. I'm using Atmega 2560. I would like to know is it possible to store all 600 values in SRAM or do I need to use EEPROM memory?

The ATmega2560 has 8kB of SRAM. So yes. possible. Do you have a question, that cannot be answered by simply one word?

If you only need the minimum and maximum, you could calculate them on the fly, and not even have to store any of the values. Add a counter, so you know when you've received 600 values. Just a thought.

@gerban  @ chrisl  After reaching 600 values, the first stored value is deleted and all 599 values are shifted left, a new value is added(LIFO). This is a continuous process, from every 600 values, need to find out max.and min values. This is my requirement.

@Gerben Say the dropped value is the minimum value and the new value isn't lower than that value--the current minimum needs to be re-calculated. Could keep the two lowest/highest values, though.

The Atmega 2560 has 8K of static ram, more than enough for your 1200-byte array.
Reading-, and especially, writing EEPROM are very slow, and EEPROM has a rather limited lifetime-number-of-write-cycles, so it is not a good candidate for active use but rather for storing data that change infrequently and need to survive a power-down. These would typically per-system preferences, or data that needs to be stored to let the system resume at the next power-up, where it had left off when the power went down. This latter function requires that the system store enough power (capacitor or tiny battery) to keep it running long enough to sense the main power failing and still have run-time enough to write to EEPROM.


text:
Could someone explain this code that sets up the software serial port data rate?
I understand most of it. The part I don't understand is the is the code in for void loop. How does that set the data rate for the software serial port? I thought mySerial.begin(9600) did that? Please help.
#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3); // RX, TX

void setup()
{
    // Open serial communications and wait for port to open:
    Serial.begin(9600);
    while (!Serial) {
        ; // wait for serial port to connect. Needed for Leonardo only
    }

    Serial.println("Goodnight moon!");

    // set the data rate for the SoftwareSerial port
    mySerial.begin(9600);
    // set master
    mySerial.print("AT+ROLE1");
    delay(10000);

}

void loop() // run over and over
{

    // set the data rate for the SoftwareSerial port
    mySerial.print("test I am master  ");
    delay(10000);
    ***if (mySerial.available())
    Serial.write(mySerial.read());
    if (Serial.available())
    mySerial.write(Serial.read());***
}

it is just a wrong placed comment :-)

are you asking about the code highlighted with ***?

You're confusing "data rate" with "baud rate".
The baud rate is the speed at which bytes are transmitted over the wires, and is set with mySerial.begin(9600);.
The data rate is the speed at which data is sent over the serial port, and that is set by the delay(10000); which dictates how often "test I am master  " is sent and any incoming data is checked for and echoed.


text:
Arduino simultaneous push button for a counter
I am a newbie with arduino. I am trying to have a counter with 3 buttons. Each Button when pressed will increase the number of counts. The counter should still count if button 2 is pressed while button 1 has not been released, and button 3 should also be able to increase the counter even if button 2 and button 1 are still pressed.
My code below counts if only one button is pressed at a time.
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
int pbutton1 = 2;
int pbutton2 = 3;
int pbutton3 = 4;
int count = 0;

void setup() {
  lcd.begin(16, 2);
  pinMode (pbutton1, INPUT);
  pinMode (pbutton2, INPUT);
  pinMode (pbutton3, INPUT);

  lcd.print("My Counter");
}

void loop() {

  lcd.setCursor(0, 1);
  lcd.print("Total ");
  if (digitalRead(pbutton1) == HIGH) {
    lcd.print(count++);
    while (digitalRead(pbutton1) == HIGH); //monitor button to avoid continous count
  }

  if (digitalRead(pbutton2) == HIGH) {
    lcd.print(count++);
    while (digitalRead(pbutton2) == HIGH); //monitor button to avoid continous count
  }

  if (digitalRead(pbutton3) == HIGH) {
    lcd.print(count++);
    while (digitalRead(pbutton3) == HIGH); //monitor button to avoid continous count
  }
}

while (digitalRead(pbutton1) == HIGH); This blocks execution so nothing else can happen while the button is pressed. To avoid continous updating of the var while the button is pressed, create 3 booleans that keep track of the button state.
bool button1_is_pressed = false;
....
// If the button is pressed AND it was not previously pressed
if (digitalRead(pbutton1) == HIGH && !button1_is_pressed) {
    button1_is_pressed = true;
    lcd.print(count++);
}
// Not pressed - reset state variable
else if (digitalRead(pbutton1) == LOW) {
    button1_is_pressed = false;
}

Do this for the other buttons as well.

Hi! @Johnny, I have tried your code, it however gives a continuous count for as long as the button is pressed. In fact, a single push of the button already gives you like 38 on the counter, and not +1

@Kidd Could be a debouncing issue.  I'll test it here and see what results I get...

Thank you, I shall wait for your feedback, in the meantime. I will play around and see how it goes.

Ok, I tested and had some minor issues with debouncing. Adding delay(10) to the end of loop() fixed it. Also, not sure how you are wired, but if you have your buttons wired directly to a pin, you should use the built in pullup resistors: pinMode (pbutton1, INPUT_PULLUP);

I have the buttons connected to 1k ohms resistors then connected to the pins on the arduino

@Kidd The Arduino's internal pullup resistors are 10K. Maybe try that, as the code works fine for me.

I am able to handle the debouncing now with the delay. But keeping the button pressed still gives a continuous count.

I have managed to solve this using the PushButton library. If buttons are pressed simultaneously, the count still sums up when the button is released.
#include <LiquidCrystal.h>
#include <Pushbutton.h>

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
int count = 0;

#define button1 14
#define button2 15
#define button3 16

Pushbutton pbutton1(button1);
Pushbutton pbutton2(button2);
Pushbutton pbutton3(button3);

void setup() {
  lcd.begin(16, 2);
  lcd.print("My Counter");
}

void loop() {

  lcd.setCursor(0, 1);
  lcd.print("Total ");
    if (pbutton1.getSingleDebouncedPress()){
      count = count + 1; //increase the counter once the button is released
    }
    if (pbutton2.getSingleDebouncedPress()){
      count = count + 1; //increase the counter once the button is released
    }
    if (pbutton3.getSingleDebouncedPress()){
      count = count + 1; //increase the counter once the button is released
    }

  lcd.print(count);
}


text:
does EEPROM.write() only writes changed data?
Do I understand the code in EEPROM.cpp / write() correctly, that val is only written to the EEPROM, if val differs from the current EEPROM contents at the given address?
And if the answer is yes, what is commit() doing?

From library Library, see fragment:

EEPROM.write does not write to flash immediately, instead you must
  call EEPROM.commit() whenever you wish to save changes to flash.
  EEPROM.end() will also commit, and will release the RAM copy of EEPROM
  contents.

Probably to prevent too many writes into the same page (mostly EEPROM is divided in pages), the write stores it into some temporary buffer and the commit actually writes it to EEPROM. This decreases the number of writes, and since the number of writes has a maximum, the lifetime of the EEPROM is increased.
Update: Majenko's comment mentions no EEPROM is used, but flash, see below.

Note that the ESP8266 doesn't have any EEPROM. It uses EEPROM emulation in Flash memory. Since Flash memory can only be erased in blocks you can't change just one value - you have to wipe the whole lot and re-write it. Doing that for every value when you want to change multiple values would quickly cripple the flash (and be slow as a dead dog), so commit() batches those changes up into just one single erase/write sequence.

I have a function that writes ~500 byte to EEPROM if one of these bytes had changed. If write() works on a buffer in RAM, it could be better to have a write-wrapper that only writes changed data to that buffer - correct? ...and then hope, that this SPI_FLASH_SEC_SIZE is below my 500 bytes.

Actually, the write itself does not hurt. However, it might be good to keep a so called 'dirty' flag, which is initially false and only true when at least one value of the page/block has been changed. Than you know a commit is needed.

I already have this dirty-flag for my data structure in RAM. If one of my 500 byte was changed, I do a EEPROM.write() for all 500 byte and a EEPROM.commit() after it. My idea was, that it might be better, to call EEPROM.write() only for changed bytes. But now I found a #define SPI_FLASH_SEC_SIZE 4096 in spi_flash.h. And that should mean: it makes no difference, because EEPROM.commit() always works on the full buffer.

True ... it does not matter much to do an additional write, this is purely CPU and will be very fast and does not reduce the lifetime. Only commits do (probably even when the same values are overwritten).

I read that after the EEPROM.commit() you need to add a delay(500).
I had several issues with the EEPROM data gone after several restarts
of the esp8266.