message:
I want to code a depth sensor for arduino

I want to code a depth sensor for a little sub that i am working on. I want it to submerge to a any certain depth  for example 2ft. The speed of the motor is to increase by 5 until it reaches the set point given. The problem that I am facing is: **whenever it reaches the set example point of 2ft the motor turns off and the sub resurfaces to the top and doesn't hold the depth .**
What I want is that for whatever speed the motor is at for 2ft depth, to maintain its speed and keep the sub submerge at 2ft.

    #include <MS5837.h>
    #include <Wire.h>
    #include "MS5837.h"
    #include <Servo.h>
    MS5837 sensor;
    Servo vertical_thruster;

    float x;
    float error;
    int pwm = 1525;
    float currentdepth = sensor.depth();
    float recquireddepth = -0.4;  //  set depth u wish to maintain in meters

    void setup() {
          Serial.begin(9600);
         vertical_thruster.attach(6);
         vertical_thruster.writeMicroseconds(1500);
     /////////////////////////////////////////////Bar 30 Configuration ////////////////////////////////////////
      Serial.println("Starting");
      Wire.begin();
     while (!sensor.init()) {
        Serial.println("Init failed!");
        Serial.println("Are SDA/SCL connected correctly?");
        Serial.println("Blue Robotics Bar30: White=SDA, Green=SCL");
        Serial.println("\n\n");
        delay(2000);
      }
      sensor.setModel(MS5837::MS5837_30BA);
      sensor.setFluidDensity(997); // kg/m^3 (freshwater, 1029 for seawater)
    }

    void loop() {

      sensor.read();
      Serial.print("Depth: ");
      Serial.print(currentdepth);
      Serial.println("m");
    error = (currentdepth) - (recquireddepth) ;

    if ( error!=0)
      { pwm +=5;
        vertical_thruster.writeMicroseconds(pwm+=5);
        Serial.println( pwm+=5);
        Serial.print ( " Submerging ");
      }
    if ( error=0){
      vertical_thruster.writeMicroseconds(pwm);
      Serial.print ( "  At Depth");
    }
    else if ( error >-0){
      vertical_thruster.writeMicroseconds(1400);
      Serial.print ( "resurfacing");
      delay(1000);
    }
    }

body:
Your code has several problems:

- You are including the MS5837 library twice. That just doesn't pose a problem, because the library has include guards, that make sure it is only included once.
- At global scope you use `float currentdepth = sensor.depth();`, which calls the function `sensor.depth()`. This will be done before the `setup()` function, so at that time the sensor library does not have any valid depth data. So it's useless. You can just set it to zero.
- In your `loop()` you are doing `sensor.read()`, but then you are never actually getting the new depth value from the library. You are just again using `currentdepth` without changing it ever. You should set the variable to the new value by using `currentdepth = sensor.depth();` after the `sensor.read()`.
- You are using the statement `if ( error=0)`. Using only a single `=` means an assigment. So here the variable `error` get's set to zero and the if statement will not compare it so zero. You have to use a double `=`: `if(error == 0)`.
- `if( error >-0)`: Why are you checking for error being greater than MINUS ZERO. Sure, -0 is a valid integer, but mostly senseless. Also it is questionable, if the logic is correct here, since first you check for error being different than zero. Then you check for it being zero and then (if it is not equal zero) you check for it being greater than zero. If `error` really happens to be greater than zero, you will first write `pwm` to the servo and then directly 1400, which is submerging and resurfacing directly after another in only one loop.
- The whole if structure seems quite off. You should rethink the logic of the program.

---

That said, for reaching a set point of whatever kind it is good to use a PID controller, that will get you to the setpoint rather fast and will keep you there. A PID controller can be done in hardware or software. For implementing a software PID controller on Arduino you can use one of the various PID libraries, for example [this one][1]. Most libraries also contain examples, that show how to use them.

  [1]: https://github.com/br3ttb/Arduino-PID-Library


sender: user

sender: assistant

body:
    #include <MS5837.h>
    #include <Wire.h>
    #include <Servo.h>

    MS5837 sensor;
    Servo vertical_thruster;

    // Variables

    float current_depth ;
    float set_depth = 0.30 ; //  depth u wish to go in meters
    float PID_error = 0;
    float previous_error = 0;
    float elapsedTime,  Time , timePrev;
    float pwmvertical_thruster;
    int PID_value = 0;
    int PID_p = 0;
    int PID_i = 0;
    int PID_d = 0;

    //PID constants
    float kp = 4.1;
    float ki = 0.03;
    float kd = 1.8;

    void setup() {
      Serial.begin(9600);
     vertical_thruster.attach(6);
     Time = millis ();
     vertical_thruster.writeMicroseconds(1500);

    ///Bar 30 Configuration

     Serial.println("Starting");
     Wire.begin();
    while (!sensor.init()) {
    Serial.println("Init failed!");
    Serial.println("Are SDA/SCL connected correctly?");
    Serial.println("Blue Robotics Bar30: White=SDA, Green=SCL");
    Serial.println("\n\n\n");
    delay(2000);
     }
     sensor.setModel(MS5837::MS5837_30BA);
     sensor.setFluidDensity(997); // kg/m^3 (freshwater, 1029 for seawater)
    }

    void loop() {

    // First read the current value of the depth sensor
    sensor.read();
    current_depth = sensor.depth();

    timePrev = Time;
    Time= millis();
    elapsedTime = ( Time - timePrev) / 1000;

    // calculate the error between the set depth and current depth
    PID_error =  set_depth - current_depth ;

    // Calculate the P Value
     PID_p = kp * PID_error;

    // Calculate the i value in a range on +-0.3

     if (-0.3 < PID_error < 0.3 )
      {
      PID_i = PID_i + (ki * PID_error);
      }

    // Calculate the d value
    PID_d = kd*((PID_error - previous_error)/elapsedTime);
    // The total PID value
    PID_value = PID_p + PID_i + PID_d;

    // range for the blue robotics esc

     if ( PID_value < -400)
     {
     PID_value = -400;
      }
      if( PID_value >400)
      {
     PID_value = 400;
      }
    // calcualte the pwm
     pwmvertical_thruster = (1500 + PID_value) || ( 1500 - PID_value);
    if(pwmvertical_thruster < 1500)
     {
      pwmvertical_thruster= 1500;
      }
     if(pwmvertical_thruster > 1900)
      {
       pwmvertical_thruster=1900;
       }
        Serial.print("Depth: ");
        Serial.print(sensor.depth());
        Serial.println(" m");
        vertical_thruster.writeMicroseconds(pwmvertical_thruster);
        Serial. println ( "t\t");
        Serial. println ( pwmvertical_thruster);
         previous_error = PID_error;

       }`


message:
Adding WiFi to my Arduino Keypad Lock

I'm a really passionate beginner with arduino and electronics and I've built a Keypad lock for my room's door (inside the house).

I've used an arduino that activates a motor using a transistor to open the door if the correct pin is entered.

I want to add wifi control to my project. I have a few transistors, relays and ESP01s lying around for the upgrade. I want to use the blynk app and use the ESP01 independently without disturbing or modifying the arduino code. I'll program the ESP01 directly.

These are my requirements:

-A failsafe so I can open the lock via blynk if I forget the pin

-A kill switch that will turn off the arduino if I suspect somebody knows my PIN.

These are my ideas:

-Can I directly connect an ESP GPIO pin to the base of the transistor where the arduino is connected? By doing this can I control the transistor to switch the motor via both the arduino and the ESP 01?

-Can I put a relay module between the arduino and the battery pack and connect it to the ESP? I will connect the relay so that it will disconnect power to the arduino only when powered on. Is this a viable solution for a kill switch?

Any suggestions and ideas about how to go about this will be highly appreciated.

body:
> Can I directly connect an ESP GPIO pin to the base of the transistor where the arduino is connected?

No. You will effectively be connecting two outputs together, and that is very bad.

Instead you will need to add a second transistor in parallel to the first - one controlled by the Arduino and one controlled by the ESP-01.

> Can I put a relay module between the arduino and the battery pack and connect it to the ESP?

Sure. No problem with that.

> I will connect the relay so that it will disconnect power to the arduino only when powered on. Is this a viable solution for a kill switch?

As long as the kill switch doesn't also shut off power to the ESP-01 - otherwise it will just switch on again straight away...


message:
Compile error in Ubuntu 18.04

I'm trying to compile a code to arudino pro micro, I have the right option for compiling like the port and the type of the board,but I get an error,I can't copy

[![error message][1]][1]

  [1]: https://i.stack.imgur.com/KZiIq.png

body:
This is likely a permission problem.  The user likely does not have permission to read from and write to the port created when plugging in the Arduino.  This can be temporally fixed using the following command:

    sudo chmod 666 /dev/ttyACM0

However, this procedure is only temporary as the port is recreated every time the Arduino is reconnected to the computer.  And upon recreation the permissions are reset to their defaults for security reasons.

A better solution is to determine the group which the port belongs to and to add the users expected to access these connected devices to that group.

Plugin and list the port to determine its group:

    ls -l /dev/ttyACM*

or

    ls -l /dev/ttyUSB*

The group the ports belong to will likely be "dialout".  Add the user to that group:

    usermod -a -G dialout user_name

...where user_name is replaced by the name of the user who needs access to the port.  If you don't know the name of the current user you can use this command:

    whoami


body:
Sorry for the late reply,it worked in the ide that I download from the web,apparently ide from the ubuntu software won't work.
Thank for the answer


message:
about how to write data in the whole EEprom?

I have interfaced AT24c1024 EEprom with ATmega32.AT24c1024, which has 512 pages each of 256 bytes. There are two mode of writing (byte write and page write).

In page write mode, it is capable of writing 256 bytes for page; if we want to write 258 bytes, then the first two bytes in the beginning of that page will be overwritten.

My question is: what should I do to write in the whole EEprom (i.e) if I want to write 300 bytes, I want to writes 256 bytes in a page then continues to the next page and so on?

body:
In that case you write two pages, the first page containing the first 256 bytes and the second page containing the following 34 bytes.

You can do a speed check to see if writing the second page's 34 bytes by using the byte write is faster, but I doubt that.

In case you want to keep from the second page the remainder of the 34 bytes (the 256-34 bytes following), you first read the second page, than you change the first 34 bytes, than write it back.

Also note that there is a limit on the number of writes on a page. This is called page wearing. So if you write these 2 pages very often, you might want to come up with an algorithm to rotate through all the available pages in your EEPROM, and not writing every time to the same 2 pages.

**EXAMPLE**

Assume you want to write totalBytesToWrite:

    // Calculate the number of pages to write, round up.
    int pagesToWrite = int((totalBytesToWrite + 255) / 256;

    for (int page = 0; page < pagesToWrite; page++) // Current page to be written
    {
        // Calculate number of bytes to be written in this page, for the last page, write remaining bytes, otherwise 256
        int pageBytesToWrite = (page == pagesToWrite - 1 ? totalBytesToWrite % 256 : 256;

        // Write page (btw, I do not know what the second argument char deviceAddress means)
        page_write(n / 256, ??, &memory[n], pageBytesToWrite);
    }


message:
Arduino Communication with Sim 900

Im using an arduino uno and a sim 900, the simcard is setup and working as I can make a phone call to it and it rings.

The sim 900 is powered via the power jack and the uno is currently powered using USB.

I am trying to print out incoming text messages however with serial monitor open I only see "Initialising...".

        #include <SoftwareSerial.h>

    //Create software serial object to communicate with SIM900
    SoftwareSerial mySerial(7, 8); //SIM900 Tx & Rx is connected to Arduino #7 & #8

    void setup()
    {
      //Begin serial communication with Arduino and Arduino IDE (Serial Monitor)
      Serial.begin(9600);

      //Begin serial communication with Arduino and SIM900
      mySerial.begin(9600);

      Serial.println("Initializing...");
      delay(1000);

      mySerial.println("AT"); //Handshaking with SIM900
      updateSerial();

      mySerial.println("AT+CMGF=1"); // Configuring TEXT mode
      updateSerial();
      mySerial.println("AT+CNMI=1,2,0,0,0"); // Decides how newly arrived SMS messages should be handled
      updateSerial();
    }

    void loop()
    {
      updateSerial();
    }

    void updateSerial()
    {
      delay(500);
      while (Serial.available())
      {
        mySerial.write(Serial.read());//Forward what Serial received to Software Serial Port
      }
      while(mySerial.available())
      {
        Serial.write(mySerial.read());//Forward what Software Serial received to Serial Port
      }
    }

[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/QBZV9.jpg

I cant for the life of me figure out why its not printing anything else out? Can anyone give me any guidance or what to check?

body:
The 'Initializing' printout happens because that is sent directly to the UNO's hardware serial port.  The rest doesn't happen because it is directed to the SIM card via SoftwareSerial pins 7 & 8, and the SIM card apparently isn't responding.

Cut the problem in half:  Connect pins 7 & 8 together, and run your program again.  If you get "AT" and the rest, then you know the 'MySerial' port is active and working correctly, and the problem is in the SIM 'half'.  Maybe you have an incorrect wire connection there, or maybe the SIM card's default serial rate isn't 9600, or something like that.  YMMV ;-).

As a test, I ran your program on a UNO, with a jumper wire between pins 7 & 8.  Unfortunately this did not work, but now I knew that the problem had nothing to do with the SIM shield. The result wasn't what I expected, but now I had 'cut the problem in half'.

Now that I had determined that the SIM card wasn't a factor (so far, anyway), I could concentrate on the 'UNO half'.  After some web research I found that 'Software Serial' doesn't support 'loopback' (looping the transmit line back into the receive line) because it cannot simultaneously transmit and receive.  Fortunately, the 'AltSoftSerial' library by Paul Stoffregen **does** support simultaneous transmit & receive, and so will support loopback.

So, I installed the library on my Arduino setup, and compiled and uploaded the example shown below.

<!-- language-all: lang-C++ -->

    #include <AltSoftSerial.h>

    // AltSoftSerial always uses these pins:
    //
    // Board          Transmit  Receive   PWM Unusable
    // -----          --------  -------   ------------
    // Teensy 3.0 & 3.1  21        20         22
    // Teensy 2.0         9        10       (none)
    // Teensy++ 2.0      25         4       26, 27
    // Arduino Uno        9         8         10
    // Arduino Leonardo   5        13       (none)
    // Arduino Mega      46        48       44, 45
    // Wiring-S           5         6          4
    // Sanguino          13        14         12

    AltSoftSerial altSerial;

    void setup() {
     Serial.begin(9600);
     //while (!Serial); // wait for Arduino Serial Monitor to open
     Serial.println("AltSoftSerial Test Begin");
     altSerial.begin(9600);
     altSerial.println("Hello World");
    }

    void loop() {
     char c;

     if (Serial.available()) {
      c = Serial.read();
      altSerial.print(c);
     }
     if (altSerial.available()) {
      c = altSerial.read();
      Serial.print(c);
     }
    }

After uploading the code, I 'looped' pin 9 back to pin 8, and found that when I sent characters to the UNO via the hardware USB port, they showed up again 'echoed' to the serial output after having traversed the AltSoftSerial port 8/9.

So at this point I have solved the UNO 'half' of the problem; the rest is up to you! ;-)


message:
Communication between arduino nano and MCP3424 over I2c

I'm am completing a project of mine that uses an MCP3424 i2c 18bit ADC and an arduino nano to measure temperature with an NTC thermistor but am having trouble with the arduino wire library. This is my first project using i2c so I'm not very knowledgeable about the subject but I have rigorously read the datasheet of the MCP3424 that can be found at (http://ww1.microchip.com/downloads/en/devicedoc/22088b.pdf)
and tried many different ways to get it working. Also I'm new to posting on this stackexchange so pardon me if my syntax and what not is not right(I'm doing my best). Here is the code I have so far that is on my arduino.

```c
#include<Wire.h>

#define ReadMode 0xDD //Device will output conversion data (7 bits, device address. 1 bit, Read/Write mode)
#define WriteMode 0xDC //Device expects config byte (7 bits, device address. 1 bit, Read/Write mode)
#define ConfigByte18 0x8c //PGA = 1, SPS = 3.75, One-Shot mode, channel 1, initiate new conversion.
#define ConfigByte16 0x88 //PGA = 1, SPS = 15, One-Shot mode, channel 1, initiate new conversion.

void setup() {
  Serial.begin(9600);//Initiate Connection to computer
  Wire.begin();//Initiate Wire library
  Wire.setClock(100000);//make sure clock speed is standard mode
  delay(500);//Allow boot up and settle of ADC
  Wire.beginTransmission(WriteMode);//begin transmission with ADC in Write mode
  Wire.write(ConfigByte18);//configure the ADC with settings found in "ConfigByte18"
  Wire.endTransmission();
  Serial.print("Everything worked\n");

}

void loop() {
  unsigned char x, y, z, a, b, c;
  //Serial.println("Bytes ready to be read:");
  Wire.begin();
  Wire.setClock(100000);//make sure clock speed is standard mode
  Wire.beginTransmission(ReadMode);//begin transmission with ADC in write mode
  Wire.requestFrom(0x6E, 6);//request 6 Bytes of information from MCP3424
  x = Wire.read();//read bytes
  delay(10);
  y = Wire.read();
  delay(10);
  z = Wire.read();
  delay(10);
  a = Wire.read();
  delay(10);
  b = Wire.read();
  delay(10);
  c = Wire.read();
  Serial.print(x);//print bytes
  Serial.print(", ");
  Serial.print(y);
  Serial.print(", ");
  Serial.print(z);
  Serial.print(", ");
  Serial.print(a, HEX);
  Serial.print(", ");
  Serial.print(b, HEX);
  Serial.print(", ");
  Serial.println(c, HEX);
  Wire.endTransmission();
  delay(1000);

}
```

So an explanation of my understanding: In the “void setup” section I begin transmission in write mode (see page 21 of datasheet to follow along with my explanation figure and table 5-3) in the begin transmission function I address the slave with 0xDC because the device address begins with 1101 (pre programmed) and then 110 as I have the two Adr pins tied to +5v and finally 0 as I want to change configuration settings. This translates to 0xDC in hexadecimal. Then I send the slave a byte of information for the configuration register (see page 18 section 5.2). I send 0x8C as I want my settings to be PGA = 1, SPS = 3.75, One-Shot mode, channel 1, initiate new conversion. Which should mean I need to send the slave 10001100 or 0x8c. This communication then ends as “Any byte sent after this second byte will be ignored” according to page 21. Then in the loop I begin transmission the same way apart from now I open transmission in read mode which is 0xDD as the last bit (R/W bit) is now 1. I then request six bytes of information and read the six bytes. If you now go to page 23 of the datasheet you can follow along again. Here I should get three data bytes from the slave and every subsequent byte should be the configuration register settings repeated. For now I am uninterested in the first three data bytes as I first of all just want to know how to change the configuration settings. What gets printed by the arduino instead is three data bytes from the slave, as expected, and then three of the exact same value, also as expected as they should all be the configuration settings. What is being printed in the second three bytes is “90”. Not what I expected. Now I’ve tried to figure out what has happened (hard without an oscilloscope). 90 converted from hex to binary is 10010000 and I believe the default settings are (which can be found on page 18) 00001001 could this be the default settings if so can anyone tell me whats going on and how to fix it? Thank you in advance for the help and thank you for taking the time to read my problem.

body:
The problem is, that you misunderstood, how the `Wire` library handles addresses.

I2C uses an address byte, where the first 7 bits are the actual address and the last bit (Read/Write bit) dictates the direction of the communication. The `Wire` library gives you different functions for both directions (in your case: `Wire.beginTransmission()` for master write and `Wire.requestFrom()` for master read) and hides away the complexity of the Read/Write bit. So what you have to give as an address is the pure address of the device without the Read/Write bit. To write the configuration you used the address `0xDC`, but the actual address of the device is `0x6E` as you used it in the `Wire.requestFrom()` call.

Also in your `loop()` you try to start a master write with `Wire.beginTransmission()`, though you are starting a master read directly after it. `Wire.beginTransmission()` and `Wire.endTransmission()` are purely for master write transactions. So you should delete these lines here. For master read the call to `Wire.requestFrom()` and the corresponding reading is enough.

**What happens in your code:** In `setup()` you write the new configuration data to a wrong address (`0xDC` instead of `0x6E`). The transmission fails, as there is most likely no device with this address at the bus, but you don't notice, since you are not checking the return value of `Wire.endTransmission()`, which would show an error code. Then in the `loop()` function you reinitialize and reconfigure the whole `Wire` library again, which makes no sense, as Juraj mentioned in his comments. Though it will only cost some cycles of computation time. Then the library get's set to master write mode (no actual I2C action here, just interal to the library) and then to master read mode (actual I2C action. The provided number of bytes get's read here from the slave). At the end you say to the library, that is should finish the master write transmission from before, which is not there anymore (since you've done a master read). So this will do nothing. Also you are doing many delays between the reads, which is not necessary. When the `Wire.requestFrom()` function returns, all the I2C communication is finished. The bytes, that could be received, are received and written into the libraries buffer. `Wire.read()` will only read the next value from the buffer, remove it from there and return the value. No I2C action at that point, so the `delay(10)` is useless

TL;DR:

- Always use the correct address without Read/Write bit: `0x6E`
- Initialize and configure the `Wire` library only once in `setup()`
- Remove `Wire.beginTransmission()` and `Wire.endTransmission()` from the `loop()` function, as you are only doing master read there.
- Remove the `delay(10);` lines between the calls to `Wire.read()`


message:
Is AREF a stable output Ref voltage with analogReference(INTERNAL)

I'm using an analog input on a NANO board to measure the midpoint between two photo resistive (Cadmium) cells, with the two outside ends tied to GND and a source voltage. Basically a simple voltage divider. So it almost wouldn't matter what reference voltage I used in a case like that, as long as the AnalogReference() was correctly set corresponding to the reference voltage, AND the load did not pull down that voltage.

Well if I used the 5V for my source, and set AnalogReference(DEFAULT), then assuming a worst case load of 4K-ohm, the total load on the 5V regulator is still only 1.25mA. But even so, I figured I could minimize the system load even more by setting AnalogReference(INTERNAL), and using the VREF pin as a source for my voltage divider.

Well it seems to work fine, but I don't know that I've seen any actual examples of what I'm doing, which is using the AREF pin as a source output voltage for my voltage divider. Using vREF as a source, a 4K load would only draw 27.5 microamps with a 1.1V source. But I can't find any spec for the max current I should avoid exceeding, That has me worried maybe I'm not even supposed to be doing that!

So is it acceptable to use the VREF pin as an output for light loads, when using the INTERNAL AnalogReference?

Thoughts?

EDIT: After receiving a "no" answer yesterday, I did some bench checking. I configured my NANO board for Internal, and connected a fully open 100K linear pot from AREF to Ground, with a DVM in parallel. The AREF terminal output was about 1.076, with or without the 100K load. Not quite the 1.1 specified but close enough. I then slowly rotated the pot to increase load. At just under 9K the voltage dropped a somewhat insignificant amount, to 1.075. From there on there were additional small decreases, down to about 1K, at which point i measured about 1.062V. Below 1K, there was a very steep decrease.

Note that this was a "quickie" test, done while powering the NANO from a USB port. However, repeating the test with 12V on the DV input did not alter the results significantly.

Even considering the USB source, from this test I conclude:

1) There does appear to be some buffering on the VREF output. It certainly did not behave as there was a simple case of a 1.1V source in series with a high impedance.

2) Up to a load of 10K, the VREF output seems at least as stable as the 5.0V regulator output.

3) Since a 1.062 drop from an initial no-load voltage of 1.076 equates to less than a 2% difference, I have to conclude that a load on VREF (to ground) greater than 1K (lets say 2K for margin) makes VREF probably useful in cases like i described, with a worst case load of 4K.

4) I repeated my test with a second NANO board. This time the initial no-load voltage was salightly higher, 1.084. However, the response to increasing load and the K point where the slope changed dramatically were unchanged.

Again, this is an arduino NANO board, and probably a clone. Can anyone else verify or disprove my results? I'm sure someone else will need to consider using VREF as I did, and it would be good to know.

body:
No, it is not acceptable.

The datasheet states:

> AVCC is connected to the ADC through a passive switch. The internal 1.1V reference is generated from the internal bandgap reference (VBG) through an internal amplifier. In either case, the external AREF pin is directly connected to the ADC, and the reference voltage can be made more immune to noise by connecting a capacitor between the AREF pin and ground. VREF can also be measured at the AREF pin with a high impedance voltmeter. **Note that VREF is a high impedance source, and only a capacitive load should be connected in a system.**

The 1.1V reference is *only* presented on the AREF pin for the purpose of adding an external bypass capacitor, or for measuring it using a very high impedance meter. Any load applied to the pin *will* cause the reference voltage to droop.

While it may work in certain circumstances it's certainly not recommended. If you want to use it externally you should buffer it through a high-impedance unity-gain voltage follower:

<!-- Begin schematic: In order to preserve an editable schematic, please
     don't edit this section directly.
     Click the "edit" link below the image in the preview instead. -->

![schematic](https://i.stack.imgur.com/uNjhI.png)

<!-- End schematic -->


body:
Now, having had the benefit of a support ticket and subsequent discussion with an engineer at TI on this subject, I can confidently offer a *qualified* YES to my own question. It turns out my case is probably the only one that would be within those qualifications.

 1. In the case where the RATIO between two hi-resistances is the ONLY thing needed from an A/D measurement, it is acceptable to use AREF and GND for the applied voltage, provided the load is low (see item 2). The main reason is that any droop in the AREF caused by the added load would not affect the ratio.
 2. The use of AREF for such a situation should still ensure limiting any load on the AREF pin to about 91uA. For the 1.1V (INTERNAL) source selection, that equates to about a 12K load. The number is based on a reverse calculation that would cause a 1 LSB difference in analog readings, *IF* other analog inputs are expected to be used for other non ratio-metric measurements.
 3.  Using the AREF pin this way makes it even more important to add a capacitor from the pin to GND.
 4. Apparently there is no danger of harming the chip in any way, should the AREF pin become shorted.

I will comment that the engineer responding to my support ticket understood I was trying to avoid a PCB change, but recommended a different approach if I had occasion to make other board changes anyway. His recommendation was to use the EXTERNAL Analog reference option, using the available 3.3V pin for AREF voltage, and using a digital output to supply my voltage divider. The idea here is that I would still have the benefit of short circuit protection, and since I was concerned about power saving, I could switch the Digital output pin to a low state until readings needed to be taken, observing sensible delay for settling time.

A good suggestion indeed, but my reason for answering my own question here is because under the constraints given, using AREF as described in my OP is acceptable, will not affect the ratio measurement, and could not harm the chip.


message:
Sampling rate of multiple analog pins on Arduino

as I checked on Arduino website, they mentioned all boards: UNO, Nano, Mini, Mega have maximum sample rate 10kHz for each analog pin. So my concern is:
1) is there any difference between sampling rate when reading a single analog pin and multiple analog pins? For example, if we read only 1 analog input, maximum sample rate can reach 10kHz. How about maximum sample rate when we want to read 6 analog inputs? Maximum sample rate will be 10kHz or (10/6)kHz? Can we do analog input reading simultaneously or not?

2) What if I want to get sampling rate at least 1kHz for each Arduino board (assume 5 analog inputs)?

3) In case we need to connect several Arduino boards via I2C or SPI protocol, is sampling rate related to these 2 protocols?

body:
1)  You only have one ADC on board and all the pins run through a mux.  You can only read one pin at time.  If you're willing to give up some resolution then you might can read a little faster but it gets tough.  What's worse is that when you are switching pins really fast it can mess with your readings so that for some things, especially when input impedance is high, you have to read twice and throw away the first reading.  So that essentially cuts your sampling rate in half right there.

2)  That may be doable.  Or at least something close to it.  You'd run in free-running mode and write a tight ISR to read the interrupt when the analog read is finished and record every other value and switch the pin every other time.  Theoretically you should get pretty close to 1kHz with 5 pins.  Maybe a little faster if you give up a little resolution.

3)  Those communications protocols run at light speed compared to the analog read.


message:
Power supply affecting sensor readings ESP8266 and JSN-SR04T-2.0

I have an ESP8266 Wemos D1R2 Board with a JSN-SR04T-2.0 ultrasonic range finder and everything works perfectly when I have the device connected to my computer USB or via a 12V battery into the onboard regulator via the external power jack. However when I use a 240V AC to 12V DC transformer to power the setup my readings become quite erratic. I have checked the voltage coming out of the power supply (12.48v) and the voltage going to the sensor (3.28V,  I have it coming off the 3.3V pin) and it is the same on each type of power supply so the onboard regulator is working. Can anyone advise what might cause this? The transformer provides 1A which is more than enough as I have measured the peak usage at <100ma

body: The JSN-SR04T-2.0 ultrasonic range finder is rated to 5Volts. giving it 3.3 volts may not be enough. from my limited knowledge it should work if you give it a separate power supply and not depend on the 3.3 volts of the ESP.


message:
Distinguishing between multiple Infra Red Transmitters

I am working on an Arduino project where I use an infra red camera along with 4 transmitters placed each on a corner of a square platform to park a robot perfectly on this platform.
However, it is important for the camera to distinguish between the 4 transmitters.
(it should know the right transmitters from the left and the upper transmitters from the lower).
Can anyone please help me find a solution to this problem?

body:
It's a symmetry problem, you can solve it breaking the simmetry.
Options:

 - use three transmitter instead of four, the plane and its center is
   still determined.
 - move one transmitter in the middle of the side of the square.
 - use different duty cycle for one (or more) transmitter.
 - use linear polarizing filters on the transmitters and a rotating filter on the camera lense.
 - ...

I guess that also [SVD][1] could be helpful to find the pattern's center, when the camera is not centered and perpendicular.

  [1]: https://en.wikipedia.org/wiki/Singular_value_decomposition


message:
My stepper motor connected to a driver and an Arduino is not working

I'm using a 28BYJ-48 stepper motor with a ULN2003 driver board. I'm trying to control the motor using an Arduino MEGA. I initially connected the pins on the driver: IN1,2,3,4 to pins of the Arduino: 8,9,10,11 respectively; as was given in a youtube video I referred to(https://www.youtube.com/watch?v=HdqCtAJxhrs). The power for the motor was given from the 5V and GND ports in the Arduino. What happens is that it rotates 180 degrees,and then stops and then goes at random angles and stops. This was the code:
<!-- language-all: lang-cpp -->

    #include <Stepper.h>

    Stepper stepper1(64,8,9,10,11);
    int a=1;

    void setup() {
      stepper1.setSpeed(50);
    }

    void loop() {
      while(a<10){
        stepper1.step(2048);
        delay(1000);
        a++;
      }
    }

body:
For those who missed the comments, what I made a mistake in, as @JRobert pointed is that I was suppose to have connected the stepper motor to a separate power supply as the Arduino was not capable of so much resources. I also altered the code as I think I had gotten the steps-per-revolution wrong which is needed in the Stepper function in the Arduino Code. One needs to check this with the datasheet or somewhere online for the respective stepper motor model. The final code that got it working is [here][1]. All thanks to @JRobert for helping me figure out the solution :)

  [1]: https://www.mschoeffler.de/2017/09/23/tutorial-how-to-drive-the-28byj-48-stepper-motor-with-a-uln2003a-driver-board-and-an-arduino-uno/


message:
Mains And Battery Monitor Using Delay on And Delay off

I am very new to Arduino. In fact I am entirely new to embedded system. I have been using other platforms for my experiments specifically PICs.

I just moved to Arduino for more easier coding but I am hooked somewhere.

Here is the constraints:

In the code I will post below;

1. When MAINS is present and is within usable range, both MAINS_OK & ENABLE Pins will go HIGH after 3sec delay(non-blocking).

2. When MAINS is BAD, MAINS_OK Pin will go LOW immediately while ENABLE Pin will wait for 3sec before going LOW.

3. If MAINS is recovered and is within usable range again, the sequence described in "1." must be followed an so on.

I have tried in so many ways, it is not working as expected. Only the blinking of the SYSTEM LED is working fine.

```
// constants won't change. Used here to
// set pin numbers:
const int enablePin     = 7;      // the number of the Function Pins
const int lvdPin        = 6;
const int sysledPin    = 5;
const int mainsokPin   = 4;

// Variables will change:
int mainsPin = A0;
int batteryPin = A2;
int MAINS;
int BATT;
int ENABLE = LOW;
int LVD = LOW;
int SYS_LED = LOW;
int MAINS_OK = LOW; // State used to set the Function Pins

long previousMillis1 = 0;
long previousMillis2 = 0;// will store last time PIN was updated
long previousMillis3 = 0;
long previousMillis4 = 0;
long previousMillis5 = 0;

long ENABLE_ON        = 3000;
long ENABLE_OFF       = 3000;
long LVD_ON           = 3000;
long LVD_OFF          = 3000;
long MAINS_DELAY_ON   = 3000;
long MAINS_DELAY_OFF  = 0;
long SYS_LED_ON       = 1000;
long SYS_LED_OFF      = 1000; //Duration of the delay time (milliseconds)

void setup()
{
  pinMode(ENABLE, OUTPUT);  // set the digital pin as output:
  pinMode(LVD, OUTPUT);     // set the digital pin as output:
  pinMode(SYS_LED, OUTPUT); // set the digital pin as output:
  pinMode(MAINS_OK, OUTPUT); // set the digital pin as output:
  pinMode(A0, INPUT); //set pin as Analog nput
  pinMode(A1, INPUT); //set pin as Analog nput
}
void loop()
{
  unsigned long currentMillis1 = millis();
  unsigned long currentMillis2 = millis();
  unsigned long currentMillis3 = millis();
  unsigned long currentMillis4 = millis();

  if ((SYS_LED == LOW) && (currentMillis1 - previousMillis1 >= SYS_LED_OFF))
  {
    SYS_LED = HIGH;  // Turn it off
    previousMillis1 = currentMillis1;  // Remember the time
    digitalWrite(sysledPin, SYS_LED);  // Update the actual SYS_LED
  }
  if ((SYS_LED == HIGH) && (currentMillis1 - previousMillis1 >= SYS_LED_ON))
  {
    SYS_LED = LOW;  // turn it on
    previousMillis1 = currentMillis1;   // Remember the time
    digitalWrite(sysledPin, SYS_LED);    // Update the actual SYS_LED
  }

  MAINS = analogRead(mainsPin);

  //========================= MAINS OK =======================================
  /* If MAINS supply is ok, the MAINS_OK and ENABLE Pins will wait for 3sec
      before going high. Both Pins will go high at the same time.
  */

  if (MAINS >= 84 && MAINS <= 177) // >=0.410V && <=0.864V >=140V && <=250V
    if ((MAINS_OK == LOW) && (currentMillis2 - previousMillis2 >= MAINS_DELAY_ON))
    {
      MAINS_OK = HIGH;  // Turn MAINS_OK on with 3sec delay
      previousMillis2 = currentMillis2;  // Remember the time
      digitalWrite(mainsokPin, MAINS_OK);  // Update the actual MAINS_OK
    }
  if (MAINS >= 84 && MAINS <= 177) // >=0.410V && <=0.864V >=140V && <=250V
    if ((ENABLE == LOW) && (currentMillis3 - previousMillis3 >= ENABLE_ON))
    {
      ENABLE = HIGH;    //Turn ENABLE ON with 3sec delay
      previousMillis3 = currentMillis3;  // Remember the time
      digitalWrite(enablePin, ENABLE);  // Update the actual MAINS_OK
    }

  //=================== MAINS NOT PRESENT or IT IS LOW/HIGH VOLTAGE ====================
  /* As soon as MAINS is lost, whether it enters low voltage or high voltage,
     the PINs MAINS_OK will go LOW imedatly without delay while ENABLE will wait for
     3sec before going LOW. Then If MAINS is restored OK, the initial delay sequence
     must be followed.
  */
  if (MAINS <= 53 || MAINS >= 258) // <= 0.260V || >=1.26V// Below <= 120V and >= 276V
    if ((MAINS_OK == HIGH) && (currentMillis2 - previousMillis2 >= MAINS_DELAY_OFF))
    {
      MAINS_OK = LOW;  // Turn MAINS_OK off after 0sec delay
      previousMillis2 = currentMillis2;  // Remember the time
      digitalWrite(mainsokPin, MAINS_OK);  // Update the actual MAINS_OK
    }
  if (MAINS <= 53 || MAINS >= 258) // <= 0.260V || >=1.26V// Below <= 120V and >= 276V
    if ((ENABLE == HIGH) && (currentMillis3 - previousMillis3 >= ENABLE_OFF))
    {
      ENABLE = LOW;    //Turn ENABLE off aftar 3sec delay
      previousMillis3 = currentMillis3;  // Remember the time
      digitalWrite(enablePin, ENABLE);  // Update the actual ENABLE
    }

  BATT = analogRead(batteryPin);

  //============================ BATTERYERY SETTINGS ==============================
  /* If Battery is below 21V LVD Pin go HIGH with 3sec delay
      When it goes high, it remains high the Batter goes up to 27.6V
      LVD will then go LOW ahter 3sec delay
  */
  if (BATT <= 391) //(1.91V) 21V         // BATTERY Low
    if ((LVD == LOW) && (currentMillis4 - previousMillis4 >= LVD_ON))
    {
      LVD = HIGH; //Turn LVD on with 3sec delay
      previousMillis4 = currentMillis4;  // Remember the time
      digitalWrite(lvdPin, LVD);  // Update the actual LVD
    }

  if (BATT >= 512) // (2.50V)  27.6V         // BATTERY low Recovery
    if ((LVD == HIGH) && (currentMillis4 - previousMillis4 >= LVD_OFF))
    {
      LVD = LOW; // turn LVD off after 3sec delay
      previousMillis4 = currentMillis4;  // Remember the time
      digitalWrite(lvdPin, LVD);  // Update the actual LVD
    }
}

```

Please What can I add or remove from this code for it to work properly?

Thanks.

body:
There are lots of problems with your code. To start, most/all of this code is wrong:

      pinMode(ENABLE, OUTPUT);  // set the digital pin as output:
      pinMode(LVD, OUTPUT);     // set the digital pin as output:
      pinMode(SYS_LED, OUTPUT); // set the digital pin as output:
      pinMode(MAINS_OK, OUTPUT); // set the digital pin as output:
      pinMode(A0, INPUT); //set pin as Analog nput
      pinMode(A1, INPUT); //set pin as Analog nput

Those lines should be setting various pins to their desired input/output state. However, you are using the variables you declared to hold their bool status, not their pin numbers.

The variables you are using are declared like this:

    int ENABLE = LOW;
    int LVD = LOW;
    int SYS_LED = LOW;
    int MAINS_OK = LOW; // State used to set the Function Pins

Those are not pin numbers, those are variables that hold boolean values.

This line, for example:

    pinMode(MAINS_OK, OUTPUT); // set the digital pin as output:

Should almost certainly read

    pinMode(mainsokPin, OUTPUT); // set the digital pin as output:

Instead.

Same goes for `enablePin`, `lvdPin`, and `sysledPin`

The two lines

    pinMode(A0, INPUT); //set pin as Analog nput
    pinMode(A1, INPUT); //set pin as Analog nput

Should probably read

    pinMode(mainsPin, INPUT); //set pin as Analog nput
    pinMode(batteryPin, INPUT); //set pin as Analog nput

Since you define the variables `mainsPin` and `batteryPin`.


message:
Which Arduino microcontrollers are able to drive a parallel 8-bit ILI9341 display at 320x240@60fps with DMA or extra CPU core or both and how?

I've always wanted to make my own game console. I don't know why the existing Arduino game consoles have this issue with framerate when a 2006's [Sony handheld PC][1] had 1GB of RAM and an Intel CPU running Windows XP. Why haven't normal DIY open-sourcing copyright-libertarian hobbyists been able to make something at that magnitude? Don't say money because money is the reason I'm in gamedev scene; wanting to make a game console or anything that has a screen, characters, multimedia and nerdiness to make money.

So the issue has always been how do I find a microcontroller that's enough fast to run a 320x240 display like ILI9341 at 60FPS without stuttering or having to do lots of precalculations for partial screen updates. What about the NES/SNES consoles which didn't even have a framebuffer but which used discrete logic?

 - My scheme was to use ATXMEGA128A1U with a parallel bus and DMA, but it was hard to find a board containing all the stuff I needed and the External Bus Interface.

 - Then I tried to use ESP32 with SPI, but SPI would go max to 80MHz while the screen could only handle 40MHz.

 - Then I tried ESP32 again with 8-bit IO pin permutation which didn't work; it was too slow; maybe it would be faster if I used Xtensa assembly to take advantage of the CPU pipeline in case the dumb C++ compiler compiled machine code that waited 7 cycles for every next operation.

 - But now I'd like to use ESP32 with an I2S bus and DMA which was used for a camera demo and it was really really fast, but I'd like to use it for I2S output for that ILI9341 display. According to my calculations, it should take 10MHz to write out all of the bytes if the bus is 16-bit wide (8 bits for data and 1 bit for Data/Command register) + Read/Write/Select strobes controlled by the bus interface. However, Bitluni has been able to drive it to out of spec values of 580MHz for his VGA library that's superfast, but that month he had nothing to pay his rent with so he licensed the code under a copyleft license (ShareAlike). You know what they say, "The love of money and the lack of money are the roots of all evil.". Money is important, but really... this just makes money an even worse enemy than it was before.

So I guess I'm out of options. There have been many attempts and they have failed. Yes, there's Teensy and stuff, but I need something in the EU which I won't have to pay for more in shipping than the actual product.

So, what are the solutions?

P.S. if I get one of those "off-topic" or "too-broad" or dislikes to my question, I'm deleting it and moving to Reddit and screenshooting how yet again StackExchange is just too formalistic and banhammersome to open conversations.

  [1]: https://www.youtube.com/watch?v=E1r2e8ub02o

body:
The problem is the whole concept of running an ILI9341 TFT screen at 60FPS from a microcontroller. You can't. It's just not fast enough.

To get those kind of speeds you need to directly interface the TFT panel with the microcontroller. And that takes a special microcontroller with a TFT interface built in.  As well as that you need the memory to store the image that you are displaying on the screen.

There are microcontrollers available that can do it quite happily.  But they aren't in the "maker scene". Simply because they aren't a common thing to do.

For many years now there has been the PIC24 "DA" range of microcontrollers with a built in GPU and TFT interface - but there is no free C++ compiler, so no Arduino support - so no easy route to using them for beginners.

There are now, though, the PIC32MZ "DA" rage which are more accessible - though still very hard to use.  These are much more viable for the kind of thing you want, with 32MB of built in DDR, a TFT panel interface, and available in a 144 pin TQFP chip that is possible for an experienced maker to hand solder.

But the barrier is still software.  While chipKIT has full support for the PIC32MZ "EF" range of chips the "DA" range is not yet supported.  That's not to say you can't work with them, just not with the Arduino API and IDE.

The more common way to make a games console like device is to take an ARM SoC and interface it with a TFT panel directly. The simplest way for a maker to do that is to put a TFT on a Pi and install Retropie.

And we're not against open discussion as people. It's the site. It's not a site for open discussion. It's a *question and answer site*. You ask a technical question that you need assistance with, and we tell you the answer. It's not a forum for general discussion.  As such, this question will be closed as either "top broad" or "primarily opinion based". However your question does deserve an answer anyway.


message:
Is DS18B20 temperature sensor makes Arduino processing slow?

I recently run into a problem that causing my whole code processing slow down, for example i had a millis timer set for one minute but it took 1:30m to finish, pressing buttons was laggy etc.

After hours of digging and commenting out codes piece by piece i finally found out what is causing the slow down!

my DS18B20 temperature sensor DATA pin is connected to pin A0 when i remove the library and related codes to the sensor processing became MUCH faster more snappier/responsive...

After googling a bit i realized that everyone connected the sensor to pin 2 of Arduino!

So is the processing slow because DS18B20 is on pin A0 instead of pin 2 **or** there's something wrong with the sensor itself **or** it is because of [This library][1]?

  [1]: https://github.com/milesburton/Arduino-Temperature-Control-Library

body:
Indirectly it's the library.

That library uses the OneWire.h library.  The OneWire protocol requires some reasonably precise timing, and because of the the OneWire.h library turns off interrupts while it communicates.

While interrupts are disabled nothing else can happen. That means that the timer interrupt that drives `millis()` can't "tick" - so the millis count doesn't increase while you communicate with the temperature sensor.


body:
The **software function** managing the 1-wire protocol generally has several non-interruptable sections in order to ensure the bus timings.  This can make your processor unavailable for long periods of time.

Worse, some implementations do not allow any interrupt at all.

And even if your implemenation would allow being interrupted, it is generally blocking the main loop as it is not executed in an interrupt itself.

Using a **hardware implementation** for the 1-wire control instead of a full software would release the CPU from managing the timing and waiting for the 1-wire to complete.  But such hardware implementation are not commonly available in microcontrollers.

There is however a middle way.  An open source implementation using **the microprocessor's or controller's UART** to ensure the timings is available ( https://github.com/MaJerle/onewire_uart ) - MAXIM also has an application note for it ( https://www.maximintegrated.com/en/app-notes/index.mvp/id/214 ).
This also offloads the processor and it can be interrupt driven.

**Is the processing slow because DS18B20 is on pin A0 instead of pin 2 ?**
That might have an influence if the processor that is on your Arduino board would have a (partially) 1-wire compatible source on another pin, in which case the libary would have to take advantage of that.

**Is there something wrong with the sensor itself?**
That would not be generally the case, but in case you have two sensors on the same bus, the 1-wire protocol is slower as it needs to find all peripherals and the master has to indicate which one it is addressing.

**Is it because of "This library"?**
It is not because of that library, but there are other implementations (see the link above) that use hardware resources to improve performance at the cost of using a hardware resource (some MCU's have only 1 HW UART so you'ld not have a second one if you also need RS232 communication for instance on other signal lines).


message:
Do we have an alternative for millis() function?

This is actually a follow up question to [this question][1], so basically I'm using DS18B20 temperature sensor which requires Onewire.h library that interrupts millis() function.

Luckily i have a [DS3231 RTC][2] module which I'm using it with [RTClib library][3], is there any way to use that module as a timer instead of millis() function?

  [1]: https://arduino.stackexchange.com/questions/67125/is-ds18b20-temperature-sensor-makes-arduino-processing-slow
  [2]: https://www.amazon.com/DS3231-AT24C32-module-precision-Arduino/dp/B00HCB7VYS
  [3]: https://github.com/adafruit/RTClib

body:
You can use the SQW output of the module to indicate the passage of precisely 1 second. Every time it transitions from LOW to HIGH one second will have passed.

RTCs cannot give you times of higher resolution than 1 second, but they can give you that 1 second granularity to a high accuracy.


message:
How to control 220V RGB Led Strip with Arduino/ESP32

I need to control 220V RGB Led strip with Arduino/ESP32-wroom over internet.
Single color led is easy (just with a relay), 12V RGB can be done with PWM and maybe external power source. But how can I control 220V RGB via MCU?
I couldn't find any answer yet.

body:
Try looking at a relay or a [triac](https://en.m.wikipedia.org/wiki/TRIAC).

Also, you can not simply "use PWM to control a 12V circuit from your MCU" which is most likely running at 5V. You need to use a component such as a MOSFET. The MCU controls the MOSFET via the Gate. The MOSFET switches the 12 V circuit off or on based upon the signal at the gate.

Alternatively, like the AC solution, you can use a Relay to control the 12V circuit.


message:
how to use hx-53 (IR Transmitter Infrared Sensor Module) with ESP32?

ESP32 tx2 (pin17) and rx2 (pin16) uses 3.3v based signals.

HX-53 data connect to tx2, gnd to gnd and vcc to vin(5v).

But as i can understand HX-53 data input should be 5v based.

How can i solve this problem?

HX-53: https://www.amazon.com/Electronic-Infrared-Emission-Transmitter-Arduino/dp/B07PJC7WSQ

Best regards.
GA

body:
The HX-53 look like a IR LED and a current limiting resistor on a small PCB.

It also has a LED and a resistor in series for indication when the invisible IR diode is on or off.

So you can change the resistor to a lower value to match the 3,3 volt output from the ESP32.

Resistor values:

    221 = 220 ohm   = IR LED
    102 = 1000 ohm  = SMD indicator LED

So replace the 220 ohm with something near 75 ohm.

**HX-53**

[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/cQW47.jpg


body:
I happen to have one just like yours. I was trying to use it on my Arduino to send commands to my AC like a remote but as it turns out, the Vcc pin on the HX-53 breakout board appears to be a dummy and doesn’t connect to anything as far as i know. By right there should be a transistor circuit driving that LED. As it is now, not only is there insufficient current from the signal pin to drive that IR LED for signal bursts, but the red SMD LED in series with the resistor is also stealing some of the current away from the IR LED. In the end, I had to buy a BJT, a standalone IR LED, some resistors and design my own transistor circuit to drive it.

On the transistor’s collector side I had a connection to Vcc and the IR LED in series with a resistor. On the base side was a connection to the signal pin and a resistor. The emitter was connected directly to Ground. Values of the resistors you use will depend largely on the Vcc, the LED max forward current, the specs of the transistor you choose and available current from the power supply.

Hope this helps.


message:
Why is Serial.write() slower than memcpy()?

I use `Serial.write()` to transmit 53 bytes to PC. For the time measurement I use `micros()` (before and after the write function). There is a delay of 1s after each transmission.

The time of the `Serial.write()` function is 532 us with 1000000 baud rate, and 360 us with 9600 baud rate.

The `Serial.write()` function is clearly asynchronous because the transmission of 53 bytes with 9600 baud rate is 53*8/9600*1e6 = 44167 us. (By the way, in the case of 1000000 baud rate, it is not so obvious that the function is asynchronous.)

I use `Serial.availableForWrite()` before `Serial.write()` to confirm that there is enough space in the buffer (this returns 63 each time, the buffer size is default 64).

I don't understand these numbers. Using `memcpy()` to copy the 53 bytes only takes 32 us. Is copying to the serial buffer not the same as the `memcpy()` function? And why is there a difference in the copy times when the baud rate is different? Serial.write() is even slower with higher baud rates according to the results. Why does `Serial.availableForWrite()` return 63 while the buffer size is 64 (according to SERIAL_TX_BUFFER_SIZE)?

Update:
Thanks for all of your answers.

I have tried another library for serial communication: https://github.com/greiman/SerialPort

It seems to be faster than the original one.
I use 2 time measurements and a delay in the code, these 3 deltaTimes represents the whole step as follows:

writeTime + memcpyTime + delaymicros = computedTime != realTime

The first 2 times are measured, the delaymicros is the theoretical delay (900 us), I can compute the step time from these. This computed step time is different from realTime (the measured step time, I measure the whole step too). It seems that the additional time can be found in the delay.

SerialPort library:
100 + 30 + 900 = 1030 != 1350

writeReal = 100 + 1350 - 1030 = 430

Arduino Serial:
570 + 30 + 900 = 1500 != 1520

writeReal = 570 + 1520 - 1500 = 590

Then I measured the delaymicros time (which is 900 us in theory), the missing time can be found there. I programmed 900 us delay, but the real delay was around 1200 in the first, and 920 in the second test.

These measurements can prove the existence of the interrupts, because measuring only the write functions doesn't give all of the writing time (especially with the downloaded serial library).
The downloaded library can work faster, but requires bigger tx buffer because of errors (256 works properly instead of 64).

Here is the code: I use a checkSum in the sendig function (which is 570-532 = 38 us). I use Simulink to receive and process the data.
<!-- language-all: lang-cpp -->

    struct sendMsg1 {
      byte errorCheck;//1

      unsigned long dT1;//4
      unsigned long dT2;//4
      unsigned long t;//4
      unsigned long plus[10];//40
    };//53

    sendMsg1 msg1;
    byte copyMsg1[53];

    unsigned long time1;
    unsigned long time2;
    unsigned long time3;
    unsigned long time4;

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

    void loop() {
      sensorRead();
      sendMsg1_f();

      //time3 = micros();
      delayMicroseconds(900);
      //time4 = micros();
    }

    void sensorRead() {
      time3 = micros();

      msg1.t = micros();
      for (unsigned long i = 0; i < 1; i++) {
        memcpy((void*)&(copyMsg1[i*sizeof(sendMsg1)]), (void*)&msg1, sizeof(sendMsg1));
      }

      time4 = micros();
      msg1.dT2 = time4 - time3;
    }

    void sendMsg1_f() {
      time1 = micros();

      msg1.errorCheck = 0;
      for (int i = 0; i < sizeof(sendMsg1) - 1; i++) {
        msg1.errorCheck += ((byte*)&msg1)[i];
      }
      Serial.write((byte*)&msg1,sizeof(sendMsg1));

      time2 = micros();
      msg1.dT1 = time2 - time1;
    }

body:
If you take a look into the implementation:

<!-- language: c++ -->

    size_t HardwareSerial::write(uint8_t c)
    {
      _written = true;
      // If the buffer and the data register is empty, just write the byte
      // to the data register and be done. This shortcut helps
      // significantly improve the effective datarate at high (>
      // 500kbit/s) bitrates, where interrupt overhead becomes a slowdown.
      if (_tx_buffer_head == _tx_buffer_tail && bit_is_set(*_ucsra, UDRE0)) {
        // If TXC is cleared before writing UDR and the previous byte
        // completes before writing to UDR, TXC will be set but a byte
        // is still being transmitted causing flush() to return too soon.
        // So writing UDR must happen first.
        // Writing UDR and clearing TC must be done atomically, otherwise
        // interrupts might delay the TXC clear so the byte written to UDR
        // is transmitted (setting TXC) before clearing TXC. Then TXC will
        // be cleared when no bytes are left, causing flush() to hang
        ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
          *_udr = c;
    #ifdef MPCM0
          *_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << MPCM0))) | (1 << TXC0);
    #else
          *_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << TXC0)));
    #endif
        }
        return 1;
      }
      tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_BUFFER_SIZE;

      // If the output buffer is full, there's nothing for it other than to
      // wait for the interrupt handler to empty it a bit
      while (i == _tx_buffer_tail) {
        if (bit_is_clear(SREG, SREG_I)) {
          // Interrupts are disabled, so we'll have to poll the data
          // register empty flag ourselves. If it is set, pretend an
          // interrupt has happened and call the handler to free up
          // space for us.
          if(bit_is_set(*_ucsra, UDRE0))
     _tx_udr_empty_irq();
        } else {
          // nop, the interrupt handler will free up space for us
        }
      }

      _tx_buffer[_tx_buffer_head] = c;

      // make atomic to prevent execution of ISR between setting the
      // head pointer and setting the interrupt flag resulting in buffer
      // retransmission
      ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
        _tx_buffer_head = i;
        sbi(*_ucsrb, UDRIE0);
      }

      return 1;
    }

It basically answers all the questions.

If the buffer is empty and it's not sending anything, it'll send the character directly so it's synchronous (but sending the character will be much faster than overhead of function callbacks and so)

No, you cannot use memcpy, as it just replaces buffer, but it does nothing else, like actually start the data register ready interrupt nor proper setting of head/tail counters (it's round buffer, so there can be scenario you'll overwrite something outside of buffer)

And write function is called for each character separately (all other specialisation of write are using this one)

Also if the buffer is full, it'll wait until there is a space for another character.


body:
Copying to the serial buffer is not the same as `memcpy()`, no.

The serial buffer is a [circular buffer](https://en.wikipedia.org/wiki/Circular_buffer). Because of that there are lots of calculations involved in working out exactly where in the buffer to place the next character. That takes time.  `memcpy()` just copies one block of memory directly over another. It makes no checks, and it can't wrap around like a circular buffer.

The reason why higher baud rates seem slower is because each character is taken from the buffer by an interrupt. The higher the baud rate the more often that interrupt is triggered, and so the more time is spent by the CPU in processing that interrupt to send the next character. And equally, the less time is available to the CPU to process the placing of data into to the serial buffer.


body:
The function you were testing is presumably
`Serial.write(const uint8_t *buffer, size_t size)`.
If you search for it in HardwareSerial.h, you will see

```c++
    using Print::write; // pull in write(str) and write(buf, size) from Print
```

and the implementation is in Print.cpp:

```c++
/* default implementation: may be overridden */
size_t Print::write(const uint8_t *buffer, size_t size)
{
  size_t n = 0;
  while (size--) {
    if (write(*buffer++)) n++;
    else break;
  }
  return n;
}
```

This is writing the bytes one by one, and for every byte, the whole code
of `HardwareSerial::write(uint8_t c)` is being run. This includes the
tests for full or empty buffer, and the arithmetic for updating
`_tx_buffer_head`.

As stated in the comment above the code, it would have been possible to
override this with a specialized implementation. In principle, you could
copy the linear buffer into the ring buffer using at most two calls to
`memcpy()`, and updating `_tx_buffer_head` only once. That would likely
be more efficient than the current implementation, at least for buffer
sizes in the range you are using (close to, but less than the ring
buffer capacity).

Would it be worth it? Maybe for your use case it would. But it could
also make the code more complex and require more flash. And the benefit
is likely to be really small for people who write small buffers. I am
not sure a pull request implementing this sort of optimization may be
accepted. You may try if you feel like so.


message:
How do I properly trigger the ATMega328 reset pin via software so that the bootloader runs and the firmware can be updated via RX/TX pins?

I am programming my Atmega328P chip via a USB to TTL converter (https://www.amazon.com/gp/product/B075N82CDL/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1)

I am able to upload hex files via the command line and the Arduino IDE when I have the RTS pin of the adapter and a capacitor attached to the !RESET pin of the Atmega. (http://www.electronics-lab.com/wp-content/uploads/2018/09/programming-Uno-on-breadboard.png)

I am also able to upload via the command line when I have a push button attached to the !RESET pin and manually pull it low then begin uploading the firmware within a few moments. (https://cdn.instructables.com/F0L/2F6U/J7AQSHD1/F0L2F6UJ7AQSHD1.LARGE.jpg)

My problem is that for my application I will only have the TX/RX/Vcc/GND pins available (no RTS or push button) and need to reset the micro controller so the bootloader runs and listens to be programmed with updated firmware.

So far I have written a batch file that sends a command to restart the Arduino, and then calls avrdude to upload a hex file. I have tried two methods of restarting the micro controller. I have told it to go to memory location zero, and I have attached an IO pin to the reset and dropped it low (although it stays low until reset, so the reset doesn't really work until I manually remove the wire between the IO pin and the !RESET pin)

My sequence is as follows:

1. Have Arduino running code:
<!-- language-all: lang-cpp -->
```
    int recvByte;
    int delayS = 400;
    int resetPin = 9; //bttom right pin of uC

    void setup() {
      // put your setup code here, to run once:
    pinMode(txPin, OUTPUT);
    pinMode(rxPin, INPUT);
    pinMode(resetPin, OUTPUT);
    digitalWrite(resetPin, HIGH);
    Serial.begin(57600);
    Serial.write("Booted/reset");
    Serial.write("This setup was uploaded with batch");
    }

    void(* resetFunc) (void) = 0;

    void loop() {

    if (Serial.available() )
    {    // get incoming byte:
        recvByte = Serial.read();
        if (recvByte==int('r'))
        {
        Serial.write("resetting");
        delay(10); //wait for last message to send
        //digitalWrite(resetPin, LOW); //commented out because this method stays low until wire is removed
        resetFunc();
        Serial.write("should not see if reset properly");
        }

    }

    delay(100);
    }
```

2.I then run my batch file.
```
echo Running upload bat, sending reset command then calling avrdude
cd "C:\Program Files (x86)\Arduino\hardware\tools\avr\bin\"
python "path\sendR.py"
.\avrdude.exe -C"C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf" -v -patmega328p -carduino -PCOM6 -b57600 -D -Uflash:w:"path\Atmega328code.hex":i
```

The python sendR.py is to send the "r" character, which the Arduino views as the reset command.
```
import serial
ser = serial.Serial("COM6", baudrate=57600)  # open serial port
bytes = "r".encode()
ser.write(bytes)
ser.close()
print("End python script")
```

When I send "r" via Tera Term or python the setup code runs again, but I have not been able to upload with the `.\avrdude.exe -C"C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf" -v -patmega328p -carduino -PCOM6 -b57600 -D -Uflash:w:"path\Atmega328code.hex":i` command inside the batch file. If I use the pushbutton to do a hardware reset, this command works without issue.

How can I upload new firmware via the RX and TX pins using software to reset the microcontroller and listen for new code as the bootloader runs?

New ideas tried:
Use a uniform baud rate of 57600 in python and atmega serial setup. I chose this value because the Arduino IDE output this baudrate in `avrdude.exe -C"C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf" -v -patmega328p -carduino -PCOM6 -b57600 -D -Uflash:w:"path\Atmega328code.hex":i`
[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/Ok5rB.png

body:
You wrote:

> `void(* resetFunc) (void) = 0;`

This seems to me like an approach worth trying, except that the function
address is wrong. At address zero of the flash you have the start of the
user's code. The bootloader, if you do use one, lives at the end of the
flash. The start address of the bootloader depends on its size, and is
configured by setting some fuses on the chip. If you are using the
popular optiboot (the bootloader of the Uno), you have to jump to
exactly 512 bytes before the end of the flash, i.e.:

```c++
void (*resetFunc)(void) = 0x7e00;
```

Oh, wait... the flash is organized as 16-bit words, so you may have to
use the wordwise address instead:

```c++
void (*resetFunc)(void) = 0x3f00;
```

But do note that, unlike a real hardware reset, this approach does not
reset the peripherals to their normal initial state. You may want to do
it before jumping to the bootloader.

------------------------------------------------------------------------

**Edit**: I have disassembled a test program that does this kind of
call-by-pointer, then double checked the documentation of [the `icall`
instruction][icall]. It appears that the function address you provide is
indeed interpreted as a word-wise address, so you should write half the
byte-wise address. If you write anything larger than the size of the
flash (`0x4000` = 16 kilowords), the most significant bits get
lost, and the address gets reduced to the correct range modulo the flash
size.

That is, if `0x7800` worked for you, then presumably the correct address
is `0x3800`, i.e. 2 kilowords (4 KB) before the end of the
flash. This is quite a large bootloader, and the largest size supported
by the ATmega328P. Are you sure it is righ? Aren't you sliding through
some uninitialized flash before hitting the bootloader? Here is a table
that gives the bootloader's start address as a function of the amount of
memory reserved for it:

    reserved size  start address
        512 B         0x3f00
         1 KB         0x3e00
         2 KB         0x3c00
         4 KB         0x3800

Note that the Arduino Uno uses [optiboot][], which fits into the
smallest size that can be allocated to a bootloader (512 bytes).

[icall]: http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf#_OPENTOPIC_TOC_PROCESSING_d94e21480
[optiboot]: https://github.com/Optiboot/optiboot


message:
How to change the resolution of DS18B20?

I'm using [DS18B20][1] sensor with [this library][2], the 750ms delay is causing problem in timer part of my code. the code below is from DallasTemperature.cpp:

    // returns number of milliseconds to wait till conversion is complete (based on IC datasheet)
    int16_t DallasTemperature::millisToWaitForConversion(uint8_t bitResolution) {

     switch (bitResolution) {
     case 9:
      return 94;
     case 10:
      return 188;
     case 11:
      return 375;
     default:
      return 750;
     }

I'm reading the temperature like this:

    #include <OneWire.h>
    #include <DallasTemperature.h>
    #define ONE_WIRE_BUS A0
    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);

    void setup() {}

    void loop () {
     float currentTemp = sensors.getTempCByIndex(0);
     sensors.requestTemperatures();
    }

*sensor is not connected in parasite mode, and there is only one sensor.*

How can i change the resolution from 12 to 9 bit?

  [1]: https://datasheets.maximintegrated.com/en/ds/DS18B20.pdf
  [2]: https://github.com/milesburton/Arduino-Temperature-Control-Library

body:
Simple:

    sensors.setResolution(9);

It normally defaults to 9, but then probes the connected device to find the maximum resolution it supports and sets it to that. This would normally be done in `sensors.begin()` which you omitted from your snippet above. If you don't have that it will be on 9 bit anyway, and also the bus probably won't work regardless.


body:
Seems to work better:

    sensors.setResolution(tempDeviceAddress, TEMPERATURE_PRECISION);


message:
DS18B20 with only OneWire library

Peter Scargill [found a way][1] to use DS18B20 temperature sensor without any library and just using OneWire library, and it's amazing how blazing fast it is! *(it's an old article from 2013)*

    #include <OneWire.h>
    int16_t dallas(int x,byte start){
     OneWire ds(x);
     byte i;
     byte data[2];
     int16_t result;
     do{
      ds.reset();
      ds.write(0xCC);
      ds.write(0xBE);
      for (int i = 0; i < 2; i++) data[i] = ds.read();
      result=(data[1]<<8) |data[0];
      result>>=4; if (data[1]&128) result |=61440;
      if (data[0]&8) ++result;
      ds.reset();
      ds.write(0xCC);
      ds.write(0x44, 1);
      if (start) delay(1000);
     } while (start--);
     return result;
    }
    void setup (){
      dallas(A0,1);
    }
    void loop (){
      float currentTemp = dallas(A0,0);
    }

Problem is The accuracy, he converts float to int to get accuracy of 1 degree and it's working just fine.

How can i get accuracy of .5 (or .2?) degree using this semi library?

  [1]: https://www.scargill.net/reading-dallas-ds18b20-chips-quickly/

body:
Actually he isn't really converting `float` to `int`. He never uses `float` since he don't need it. The [datasheet][1] of the DS18B20 shows at page 6, how the data is formatted:

[![data structure][2]][2]

1. The 4 highest bits just resemble the sign bit 11.
2. The first digit with full degrees is bit 4. Every bit below that has values below 1°C

So the data bytes `0b1111100001010000` will represent a temperature of -123°C and `0b1111100001011000` -122.5°C.

The author from the link then shifts this data 4 bits to the right, so that all bits representing values under 1 vanish. You can convert the received value per hand to `float` by also using this.

    int16_t whole_degree = (result & 0x07FF) >> 4;
    float temperature = whole_degree + 0.5*((data[0]&0x8)>>3) + 0.25*((data[0]&0x4)>>2) + 0.125*((data[0]&0x2)>>1) + 0.625*(data[0]&0x1);
    if (data[1]&128) temperature*=-1;

As float does not have the same structure, as the data, we need to convert them. So I calculate first the number of whole degrees analog the your code. Then I add this up with the values of the lowest 4 bits. `((data[0]&0x8)>>3)` and it's siblings will be 1, when the corresponding bit is set, and 0, if not.

So you get the full precision of the sensor (12 bits). Please note, that for this to work, you should not configure the sensor to less resolution. In that case you would have to ignore the corresponding lowest bits. But the sensor is in 12 bit mode at power up anyway and your code does not configure it otherwise.

Note: I'm unsure about the line `result |=61440;` in the original code. This sets the 4 highest bits of a 16 bit value to 1. I don't see, why this should be correct here, since a normal 16bit integer does only have 1 sign bit. In my understanding the original code would lead to false readings (way off), when reading temperatures below zero. I instead simply multiplied the resulting temperature with `-1`.

The whole code would look like this (I also added the statement for printing out the pure received data as binary, as I requested it in my comment. These statements are currently commented out):

    #include <OneWire.h>
    float dallas(int x,byte start){
        OneWire ds(x);
        byte i;
        byte data[2];
        int16_t result;
        float temperature;
        do{
            ds.reset();
            ds.write(0xCC);
            ds.write(0xBE);
            for (int i = 0; i < 2; i++) data[i] = ds.read();
            result=(data[1]<<8) |data[0];
            // Here you could print out the received bytes as binary, as requested in my comment:
            // Serial.println(result, BIN);
            int16_t whole_degree = (result & 0x07FF) >> 4; // cut out sign bits and shift
            temperature = whole_degree + 0.5*((data[0]&0x8)>>3) + 0.25*((data[0]&0x4)>>2) + 0.125*((data[0]&0x2)>>1) + 0.625*(data[0]&0x1);
            if (data[1]&128) temperature*=-1;
            ds.reset();
            ds.write(0xCC);
            ds.write(0x44, 1);
            if (start) delay(1000);
        } while (start--);
        return temperature;
    }
    void setup{
      //Adding Serial.begin(9600); for printing the received bytes here
      //Serial.begin(9600);
      dallas(A0,1);
    }
    void loop{
      float currentTemp = dallas(A0,0);
    }

  [1]: https://datasheets.maximintegrated.com/en/ds/DS18B20.pdf
  [2]: https://i.stack.imgur.com/uboxl.png


body:
Why not rewrite the dallas() function so that it returns a float?

    #include <OneWire.h>

    OneWire ds(A0);

    float dallas(OneWire& ds, byte start = false) {
        int16_t temp;
        do {
            ds.reset();
            ds.write(0xCC);
            ds.write(0xBE);
            ds.read_bytes((uint8_t*) &temp, sizeof(temp));
            ds.reset();
            ds.write(0xCC);
            ds.write(0x44, 1);
            if (start) delay(1000);
        } while (start--);
        return (temp * 0.0625);
    }

    void setup {
      dallas(ds, true);
    }

    void loop {
      float currentTemp = dallas(ds);
    }


message:
Remove Function at Preprocessor Time

I have a single function for debugging messages, used through all the project. When `KEYDEBUG` is defined as `1` or `0`, the function is enabled or disabled as required.
<!-- language-all: lang-cpp -->

    #define KEYDEBUG 0

    void debugging(int var){
       #if KEYDEBUG
       //Assert
       #endif
    }

When checking the compiler, the variable `var` raises a warning `-Wunused-parameter`.
How should remove this warning just at this part of the project?
Or which other alternative for using debugging code and removing it from memory for production release?

body:
In your case you do not use the entire body, so you can use a macro.

This way the code when KEYDEBUG is 0, will be like the complete function would not exist (except for the void cast, see below).

    #include "assert.h"

    #define KEYDEBUG 0

    #ifndef KEYDEBUG
    #define debugging(x) void(x);
    #endif

    void debugging(int var){
       assert(var);
    }

    void setup() {
      // put your setup code here, to run once:
      debugging(1);
    }

---

The information below is for not using the function parameter, but keep the function (in case you have code in your function that also does something when KEYDEBUG is 0.

**Unused attribute**

The cleanest way I could find is using the unused attribute:

    #if KEYDEBUG
       void debugging(__attribute__((unused)) int var){
          //Assert
    #else
       void debugging(int var){
          //Assert
    #endif
       }

or if you prefer better readability:

    #if KEYDEBUG
       void debugging(__attribute__((unused)) int var){
          //Assert
       }
    #else
       void debugging(int var){
          //Assert
       }
    #endif

**Cast to void**

Less clean but does the job:

    void debugging(int var){
       #if KEYDEBUG
          //Assert
       #else
          (void) var; // prevent unused parameter warning
       #endif
    }

**Macros/Parameter**

It's not easy to remove the variable since it's used in a function and will be called from many places probably. You could maybe you use a macro but that gets messy soon.

This solution works, and afaik the compiler will optimize the code out (if not , it will cost very less anyway).


message:
Arduino Mega reading same information that it's sending out via serial

So I have an Arduino Mega and I'm attempting serial communication with another device, and I ran into this weird issue.

Let's say I use Serial1.write to send out hex A-F. If I read on that same port (Serial1, print out what I read on Serial0), **with NO wires plugged in the serial port**, I get a mirror of what I'm sending out in my read function. I've tested this theory on multiple serial ports, as well as different Megas.

How is this interference happening? Do I have an incorrect understanding of the serial buffers? What can I do to stop it? It's causing interference in communicating with my external device.

Here is a super short program to test this theory.

<!-- language-all: lang-cpp -->

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

    void loop()
    {
      char test[15];
      for (int i = 0; i < 15; i++)
        test[i] = i;

      for (int i = 0; i < 15; i++)
         Serial1.write(test[i]);

      while(Serial1.available() > 0 )
       {
        byte c = Serial1.read();
        Serial.print(' ');
        Serial.print(c, HEX);
      }
    }

**UPDATE:**  I came back the next day with my O-scope and the yellow line is the TX and the blue line is the RX. I was not getting the crosstalk anymore in the Serial port, but on the scope shows the RX line was only being effected about 250mV in perfect unison to the TX. I tried connecting everything back up the same way but I was not able to replicate the issue. Somehow whatever I had going on when I posted this was causing the RX line to be affected great enough for the Mega to pick up on it over serial. For now I'm just blaming it on escaped aliens from Area 51 :)

[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/kGHWw.png

body:
I ran a slightly modified version of your test code on a Mega 2560 and got no echo at all;  Unless I totally misunderstood your problem description, there must be something else going on.  Here's the code I ran:
<!-- language-all: lang-cpp -->

    char test[15];

    void setup()
    {
     Serial.begin(9600);
     Serial1.begin(115200);
     for (int i = 0; i < 15; i++)
     {
      //Serial.print(i);
      test[i] = i;
      Serial.print(test[i],HEX);
     }
     Serial.println();

     for (size_t j = 0; j < 15; j++)
     {
      Serial.print("test["); Serial.print(j);
      Serial.print("] = ");Serial.println(test[j],HEX);
     }
    }

    void loop()
    {
     for (int i = 0; i < 15; i++)
     {
      Serial1.write(test[i]);
     }

     Serial.println(Serial1.available());

     while (Serial1.available() > 0)
     {
      byte c = Serial1.read();
      Serial.print(' ');
      Serial.print(c, HEX);
     }
    }

And here's a bit of the output seen on Serial0:

    Opening port
    Port open
    VMDPV_1|1_�Se�
    0123456789ABCDE
    test[0] = 0
    test[1] = 1
    test[2] = 2
    test[3] = 3
    test[4] = 4
    test[5] = 5
    test[6] = 6
    test[7] = 7
    test[8] = 8
    test[9] = 9
    test[10] = A
    test[11] = B
    test[12] = C
    test[13] = D
    test[14] = E
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0
    0

As you can see, the Serial1 read buffer was always empty.

Did I misunderstand something you said?


message:
Making a PID Controller for BAR 30 pressure sensor

I am having issues with my PID controller  for a BAR 30 depth sensor. The issue that I have is my ESC have two initial start up { 1500 - 1900} is min - max respectively clockwise and { 1500-1900} is max respectively counter clockwise.
What I want is for me to set a depth and I can submerge to a certain depth and lock in at that certain depth.

    #include <PID_v1.h>
    #include <MS5837.h>
    #include <Wire.h>
    #include <Servo.h>
    MS5837 sensor;
    Servo vertical_thruster1;

    // Variables

    float current_depth ;
    float set_depth = 0.50 ; //  depth u wish to go in meters
    float PID_error = 0;
    float previous_error = 0;
    float elapsedTime,  Time , timePrev;
    double pwmvertical_thruster1 = 1440;

    int s;

    float PID_value = 0;
    float PID_p = 0;
    float PID_d = 0;
    float PID_i = 0;
    //PID constants
    float kp = 100;
    float ki = 0.003;
    float kd = 5.2;

    void setup() {
      Serial.begin(9600);
     vertical_thruster1.attach(4);
       vertical_thruster1.writeMicroseconds(1500);

     Time = millis ();

     ///Bar 30 Configuration

      Serial.println("Starting");
      Wire.begin();
     while (!sensor.init()) {
    Serial.println("Init failed!");
    Serial.println("Are SDA/SCL connected correctly?");
    Serial.println("Blue Robotics Bar30: White=SDA, Green=SCL");
    Serial.println("\n\n\n");
    delay(2000);
      }
      sensor.setModel(MS5837::MS5837_30BA);
      sensor.setFluidDensity(997); // kg/m^3 (freshwater, 1029 for seawater)
    }

    void loop() {

    ///*
    // First read the current value of the depth sensor
    sensor.read();
    current_depth = sensor.depth();

    timePrev = Time;
    Time= millis();
    elapsedTime = ( Time - timePrev) / 1000;

    // calculate the error between the set depth and current depth
     PID_error =  set_depth - current_depth ;

     // Calculate the P Value
     PID_p = kp * PID_error;
       Serial.print("PID_p: ");
        Serial.print(PID_p);
        Serial. println ( "\t\t");
    // Calculate the i value in a range on +-0.3

     if (-0.2 < PID_error < 0.2)
     {
      PID_i = PID_i + (ki * PID_error);
     }
    Serial.print("PID_i: ");
    Serial.print(PID_i);
    Serial. println ( "\t\t");
    // Calculate the d value
     PID_d = kd*((PID_error - previous_error)/elapsedTime);
    Serial.print("PID_d: ");
    Serial.print(PID_d);
    Serial. println ( "\t\t");
    // The total PID value
    PID_value = (PID_p + PID_i + PID_d) ;

    // range for the blue robotics esc

    if ( PID_value < -150)
     {
     PID_value = -150;
      }
      if( PID_value >150)
      {
      PID_value = 150;

      }
      Serial.print("PID_value: ");
      Serial.print(PID_value);
      Serial. println ( "\t\t");
     // calcualte the pwm

     s =  (pwmvertical_thruster1 + PID_value  );
     if(s < 1350)
    {
     s= 1450;

    }
    else if(s> 1650)
    {
      s=1550;

    }
      Serial.print("Depth: ");
      Serial.print(sensor.depth());
      Serial.println(" m");
      Serial.print ( "Speed s  ");
      vertical_thruster1.writeMicroseconds(s);
      Serial.print( s) ;
      Serial. println ( "\t\t");
      previous_error = PID_error;
      //  */
      delay(300);
     }

body:
A PID controller should be a good match for your application, but it appears that your code doesn't take advantage of the PID_v1 library at all; a PID_v1 object is never declared, and it appears you are attempting to manually compute what the PID library is designed to do for you automatically.

I would recommend you 'start slow and simple' by learning how to use a PID controller in its most basic form.  The PID library has a very basic example, which I have modified slightly to demonstrate how a PID controller works.  I tested this example with a UNO, a potentiometer (variable resistor) and a capacitor. The resistor and capacitor values aren't critical - I used the first things I found in my parts box.  The output on Pin 3 is a PWM pulse train signal, and the resistor/capacitor combination filters this pulse train to a variable level analog signal, which the PID controller sees as the analog 'Input' on A5.

 Once you have this running, you can vary the pot value to see how the PID changes the output value in order to achieve the setpoint value on the input, and you can vary the setpoint and PID parameters to play around with different configurations.  Once you are comfortable with basic PID operation, you should then be able to configure it properly for your application.

Hope this helps,

    #include <PID.h>

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

    //Specify the links and initial tuning parameters
    PID myPID(&Input, &Output, &Setpoint, 2, 5, 1, DIRECT);

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

     //initialize the variables we're linked to
     //Input = analogRead(0);
     Input = analogRead(A5);  //I used A5 as A0 was unavailable
     Setpoint = 100;

     //turn the PID on
     myPID.SetMode(AUTOMATIC);
    }

    void loop()
    {
     //Input = analogRead(0);
     Input = analogRead(A5); //I used A5 as A0 was unavailable
     myPID.Compute();
     analogWrite(3, Output);
     Serial.print("Input = "); Serial.print(Input); Serial.print(", Output = "); Serial.println(Output);
     delay(100);

    }

[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/QQfT2.jpg


message:
HardwareSerial Indexing Array

How should I index HardwareSerial ports into a single array?.

This compiles, but do not work.

    HardwareSerial Serials[]={Serial,Serial1,Serial2,Serial3};

    void setup(){
        for (int i=0;i<=3;i++){
            Serials[i].begin(38400);
            while (!Serials[i]);
        }
    }

    char s;
    void loop(){
        for (int i=0;i<=3;i++){
            if (Serials[i].available()){
                s=Serials[i].read();
                Serials[i].write(s);
            }
        }
    }

body:
your code makes copies of Serials into items in the array of HardwareSerials. To use the original Serial objects, store and use pointers.

    HardwareSerial* Serials[]={&Serial,&Serial1,&Serial2,&Serial3};

    void setup(){
        for (int i=0;i<=3;i++){
            Serials[i]->begin(38400);
            while (!*Serials[i]);
        }
    }

    void loop(){
        for (int i=0;i<=3;i++){
            if (Serials[i]->available()){
                char s=Serials[i]->read();
                Serials[i]->write(s);
            }
        }
    }


message:
Code that worked in Uno is not working in Mega 2560

I send data with Android and read it from the Arduino serial screen. When I use UNO, I can read the data smoothly. When I use MEGA, it uploads the code without error, but does not transfer data on the serial screen. Can you tell me why?

```
#include <SoftwareSerial.h>

SoftwareSerial bluetooth(2,3);    // TX,RX
int bar_analog=0;
int head_analog=0;
int bar_anim=0;
int strip_anim=0;
int motor_speed=1;
int direct=0;
int level=0;
boolean debug = true;

void setup() {
  Serial.begin(9600);
  bluetooth.begin(9600);
  Serial.println("Program is starting...");
  Serial.println("by Berke Ogulcan Parlak");
}

void loop() {
  if (bluetooth.available()) {
    while (bluetooth.available())
    {
      bar_analog = bluetooth.parseInt();
      head_analog = bluetooth.parseInt();
      bar_anim = bluetooth.parseInt();
      strip_anim = bluetooth.parseInt();
      motor_speed = bluetooth.parseInt();
      direct = bluetooth.parseInt();
      level = bluetooth.parseInt();
      if (debug) {
        Serial.print("Bar Brightness: ");
        Serial.println(bar_analog);
        Serial.print("Bar Animation Type: ");
        Serial.println(bar_anim);
        Serial.print("Headlight Brightness: ");
        Serial.println(head_analog);
        Serial.print("Strip Animation Type: ");
        Serial.println(strip_anim);
        Serial.print("Motor Speed Level: ");
        Serial.println(motor_speed);
        Serial.print("Direction: ");
        Serial.println(direct);
        Serial.print("Mast Goes: ");
        Serial.println(level);
        Serial.println("--------------------------------");
      }
      if (bluetooth.read() == '\n') {
        azdırma işlemleri bu satırda yapılacak..

      }
    }
  }

}
```

body:
SoftwareSerial relies on the Pin Change interrupt. Not all pins on the Mega have pin change interrupts.

But that is all a moot point really, because when you're using a microcontroller that has lots of *real hardware UARTs* there is no call to be using SoftwareSerial in any case.


message:
i2c Connection for MCP4725(Dac) with Esp8266 wemos d1 mini

------------ *This question has been edited* ------------

*note*: Dac and Adc is12bits

my problem : I use two ESP. Using esp1, I read the Adc amount of the alternating signal (ECG) and send it to esp2 with UDP and I get it. Now, using the same amount of Adc, I would use the MCP4725 to convert the digital value of the Adc to the analog. But I don't know how to do it !

- Do you need sine lookup table like default library example again ??!

- If so, how is it done?!

- I wrote the following code right now, what is your opinion?
Explain to me if my code is in error.

I just want the DAC output, to be the ADC signal input.

*Code*:

    void loop () {

      int noBytes = Udp.parsePacket();
      String received_command = "";

      if ( noBytes ) {
        Udp.read(packetBuffer,noBytes);

        for (int i=1;i<=noBytes;i++)
        {
          received_command += char(packetBuffer[i - 1]);
        }
        int dac_value ;
        dac_value = received_command.toInt();
        Serial.print("dac value: ");Serial.println(dac_value);
        aPin = dac_value ;
        if (!si.i2c_start((I2C_7BITADDR<<1)|I2C_WRITE)) {
          Serial.println("I2C device busy");
          return;
        }

        else{
          Serial.println("i2c is worked");
        }

        for (byte i=1; i<noBytes; i++){
          si.i2c_write(aPin);
          si.i2c_rep_start((I2C_7BITADDR<<1)|I2C_READ);
          si.i2c_stop();
          delay(50);
        }
      }
    }

--------------------------------------

I use `#include <SlowSoftI2CMaster.h>`.

***si*** is: `SlowSoftI2CMaster si = SlowSoftI2CMaster(4, 5, true);`

Photo:
[![enter image description here][1]][1]

  [1]: https://i.stack.imgur.com/dZ1Rd.jpg

body:
Ok, I will explain the basic principles and give some tips. This won't be about your code, since it is neither compilable, nor does it make much of a sense to me.

1. **The I2C Protocol:** An I2C connection always needs 2 lines, SDA (which carries the data) and SCL (where the master outputs the clock signal). The communication always get's started by the master with a START CONDITION. Then it transmits the first byte, which consists of the 7 bits long address of the slave device and one bit, that shows if a read or a write operation will be performed. The slave - if there is any with that address - will then respond with an Acknowledgement. The master will transmit it's data and end the transmission with a STOP CONDITION or start a new transmission with a repeated start condition.

2. **Choose the I2C library:** You are using the [SlowSoftI2CMaster][1] library because it is architecture independent. As you are a beginner, you should use the [SlowSoftWire][2] library, which is a `Wire`-like wrapper library. It gives you the same interface, as the `Wire` library. That is good for beginners, since this hides some of the complexity and most examples and tutorials use the `Wire` library (so you can often copy the code structure). You have to install both libraries (`SlowSoftI2CMaster` and  `SlowSoftWire`) in your libraries folder, but you only need to include the `SlowSoftWire` library. Please look at the examples, that come with that library. I will refer to that library in the following points.

3. **Using the `SlowSoftWire` library:** You can declare and initialize the library as in it's `simpleSlowWire.ino` example. For transmitting a new value to the DAC, you have to first use `beginTransmission()` to configure the library for a master write transaction. Then place the data bytes in the libraries buffer with `write()`. And finally do the transmission with `endTransmission()` (this is the only place during this process, where the real I2C action happens on the bus). When you begin the transmission with `beginTransmission()` you must provide the correct address of the DAC. This is meant without the direction bit. The address of the MCP4725 consists of the device code `1100`, the hardwired address pins A1 and A2, and the variable address pin A0. The hardwired address pins are most likely both zero, unless the manufacturer was ordered to program it otherwise (You can check the address with the scanner example). So, if you wire A0 to ground, the address will be `0b1100000`. If you wire A0 to 3.3V, it will be `0b1100001`. The direction bit will be handled by the library - you don't have to worry about it.

4.**The MCP's data protocol:** You cannot simply send the values from the ADC to the DAC. It except's a special data format, which includes command bits to determine it's mode of operation. I think, I have already described how the data is build up in principle and code pretty well in my answer to [this question][3]. If there is something special, that you don't understand, you can ask a new question and refer to that answer in it. Also I think, you should use the type `unsigned int` for the `dac_value`, since values from an ADC and values for a DAC both are positive only.

Please keep in mind, that building such projects needs some time investment, until you understand, what actually is happening there. If you use any chip, the datasheet of that chip is always a must read. I personally never haven't worked with the MCP4725. I just have read the datasheet. All information is already there.

  [1]: https://github.com/felias-fogg/SlowSoftI2CMaster
  [2]: https://github.com/felias-fogg/SlowSoftWire
  [3]: https://arduino.stackexchange.com/questions/67043/software-i2c-sending-data/67044#67044