# Question
Title: Generate a true analog signal using Arduino
I am looking for a way to create a true analog output with the arduino uno. I am constantly reading an analog input on a0 pin, all i want to do is send the same signal as output. I know arduino convert the signal into pwm so have can i convert it back to true analog signal.I have a dac too but not getting proper output.

secondly, i want to send same signal by converting it into bits through Ethernet so how do i send and receive the signal.

here is my code for dac.

```
#include "Wire.h"
#include "MCP4725.h"
MCP4725 MCP(0x60);
uint32_t microphonePin=A0;
uint32_t threshold=800;
const int ledPin=13;

void setup() {
    Serial.begin(115200);
    pinMode (ledPin, OUTPUT);
    Serial.print("MCP4725 test program: ");
    Serial.println(MCP4725_VERSION);
    if (MCP.begin() == false)
     {
       Serial.println("Could not find sensor");
     }

    MCP.begin();
 }

void loop() {
   uint32_t sensorValue=analogRead(microphonePin);
   MCP.writeDAC(sensorValue);
   Serial.println(MCP.getValue());
   if (MCP.getValue()>threshold)
    {
      digitalWrite (ledPin, HIGH);
    }
   else{ digitalWrite(ledPin, LOW); }

  }

```

here is my circuit for audio amplifier

and for the speaker it is connected on DAC out.

FYI:I am able to read the data on my serial monitor form mic and i am also able to so do some operation by just using mic and GUi. I just want to here what i am saying on speaker.

# Answer
> 4 votes
I see that MCP4725 uses Wire library with the default clock of 100,000 kb/sec.

At a rough estimation each call to MCP.writeDAC or MCP.getValue will be at least 32 bits long and you use three of them in each loop.

This one:

```
   Serial.println(MCP.getValue());
   if (MCP.getValue()>threshold)

```

is redundant, you should store the value in a temporary variable and use-it in both "print" and "if".

With 10us for each bit that means 1060 us for each loop. The analog read also takes 100us to complete. Over all 1160us minimum. Is the MCP.getValue() really needed?

That means that your maximum sample frequency is 860hz and the maximum bandwidth of 430hz. I doubt that this is an acceptable bandwidth for a microphone.

Even so, the output signal will not look similar at all, you need a higher bandwidth or to limit, if possible, the bandwidth of the input signal.

In some limits you can modify the MCP4725 library to use fast wire clock four times faster if it suits your requirements. If you also drop the two MCP.getValue() calls that will be again almost three times faster, up to 5khz.

Also you might search for faster ADC on Arduino.

Update after OP microphone amplifier schematic.

The ADC works only with positive voltages. Short the output capacitor of the amplifier!

# Answer
> 2 votes
**If you want something simpler than the transistor version you can use the following as well, for the other options skip to the --here-- mark**

Oldstyle analog out. this works like a vacuum tube and while I use a LDR you can also use heat or a actual vacuum tube.

You Will Need:

1. A low resistance LDR or multiple in parallel.
2. A cardboard box or other box to isolate it from outside interfearance.
3. A Led or light bulb.

How this works: while a led flashes, a LDR needs a certain time to just to values(often up to around a few ms), so this will stabilize your adc signal.

You send the desired amplitude as a pwm signal to the light source(you probably want to invert your pwm signal) which aims at the LDR. you send your sound frequency through the LDR which now works as a variable resistor.

!!Use low resistance LDR's and a bright light source to get a as low as possible resistance. with (weak)lasers, you can get a normal LDR down to around 1 to 0 ohm. but you will most likely use a led since that has more precise intensity control.

Another simple method is the inversed of analog read in an Arduino. you basically use multiple output ports with different resistances to get a different output when done right in this case you can get around 257 different volume levels with 8 pins for the amplitude and 1 for the frequency.

**--here--**

--added this here as a simple explaination/guide-- first start with getting your microphone working, see if analogread get's some high values. if it stays at 0, 1 or another low value, then you didn't include a transistor with your microphone to boost the signal.

-For your output start with a project without a microphone to see if it is working right. you will need to use 2 pins to power your output(excluding ground, assuming single-channel audio). -the first one you will need for your frequency signal output. the other one is for the amplitude/volume/gain. -We will use any type of amplifier(transistor) to merge the signals, in this case, I assume a transistor since they are cheap, simple low power, have an easy dynamic range and you most likely have them already.

-this following part can be done in 2 ways I would suggest to try way 1 first since it is most simple, logic, and fast which is great on a slow which is great in a small microprocesssor. where method 2 might seem the exact different way around but is much more precise.

Method 1: connect the frequency output pin to the emmitor pin of the transistor where the + normally goes in. Connect the amplitude output pin to the base pin of transistor(the trigger) add a very small capacitor(or a bigger one for tests) between the base and ground this is to convert the adc in analog voltage instead of pulses. the collector of the transistor which you would normally connect to ground is your output. you might want to add a small resistor after it especially if you are using it for a audio cable. you can also directly connect a very small speaker to hear the sound for a cable(be careful withconnection arduino IO to things like a pc) you connect the output as oudio signal and the ground as ground. but check what voltage the other devices audio port supports since arduino's IO pins generate 5v

method 2. connect the frequency out pin to the base of the transistor, connect the ADC of the amplitude pin to the emitter pin of the transistor, connect a capacitor of larger capacity than described in method 1 between the emitter pin of the transistor and the ground of the Arduino. the collector is again your output, you might to as a resistor to it. connect a wire from an analog port to the emitter pin of the transistor to read out the voltage in the capacitor for precise voltage regulation.

tinker with the values of the capacitor size. (you now have an energy pool in front of the transistor if you know the ampere on which you are outputting you can use this to regulate the pool, otherwise you can read it using the analog feedback loop). important to know is that if you want precise volume you use a larger capacitor, if you want fast volume differences you use a small one and intentionally use more pins to charge it. for an Arduino Uno due to low analog read speeds, I would recommend a larger capacitor or this.

extra stuff when putting your complete system together you might run into speed issues. you should therefor connect the microphone to both a digital and a analog pin. the digital pin constantly monitors the frequency and the analog pin measures the amplitude sometimes(add a small capacitor get that average amplitude). I would also recommend turning down the analog read precision to prevent checking for all 1024 possible voltages.

for method one you can also add a extra resistor from base to ground and from the amplitude pin to base so you can more precisely calculate the voltages.

**--end of simple version--**

You can try to use 2 pins for the output signal. one of them sends the frequency digital(3 pins if you also want negative polarity audio). this output signal should go to something like a transistor or a digitally controlled potentiometer or amplifier. I will assume you use a transistor since those are most common and quite fast. the first digital output pin should go to the emitter pin of the transistor the second pin is used for the volume and will go to the base of the transistor. you might want to add a very small capacitor between the base and ground to reduce frequency interference(to prevent the ADC frequency from showing up in your signal). the Collector pin would be your analog output suitable for audio.

So in basic steps:

1. split the signal into a digital frequency and volume. (the digital frequency can be made by seeing a signal above a certain value as high and the other as low, this works best when you use both the positive and the negative side of the soundwave otherwise you will need to chose a very low number)(the analog frequency is literally your analog value for the positive only audio, and value-512 (\*-1 for negative numbers to get only positive numbers) for the full audio if you include the negative audio)
2. Send the frequency signal to the emitter pin of your diode.
3. Send the amplitude signal to the base pin of your diode.
4. Connect a small capacitance between the ground and the amplitude signal.

however What Dorian said are things you might want to keep track of as well since they often indeed tend to kill of such projects because you very easily run into speed limits(analog read in a arduino ar basically 1024 digital reads(literally)).

So some tips for your cirquit:

1. If your microphone doesn't have a transistor connected to boost the signal add it since otherwise the analog port of the arduino uno is not sensitive enough to measure the signal. you can and should fist test this using a project where you constantly analogread and print it. you can add a small capacitor between the analog port and the ground to just measure the voltage.
2. use diodes to rectify your microphone signal, your arduino can only read positive voltage, the microphone also sends negative voltage. redirect the negative voltage to the arduino ground (you can invert the negative voltage using a transistor or some other methods to read the negative voltages as well, but I would recommend just sending the negative signals to ground since this would give the near full range as well)
3. use 2 microphones one for frequency and one for amplitude. or connect the output of your microphone to both a analog and a digital port. you might in the last case want to use resistors to lower the current going to them this makes sure both get a accurate voltage.
4. avoid as manny analog reads as possible, storing it is better than calling it twice
5. use c/c++ bitmanipulations for IO, not only is it more easy to program larger systems when using them, they are also a lot faster( arduino uno has the PORTB, PORTD, PIND, PINB, DDRD, DDRB, and the a and c version(however you most often only use the D and B) predefined. bitmanipulations require very little knowledge compared to other programming methods as long as you know the port addresses, which again for the arduino uno are predefined search: arduino uno bit manipulations or arduino uno PORTB.
6. you can sample the sound frequency using a digital port at a higher frequency than the amplitude. since sound often doesn't jump to fast in amplitude in a way that you would clearly notice. this means you could read the sound with a IO pin and write it on another IO pin, additionally you could once every interval measure the amplitude to use which makes your code a lot faster.

there are way more ways but these are easy to do. for sending it trough internet however you need to be careful that the module you use processes those things itself so that you do not just connect a internet port since that would slow your system down even more.

For those wanting a ms paint sketch:

version one:

version two:

note that I just used random images from the internet you can use any capacitor and transistor that works for this, I did not check if this transistor is right for this, but it had a nice layout description in the image. the capacitor doesn't need to be ceramic, but this way you see clear legs and I don't need to focus on polarity. in general, all cheap 5v compatible transistors should work and all capacitors if they are not way too big or too small for your load.

I used descriptions rather than logos, so anyone should be able to read it as long as they have software to tell the differences in colour if they are colourblind.

**How it works** *The transistor sends the voltage from the emittor to the collector(or the other way around based on the transistor you use). so in method 2 which also works for mosfets. we send a adc signal to the capacitor to charge it to a voltage, you should however also add a resistor to ground or a cable to a analog port, because otherwise the voltage can just build up to 5v. this capacitor which we charge becomes a analog power source. we connect it to the emmitor(or pin which you normally connect on the + side). so if we where to open up the transistor(close the cirquit) by putting a positive voltage on the base or trigger pin then you would get a output of the voltage that you put into it. so if you play the frequency digital on the base completely opening and closing the transistor then you get a voltage output similar to the voltage in the capacitor. method one works more difficult but a transistor opens up relative to the current going from base to exit, so we use the pwm and a small capacitor to get a analog voltage on it only partly opening it, then we send the digital audio signal into the pin that you normally connect to 5v and you get that frequency payed with the transistor acting as a variable resistor* So method one uses a transistor as a variable resistor And method two uses the transistor or fet as a switch which uses the voltage build up in the capacitor, doesn't actually need to use pwm if you use a feedback loop.

# Answer
> 1 votes
for your case(**audio**) there also is https://github.com/connornishijima/arduino-volume1 or the volume library to install it you can use the git to get the files, or if you use the arduino ide, you can open the arduino ide and in the software go to helptools(4thoptionoftopmenubar)-\>Manage Libraries-\> {type volume in the search bar}-\> install the library called volume. you can also chose volume 2 or volume 3, see the git for the differences.

this however still uses micro pwm, so it is not true analog, but for audio it works. also note that on low volume the audio will be affected. I recommend only using the volumes between 100 and 255.

this method requires no additional hardware, and works well for audio, to send the audio to other devices however I would just send the audio values and not the audio output.

NOT TRUE ANALOG, but it solves your problem, the methods I described in my other answer will work well for most other analog cases, or even adding a small capacitor at that ma output might work in many cases. however since audio needs the voltage to change really fast this method works well, also since the volume is read by your mind instead of a digital device it has a normalization filter built in and a low sampling speed as well as sensitivity to only low frequency(how human brains and ears work) which will make the volume sound natural.

If you have a separate arduino for the volume or a well optimized code you can also avoid interrupts to get a higher frequency, this method is harder and requires you to know what your code does but allows for better quality volume(speciffically at low volume levels)

**alternatively you can use a shiftregister** and connect resisters to the outputs, for example 12800, 6400,3200,1600,800,400,200,100. like a bit but reversed, since the audio gets louder with a lower resistance. you can use other values, just don't make them to low, since arduino outputs 5v and 3.3v, both are much higher than your average headphone connection, also turning on multiple parallel resistors at once gives a lower resistance. for example if we turn on the 100 ohm and the 200 ohm resistor we get a output of around 66,66666666 ohm since the output is 1/((1/Resistor1)+(1/Resistor2)+(1/ResistorETC) like this a singe 8 bit shift register can deliver 256 different volume levels as true analog. if you have ports free on your ardruino you can also use those instead of a shift register, however be sure to use bitmanipulations and not digitalwrite, since the later one is slow. 1 pin = 2 volume levels 2 pin = 4 volume levels 3 pin = 8 volume levels 4 pin = 16 volume levels 5 pin = 32 volume levels 6 pin = 64 volume levels 7 pin = 128 volume levels 8 pin = 256 volume levels etc. this method can give true analog voltage if you know the resistance at the output, a speaker however differs in resistance based on many factors, but doing this will still give you good volume control like actual analog voltage, even though it is actually more analog amperage. to get voltage content the terminal connected to all the outputs of the resistors to another resistor to generate a voltage divider, this works for things like vga displays, however for things like audio, lights, etc. you should jus directly take the output of the resistors

---
Tags: arduino-uno, arduino-ide, audio, code-optimization, analog
---


# Question
Title: Connect 4 HC-12 transmitters to 1 HC-12 receiver
I am currently receiving data from HC-12 modules via USB-TTL that are working in pair . But I want to receive data simultaneously from 4 Hc-12 modules to a single HC-12 module via USB-TTL.

# Answer
> 1 votes
When a HC-12 is transmiting all other HC-12 in his range (using same frequency) are receiving. So if you want your transmiter to talk to one specific HC-12 then to an other and so on, you have to create a kind of "message protocol".

Let's say you have an Arduino with a HC-12 and 4 buttons and want to turn on-off 4 lights, each connected to a HC-12. You can use a binary representation, so a byte, on which each bit as a meaning.

Bit 0 -\> at 1 -\> turn on the light at 0 turn off

Bit 1-2 -\> give the number of the HC-12

So 00000111 -\> message for HC12 number 4, tell it to turn on the light. ALL HC-12 will receive the message. So each has to check the incoming byte to see if "it's for me" or nor. If you want one HC-12 to receive from many HC-12, that's the same: the message must contain the "id" of "who is sending".

# Answer
> 1 votes
The problem with multiple transmitter mostly resides in the collision risks. On networking contexts like Ethernet, There is a collision detection protocol making transceiver know that a problem arises, but that doesn't exist with HC-12, so you need something else.

In air contexts like this one, another solutions might to minimize chances of collisions restraining onself to a low bandwidth percentage (e.g.: not more that 10% of the total time) and just ignore lost packets.

However, if you cannot ignore lost packets, you need to implement a synchronisation protocol between receiver and transmitters. A solution would be to make some kind of token bus, where your receiver would poll each transmitter each on his turn to see if it has something to send.

However, since it is not recommended (and sometimes not even legal) to use to much time slices, you should avoid continuously polling all the transmitters.

In this case, what I suggest is that each transmitter can "wake up" the receiver by sending an unattended message. If this doesn't not cause reaction, this is interpreted as a collision detection. Then the transmitter wait for a specific delay (each one having a different delay value) - or a random delay.

When the receiver receives this packet it processes it, Then polls all the other transmitters, and then goes back to sleep mode, until the next time.

If the packets are long it might be better to have a short wake-up packet and to send the real data during the polling phase, and if the packets are short, you can just use the collision avoidance mechanisme alone.

---
Tags: hc-12
---


# Question
Title: What are examples of large Arduino code bases and how are they organized?
I'd like to find out:

* how big can an Arduino project get, is there some limit?
* are there examples of large open source code bases? I did some research but find only example projects with single .ino file. Are there projects with multiple files e.g. functions, constants in separate files say to avoid a 10K+ .ino file?

# Answer
Big projects are likely not developed with Arduino IDE. Arduino IDE was make for designers/inventors, not for programmers.

> Arduino was born at the Ivrea Interaction Design Institute as an easy tool for fast prototyping, aimed at students without a background in electronics and programming.

Source

Programmers will use a fully-fledged IDE which has many features a programmer needs on a daily basis, such as:

* handling multiple files efficiently
* allowing to create libraries instead of just `setup()` and `loop()`
* code completion (suggestions as you type)
* debugging (inspection and changing of variables at runtime)
* refactoring (modifying the structure of your code without changing the behavior)
* integrated version control (like Git / Github)

Such an IDE could be Eclipse with an Arduino Plugin or Atmel Studio and perhaps Visual Studio.

So, what do you need to look for? Don't look for `.ino` files. Instead, look for `.h` and `.cpp` code, just like other non-Arduino C++ code.

Some examples:
> 1 votes

# Answer
Again im late to the party...

If you are planning on making a larger project and splitting things up you can take advantage of libraries. This will work even if you are married to the arduino ide for some reason. if your not married to the arudino ide platformio doesn't suck too bad, and makes libraries a bit less messy when your doing the grunt work of setting them up the first time.

The idea should be to break your problem into smaller testable pieces of code into smaller testable libraries. If your code doesn't depend on arduino features you may be able to use test your library fully on a bigger machine to make sure there are no bugs (for example abuse clangs static analysis tool to see if you made any dumb pointer errors https://clang-analyzer.llvm.org/)

I kinda set an example of this (https://gitlab.com/mikealger/ExampleArduinoProjectStructure) up for students a while back but i still think its handy for anyone looking to build /manage the lifecycle of a project, I still use the basic ideas when i'm doing one off small projects based on others work to keep my notes straight i.e. https://gitlab.com/mikealger/celstronhomebrewgps

yea its probably shameless promotion but i haven't logged in for like 2 years...
> 1 votes

# Answer
Each sketch uses Flash memory, you can see this when you compile your project. You also can see how much percentually you have used.

And as jsotola explains, libraries are examples how multiple files can be used.

However, next to you .ino scene (in the same folder) you can put .h, .c and .cpp files which are automatically compiled (when used by the .ino file). However, if you use too many files, because tabs are placed horizontally in the Arduino IDE, it's better to use a decent editor. And while doing that, you use the Arduino IDE to compile (only).
> 0 votes

# Answer
Thats an example how to organize by function groups.
Other good complex examples can be found when searching for
`Arduino esp8266 webserver site:github.com`
The limit is basically your IDE -If you use ArduinoIDE the limit is (without already tested and working lib files) around 20 files, more is a pain in the a\** to handle.
I keep the length of my files between 500 - max 1000 lines. For documentation and keeping relationship diagrams (valuable for debug) I use doxygen with the graph extension.
When using an IDE like eclipse you can use more files, you have a good overview over your classes, but time to spend (and learn) configuring a project is initially much higher and there are sometimes (release dependent) breaking changes in the tool chain.
> 0 votes

---
Tags: code-review, project
---


title: Sunfounder IR remote controller issue

text:
# Question
Title: Sunfounder IR remote controller issue
I've been making a hoverboard using arduino, tinkercad and c++ (pic included). When I wired it up irl, I wired it exactly as I did in the picture (arduino UNO)

However, when I tested it out, it didn't work. The IR sensor got signal from my Sunfounder IR remote, but the fans didn't turn like I expected it to. The entire thing works fine with tinkercad.

I'm really sure it's not my wiring, since I took extra extra care to wire it properly. This leads me to believe that it's a problem with my remote code

The IR remote control used was a random one in tinkercad. I'm using sunfounder ir remote irl. Starting line 37, I've put code that uses the remote in the tinkercad to control the motors.

Is it possible that I need to recode specifically with the cases of the sunfounder IR remote? If so, where can I find a list of what buttons are what cases/code. so that I can rewire the entire thing?

I hope you all can help me. Thank you! :)

# Answer
> 2 votes
You're saying that your remote is SunFounder's so I assume this is the one?

If it is then this should be the equivalent codes:

Try if it works for you.

---
Tags: arduino-uno, remote-control
---


title: Average of 10 readings, wrong

text:
# Question
Title: Average of 10 readings, wrong
I am reading from loadcell and calculating the average of last 10 readings. But when the load cell reads something more than 3800 g the average gets negative, how? The mass I read are not negative numbers. I have been trying to find my mistake but I am not able to. Any help?

```
#include "HX711.h"

const int numReadings = 10;
const int LOADCELL_DOUT_PIN = 8;
const int LOADCELL_SCK_PIN = 10;
int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average
int mass  =0;
long reading = 0;

HX711 scale;

float a = 0.0088;
float b = 2009.7;

void setup() {
  // initialize serial communication with computer:
  Serial.begin(9600);
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
  scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
}

void loop() {
  if (scale.is_ready()) {
    // read from the sensor:
    reading = scale.read();
    // convert to mass
    mass = int((a*reading)-b);
    // subtract the last reading:
    total = total - readings[readIndex];

    Serial.print(int((a*reading)-b));
    readings[readIndex] = mass;
    // add the reading to the total:
    total = total + readings[readIndex];
    // advance to the next position in the array:
    readIndex = readIndex + 1;

    // if we're at the end of the array...
    if (readIndex >= numReadings) {
      // ...wrap around to the beginning:
      readIndex = 0;
    }

    // calculate the average:
    average = total / numReadings;
    // send it to the computer as ASCII digits

    Serial.print("   ");
    Serial.print(average);
    Serial.println("");
    delay(1000);        // delay in between reads for stability
  }
  else{
    Serial.print("loadcell not found!");
  }
}

```

# Answer
Another option would be use 'long' as a variable type for total. Depending on your application, you also might look into an exponentially weighted moving average (EWMA); it can de-emphasize older data points, if that is an issue.
> 2 votes

# Answer
As already commented by Majenko, the problem in integer wraparound. One solution would be to get rid of that `total` variable and calculate every new average based on the previous average and the mass you are replacing in the array, using this formula:

```
new_average = old_average + (mass - readings[readIndex]) / numReadings

```

So your code would look like:

```
  if (scale.is_ready()) {
    // read from the sensor:
    reading = scale.read();
    // convert to mass
    mass = int((a*reading)-b);

    // calculate the new average:
    new_average = average + (mass - readings[readIndex]) / numReadings;

    Serial.print(int((a*reading)-b));
    readings[readIndex] = mass;

    // advance to the next position in the array:
    readIndex = readIndex + 1;

    // if we're at the end of the array...
    if (readIndex >= numReadings) {
      // ...wrap around to the beginning:
      readIndex = 0;
    }

    // set the average:
    average = new_average;

    // send it to the computer as ASCII digits
    Serial.print("   ");
    Serial.print(average);
    Serial.println("");
    delay(1000);        // delay in between reads for stability
  }

```

Just don't forget to add a declaration for `new_average` to the beginning of your code.
> 0 votes

---
Tags: sensors
---


# Question
Title: Use normal TFT Shield with SD as a Nextion Display
I have a normal Elegoo TFT 2.8" display shield that also had an SD reader. I am trying to use it as a Nextion display. I want to do this because the Nextion tool allows you to make very nice looking sophisticated graphics and I wanted to do the same. Is there any possibility? Maybe some interpreter library?

# Answer
> 0 votes
No, you can't.

Nextion displays contain their own microcontroller with their own closed-source firmware on them. You need that firmware to have a clue what is in Nextion files, and only Nextion have that firmware.

While it may be possible to reverse engineer Nextion display data and write your own software to interpret it, it would be a huge job with little to no real-world benefit.

# Answer
> 0 votes
You cannot use a 2.8" TFT as a Nextion Display. Two are seperate things

Nextion Display is an HMI. You can configure prebuilt menus and graphics without coding.

The 2.8" TFT is a generic display module. It prints data according to the commands it receives. The user has to prepare the data to be printed. It can read data from an sd card, but the user program has to issue the commands for it.

Nextion displays use a generic display like the 2.8" TFT, an onboard controller with custom firmware running on it.

---
Tags: arduino-mega, programming, shields, tft
---


# Question
Title: How to use HC-SR04 sensor to make a flowmeter?
I am somewhat familiar with Arduino and am trying to use two ultrasonic HC-SR04 modules to measure the direction of water flow inside a pipe. The sensors are kept as in the image below. The direction is determined by emitting a signal from one sensor and receiving it in the other, noting down the time and repeating with the other set(See image below). This is called an ultrasonic time of flight flowmeter.

We then use the obtained values to determine the direction by seeing which one is greater. Further details on how it works can be found here: https://www.youtube.com/watch?v=rqJ9snaqYiY

I used the below code to collect the data to determine direction for this but it doesn't seem to be working, as only the first value is displayed and the second is always 0.

```
long firstduration = 0;
long secondduration = 0;

void setup() {
  // put your setup code here, to run once:
pinMode(13, OUTPUT);
pinMode(12, INPUT);
pinMode(11, INPUT);
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
digitalWrite(13,LOW);
delayMicroseconds(2);
digitalWrite(13,HIGH);
delayMicroseconds(10);
digitalWrite(13,LOW);
firstduration = pulseIn(12,HIGH);
secondduration = pulseIn(11, HIGH);
Serial.print(firstduration);
Serial.print(", ");
Serial.println(secondduration);
}

```

Updated code:

```
long firstduration;
long secondduration;

void setup() {
  // put your setup code here, to run once:
pinMode(10, OUTPUT);
pinMode(13, OUTPUT);
pinMode(12, INPUT);
pinMode(11, INPUT);
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
digitalWrite(13,LOW);
delayMicroseconds(2);
digitalWrite(13,HIGH);
delayMicroseconds(10);
digitalWrite(13,LOW);
firstduration = pulseIn(12,HIGH);

digitalWrite(10,LOW);
delayMicroseconds(2);
digitalWrite(10,HIGH);
delayMicroseconds(10);
digitalWrite(10,LOW);
secondduration = pulseIn(11,HIGH);

Serial.print(firstduration);
Serial.print(", ");
Serial.println(secondduration);
}

```

What would the issue be?

I am using an Arduino Uno board.

I have ruled out wiring issues...

Thanks!

# Answer
> 3 votes
I don't think this will work with HC-SR04 sensors. They are not just ultrasonic transducers. They incorporate extra electronics for the sole purpose of measuring the time difference between the sended and received signal. They just don't provide the needed control on the ultrasonic transducers. To change their function to suite you you will need to fully understand their circuitry (I surely don't). Or build your own support circuitry. Additionally you need to think about how to transmit the ultrasonic wave into the fluid. It isn't enough to just tag a standard transducer to the pipe. The small transducers on the HC-SR04 sensors are made for transmitting through air, so the actual transducer is hidden behind the grill inside the capsule. I thin you need to at least bring the transducer itswlf directly to the pipe, if not directly to the water. You will need to buy fizting ultrasonic transducers.

Also you have a problem due to the workings of `pulseIn()`.

If you want to read a HIGH pulse it will wait for the pin to go LOW, then to go HIGH again, and then counting the time until it goes LOW again. This means it blocks from the moment it is called until the pulse is finished (or the 1s timeout hits).

I will assume that you trigger the sensor which has its echo pin on pin 12, though a similar problem arises when you trigger the other sensor.

With the HC-SR04 the HIGH pulse will start at a specific time after the trigger pulse. Lets assume the pulse starts at the same time on both sensors (despite the described problems above). Directly after the trigger pulse you call `pulseIn()` on the sending sensor. It will block until it receives the each. Since this needs about twice as long as the other sensor to receive the signal (signal needs to go to the second sensor and then back to its source) the end of the echo pulse from the receiving sensor will be inside this time, thus putting its echo pin low again. The sending snsor receives its echo, the `pulseIn()` function ends. Now you call `pulseIn()` on the receiving sensor. But its pulse already ended, so the function waits and waits for the pulse to start and finally reaches its timeout. In this case it returns zero.

You would need to check the pins in a non-blocking way. Maybe even an Input Capture Interrupt would be fitting (depending on the requirements on the resolution).

---
Tags: arduino-uno, hc-sr04
---


# Question
Title: Is 1MB flash enough for OTA upload in ESP-01?
I'am asking this question, because in my ESP-01 OTA upload always fail. In fact update won't even start. When update was triggered esp wifi led(build in blue) indicates "working" , but after cca one second esp reset itself. And The original program remains and starts again...

# Answer
> 3 votes
Yes, 1MB is fine for OTA. There are, though, a few caveats when working with OTA that you must observe regardless of the flash size:

1. The maximum OTA program size is less than half the available flash size. Typically it is about 500kB. Two copies need to be stored in flash, plus the partition table and NVRAM. The rest of the flash on larger chips is most often dedicated to FS storage.
2. The device must first be programmed through USB with an OTA-compatible partition layout.
3. After programming through USB it must be manually reset or power cycled to set the boot mode correctly.
4. You can not change the partition layout over OTA programming. You need to make sure you have the same partition layout selected as when you originally programmed through USB.
5. `ArduinoOTA.handle();` has to be called very regularly to handle the programming request. You can't have any blocking code in your sketch that might stop that from being called.

Observe all those and you should be able to program over WiFi with no problems.

# Answer
> 2 votes
For OTA uploads, the size of the compiled (old sketch + new sketch) should not exceed the flash size.

Due to this, large sketches (more than 500KB with 1MB flash) cannot be OTA uploaded directly if the sketch size exceeds half of the flash size.

However, this restriction can be circumvented by first uploading a sketch only with OTA features as given below:

---

```
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

char ssid[] = "xxxxxxxx"; //WiFI user id
char pass[] = "yyyyyy";   //WiFi password

#define OTA_Host_Name "ESP01S-EMPTY-OTA"

void setup()  {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, pass);

  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    delay(5000);
    ESP.restart();
  }
  ArduinoOTA.setHostname(OTA_Host_Name);
  ArduinoOTA.begin();
}

void loop() {
  ArduinoOTA.handle();
}

```

---

This script will compile to around 300KB. Once this script is uploaded in flash, a script with upto 700KB can be uploaded through OTA to a 1MB flash!

Upload this script first. Then restart the controller and choose "ESP01S-EMPTY-OTA" as the port and upload the new updated script that you wish to upload!

IMPORTANT: Firewall must be turned OFF during OTA uploads.

---
Tags: esp8266, arduino-ide, wifi, esp, ota
---


# Question
Title: How do I create a code that lets me use an array of 10 thermistors on one arduino?
I am new to programming and am trying to create an array of 10 thermistors on one arduino. So far I have found a code for Temperature Sensor Using NTC Thermistor that is only for one thermistor. How do I fix this code for 10 thermistors? Here is the link where I found the code. https://thecustomizewindows.com/2020/10/temperature-sensor-using-ntc-thermistor-arduino-ntc/ The code below has been changed a little for the thermistor I am using. Thank you.

```
#define RT0 10000   // Ω
#define B 3470      // K
#define VCC 5       //Supply voltage
#define R 10000     // R=10kΩ

float RT, VR, ln, TX, T0, VRT;

void setup() {
  Serial.begin(9600);
  T0 = 25 + 273.15;                 //Temperature, Celsius to Kelvin
}

void loop() {
  VRT = analogRead(A0);              //Acquisition analog value of VRT
  VRT = (5.00 / 1023.00) * VRT;      //Conversion to voltage
  VR = VCC - VRT;
  RT = VRT / (VR / R);               //Resistance of RT

  ln = log(RT / RT0);
  TX = (1 / ((ln / B) + (1 / T0))); //Temperature from NTC thermistor

  TX = TX - 273.15;                 //Conversion to Celsius

  Serial.print("Temperature:");
  Serial.print("\t");
  Serial.print(TX);
  Serial.print("C\t\t");
  Serial.print((TX * 1.8) + 32);    //Conversion to Fahrenheit
  Serial.println("F");
  delay(500);
}

```

# Answer
> 3 votes
You haven't said which (of the many kinds) of "Arduino" you plan to use, but Uno being the most common, I'll assume that. You also haven't said why/whether you must use a particular temperature sensor, but if you can be flexible about that, there will more choices of solution.

First, thermistors: You read a thermistors with an an A/D converter. Uno has an A/D converter but it has only 6 channels available - not enough for your spec of 10 sensors.

* You could add an external A/D multiplexer with 5 channels fed into one of your on-board channels plus the remaining 5 on-board channels.
* Or add a 10-channel multiplexer for all 10 sensors and feed it to one of the on-board A/D channels. This is better because it's simpler - all of the sensor signals will be processed identically, and all accessed the same way in the code.
* Add an external 10-channel A/D. It will cost a little more but will be even easier to work with.

If you don't require thermistors, I'd suggest the Dallas/Maxim DS18b20 "1-wire" sensors. The "1-Wire" bus is a proprietary protocol developed by Dallas Semiconductor on which these sensors depend. You use one, simple, twisted-pair bus to access all of them, needing only 1 Arduino pin (and ground) to provide both power and communication to/from the sensors. Libraries are available to manage the bus and the communication. The 1-wire bus can be in a linear or a branched configuration, to suit your installation. You can use 2 wires (ground and power+data) or 3 wires (ground, power, data). Here's a link to the DS18b20 data sheet for the details.

Update:
I didn't really answer your question about *coding* for 10 thermistors (since you can't directly connect 10 thermistors to an Uno), I'll try to address that now without getting into any more detail about what kind of sensors you use or how you connect them.

You'll need to read 10 sensors, compute the sensor data to temperature and store it, and do whatever you plan to do with the temperature value. Your present code prints it (as both degC and degF, but let's just describe that part as printing the value).

You'll need a `for( )` loop that executes 10 times, once for each sensor, where the loop index tells which sensor (0-9) you'll be processing. In time the loop executes, read a sensor, compute the temperature from what the sensor gives you, if it isn't already in the units you need, and print the value. So structuring that as if it were code (but I won't be writing it out in full C++) it would look like:

```
tell all 10 sensors to take a measurement; // if necessary
for( i = 0; i < 10; ++i ){
   read data from sensor[i];
   convert it to temperature;      // depends on the sensor
   print the temperature value;
}

```

If that is all you want to do, code this loop in your `setup()` function. Each time you reset the Arduino, it will measure and print all 10 temperatures and stop (actually, loop forever, doing nothing, until you power it down). If you want it to do this periodically, code this loop in your `loop()` function, with a `delay(5000);` statement after it. Now it will print the 10 temperatures every 5 seconds. You can change the 5000 (it's in milliseconds) to whatever period you want.

But it's the details that get you. You've got code to read and convert thermistors but your Arduino can't directly connect to 10 thermistors. If you use an external multiplexer, then you'll have to include code for that. If you use DS18b20 1-Wire sensors, you'll need to download and use the code library for those, as well as converting their 1/16-degC units to the units of your choice.

I'd recommend you start with 2 or 3 thermistors since you have the code for them, and write the loop for those. Once that's working, you'll have the answer to your title question. Then you'll have to decide how to connect 10 sensors of some kind, as I wrote about earlier. That will involve some additional coding, for an analog multiplexer, or for 1-Wire sensors, or whatever solution you choose. Just expand your experiment by small steps at a time and get each step working before you move on.

---
Tags: arduino-uno, code-optimization, thermistor
---


# Question
Title: Morse encoder code not working as expected on Arduino UNO
I'll start saying that I don't have much experience working with Arduino and programming in C. I have an Elegoo Arduino UNO clone.

Recently I was trying to build a morse encode which converts a text to morse and then flashes a LED to communicate the morse code. The code is as follows

```
#define OUT_PIN 8
#define END_PIN 7

const short dot_time = 200; // Time LED is ON for dot
const short dash_time = dot_time*3; // Time LED is ON for dash
const short same_letter_space = dot_time; // Time LED is OFF between dots/dashes of the same letter
const short letter_space = dot_time*3; // Time LED is OFF between letters
const short word_space = dot_time*5; // Time LED is OFF between words
const char letter_separator[] = "_";
const char word_separator[] = "/";

typedef struct {
  char * morse;
  char letter;
}morse_pair;

morse_pair morse_table_letters[] = {{".-", 'A'}, {"-...", 'B'}, {"-.-.", 'C'}, {"-..", 'D'}, {".", 'E'}, {"..-.", 'F'}, {"--.", 'G'}, {"....", 'H'}, {"..", 'I'}, {".---", 'J'},//
{"-.-", 'K'}, {".-..", 'L'}, {"--", 'M'}, {"-.", 'N'}, {"---", 'O'}, {".--.", 'P'}, {"--.-", 'Q'}, {".-.", 'R'}, {"...", 'S'}, {"-", 'T'}, {"..-", 'U'}, {"...-", 'V'},
{".--", 'W'}, {"-..-", 'X'}, {"-.--", 'Y'}, {"--..", 'Z'}};
morse_pair morse_table_digits[] = {{"-----", '0'}, {".----", '1'}, {"..---", '2'}, {"...--", '3'}, {"....-", '4'}, {".....", '5'}, {"-....", '6'}, {"--...", '7'}, {"---..", '8'},//
{"----.", '9'}};

char test_text[] = "aaa";

morse_pair letter_encoder(char letter){
  int letter_value = (int) letter;
  if(letter_value >= 97){
    //lowercase
    return morse_table_letters[letter_value-97];
  }
  else if (letter_value>=65){
    //uppercase
    return morse_table_letters[letter_value-65];
  }
  else {
    //digits
    return morse_table_digits[letter_value];
  }
}

char* word_to_morse(char* word, size_t len){
  Serial.print("Encoding word: ");
  Serial.println(word);
  size_t len_morse = 0;
  char* letters[len];
  for(size_t l=0;l<len;l++){
    letters[l] = letter_encoder(word[l]).morse;
    len_morse += strlen(letters[l])+1;
  }
  char* morse_string = malloc(len_morse*sizeof(char));
  for(size_t l=0;l<len;l++){
    strcat(morse_string, letters[l]);
    if(l<len-1){
      strcat(morse_string, letter_separator);
    }
  }
  strcat(morse_string, word_separator);
  Serial.print("Result: ");
  Serial.println(morse_string);
  return morse_string;
}

char* text_to_morse(char* text){
  Serial.print("Encoding text: ");
  Serial.println(text);
  size_t len = strlen(text);
  char* text_morse = malloc((4*len+len)*sizeof(char));
  char* swp = text;
  for(char* ewp = text;ewp!=(text+len);ewp++){
    if(*(ewp+1)==' ' || *(ewp+1) == '\0'){
      char * wtm = word_to_morse(swp, ewp-swp+1);
      strcat(text_morse, wtm);
      swp=ewp+2;
      free(wtm);
    }
  }
  Serial.print("Result: ");
  Serial.println(text_morse);
  return text_morse;
}

void morse_to_pin(char* text_morse){
  Serial.println("Playing with pins");
  size_t len = strlen(text_morse);
  for(size_t l=0;l<len;l++){
    char letter = text_morse[l];
    Serial.println(letter);
    if(letter == '.'){
      digitalWrite(OUT_PIN, HIGH);
      delay(dot_time);
    }
    else if(letter=='-'){
      digitalWrite(OUT_PIN, HIGH);
      delay(dash_time);
    }
    else if(letter=='_'){
      digitalWrite(OUT_PIN, LOW);
      delay(letter_space);
    }
    else if(letter=='/'){
      digitalWrite(OUT_PIN, LOW);
      delay(word_space);
    }
    else {
      digitalWrite(OUT_PIN, LOW);
      delay(same_letter_space);
    }
  }
}

void start_comm(){
  Serial.println("Start comm.");
  digitalWrite(END_PIN, HIGH);
  delay(2000);
  digitalWrite(END_PIN, LOW);
}

void end_comm(){
  Serial.println("End comm.");
  digitalWrite(END_PIN, HIGH);
  delay(500);
  digitalWrite(END_PIN, LOW);
  delay(500);
  digitalWrite(END_PIN, HIGH);
  delay(500);
  digitalWrite(END_PIN, LOW);
}

void setup(){
  Serial.begin(9600);
  pinMode(OUT_PIN, OUTPUT);
  pinMode(END_PIN, OUTPUT);
}

void loop ()
{
  start_comm();
  delay(1000);
  char* ttm = text_to_morse(test_text);
  morse_to_pin(ttm);
  free(ttm);
  delay(1000);
  end_comm();
  delay(1000);
}

```

The part of the code that converts text to a morse string behaves correctly when run on my laptop, but when I upload it to my Arduino UNO behaves weirdly and the morse LED doesn't flashes at all.

---

## **Edit:**

the Arduino UNO just seems to run only the `start_comm` and `end_comm` functions, as if there's nothing inbetween. It changed behaviour and doesn't behaves always the same, before it printed some garbage to the serial monitor, but now it just skips the whole code inbetween the two functions mentioned above.

# Answer
I kind of solved it, I was using `malloc` incorrectly and was accessing uninitialized bits, thus causing undefined behaviour. The code below should work correctly

```
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define OUT_PIN 8
#define END_PIN 7

const short dot_time = 200; // Time LED is ON for dot
const short dash_time = dot_time * 3; // Time LED is ON for dash
const short same_letter_space = dot_time; // Time LED is OFF between dots/dashes of the same letter
const short letter_space = dot_time * 3; // Time LED is OFF between letters
const short word_space = dot_time * 5; // Time LED is OFF between words
const char letter_separator[] = "_";
const char word_separator[] = "/";
const char unkown_letter[] = "?";

typedef struct {
  char * morse;
  char letter;
} morse_pair;

const morse_pair morse_table_letters[] = {{".-", 'A'}, {"-...", 'B'}, {"-.-.", 'C'}, {"-..", 'D'}, {".", 'E'}, {"..-.", 'F'}, {"--.", 'G'}, {"....", 'H'}, {"..", 'I'}, {".---", 'J'},//
  {"-.-", 'K'}, {".-..", 'L'}, {"--", 'M'}, {"-.", 'N'}, {"---", 'O'}, {".--.", 'P'}, {"--.-", 'Q'}, {".-.", 'R'}, {"...", 'S'}, {"-", 'T'}, {"..-", 'U'}, {"...-", 'V'},
  {".--", 'W'}, {"-..-", 'X'}, {"-.--", 'Y'}, {"--..", 'Z'}
};
const morse_pair morse_table_digits[] = {{"-----", '0'}, {".----", '1'}, {"..---", '2'}, {"...--", '3'}, {"....-", '4'}, {".....", '5'}, {"-....", '6'}, {"--...", '7'}, {"---..", '8'},//
  {"----.", '9'}
};

const char* letter_encoder(char letter) {
  int letter_value = (int) letter;
  if (letter_value >= 97 && letter_value <= 122) {
    //lowercase
    return morse_table_letters[letter_value - 97].morse;
  }
  else if (letter_value >= 65 && letter_value <= 90) {
    //uppercase
    return morse_table_letters[letter_value - 65].morse;
  }
  else if (letter_value>=48 && letter_value<=57) {
    //digits
    return morse_table_digits[letter_value].morse;
  }
  else {
    //Boh
    return unkown_letter;
  }
}

void word_to_morse(char* morse_word, char* word, int len) {
  Serial.print("Encoding word: ");
  Serial.println(word);
  for (int l = 0; l < len; l++) {
    strcat(morse_word, letter_encoder(word[l]));
    if (l < len - 1) {
      strcat(morse_word, letter_separator);
    }
  }
  strcat(morse_word, word_separator);
  Serial.print("Word result: ");
  Serial.println(morse_word);
}

void text_to_morse(char* morse_text, char* text, int len) {
  Serial.print("Encoding text: ");
  Serial.println(text);
  char* swp = text;
  int morse_len = 0;
  for (char* ewp = text; ewp != (text + len); ewp++) {
    if (*(ewp + 1) == ' ' || *(ewp + 1) == '\0') {
      int w_len = ewp - swp + 1;
      char * morse_word = (char*) malloc((5*w_len+w_len)*sizeof(char));
      strcpy(morse_word, "");
      word_to_morse(morse_word, swp, w_len);
      morse_len += strlen(morse_word);
      Serial.print("Word result: ");
      Serial.println(morse_word);
      Serial.print("Word len: ");
      Serial.println(morse_len);

      strcat(morse_text, morse_word);
      swp = ewp + 2;
      free(morse_word);
    }
  }
  morse_text = (char*) realloc(morse_text, ++morse_len*sizeof(char));
  Serial.print("Text result: ");
  Serial.println(morse_text);
}

void morse_to_led(const char* text_morse, int len) {
  Serial.println("Flashing morse with pins");
  for (int l = 0; l < len; l++) {
    char letter = text_morse[l];
    Serial.println(letter);
    switch(letter){
      case '.':
        digitalWrite(OUT_PIN, HIGH);
        delay(dot_time);
        break;
      case '-':
        digitalWrite(OUT_PIN, HIGH);
        delay(dash_time);
        break;
      case '_':
        digitalWrite(OUT_PIN, LOW);
        delay(letter_space);
        break;
      case '/':
        digitalWrite(OUT_PIN, LOW);
        delay(word_space);
        break;
      default:
        digitalWrite(OUT_PIN, LOW);
        delay(same_letter_space);
        break;
    }
  }
}

void start_comm() {
  Serial.println("Start comm.");
  digitalWrite(END_PIN, HIGH);
  delay(dash_time);
  digitalWrite(END_PIN, LOW);
}

void end_comm() {
  Serial.println("End comm.");
  digitalWrite(END_PIN, HIGH);
  delay(dot_time);
  digitalWrite(END_PIN, LOW);
  delay(dot_time);
  digitalWrite(END_PIN, HIGH);
  delay(dot_time);
  digitalWrite(END_PIN, LOW);
}

void setup() {
  Serial.begin(9600);
  pinMode(OUT_PIN, OUTPUT);
  pinMode(END_PIN, OUTPUT);
}

void loop ()
{
  //Start
  start_comm();
  delay(2000);

  //Convert
  char test_text[] = "test";
  int len = strlen(test_text);
  char * morse_text = (char*) malloc((5*len+len)*sizeof(char));
  strcpy(morse_text, "");
  text_to_morse(morse_text, test_text, len);
  morse_to_led(morse_text, strlen(morse_text));
  free(morse_text);
  delay(2000);

  //End
  end_comm();
  delay(2000);
}

```
> 1 votes

---
Tags: arduino-uno, programming, c
---


# Question
Title: Multiplexer 74HC4067, conflict between channels
I am currently working on an Arduino Zero with a 74HC4067 multiplexer and I am experiencing inconsistencies when testing some of the channels.

My class is the following (it should be functional for 8 or 16 channels multiplexers).

Multiplexer.h :

```
#ifndef Multiplexer_h
#define Multiplexer_h

#include "Arduino.h"

class Mux
{
  public:
    Mux(uint8_t numberOfChannels, byte sigPin, byte adress1, byte adress2, byte adress3, byte adress4 = 0);

    uint8_t muxRead(byte pin);//Read specific mux pin
    void selectMuxPin(byte pin);

  private:
    uint8_t m_numberOfChannels;
    byte m_sigPin ;
    byte m_adress1 ;
    byte m_adress2 ;
    byte m_adress3 ;
    byte m_adress4 ;
    uint8_t m_numberOfAdressPins;
};

#endif

```

Multiplexer.cpp :

```
#include "Multiplexer.h"

//**************************************************************

Mux::Mux(uint8_t numberOfChannels,
         byte sigPin,
         byte adress1,
         byte adress2,
         byte adress3,
         byte adress4)

:   m_numberOfChannels(numberOfChannels),
    m_sigPin(sigPin),
    m_adress1(adress1),
    m_adress2(adress2),
    m_adress3(adress3),
    m_adress4(adress4)
{
  if(m_numberOfChannels > 8) {m_numberOfAdressPins = 4;}
  else {m_numberOfAdressPins = 3;}

  //Set adresses to OUTPUT
  pinMode(m_adress1, OUTPUT);
  pinMode(m_adress2, OUTPUT);
  pinMode(m_adress3, OUTPUT);
  if(m_numberOfChannels > 8){pinMode(m_adress4, OUTPUT);};

  //Set adresses to LOW
  digitalWrite(m_adress1, LOW);
  digitalWrite(m_adress2, LOW);
  digitalWrite(m_adress3, LOW);
  if(m_numberOfChannels > 8){digitalWrite(m_adress4, LOW);};

  pinMode(m_sigPin, INPUT_PULLUP);
}

//**************************************************************

uint8_t Mux::muxRead(byte pin)
{
  selectMuxPin(pin);
  bool value = digitalRead(m_sigPin);
  return(value) ;
}

void Mux::selectMuxPin(byte pin)
{
  const int selectPins[4] = {m_adress1, m_adress2, m_adress3, m_adress4};
  if (pin > (m_numberOfChannels - 1)) return; // Exit if pin is out of scope

  for (int i = 0; i < m_numberOfAdressPins; i++)
  {
    if (pin & (1<<i)) {digitalWrite(selectPins[i], HIGH);}
    else {digitalWrite(selectPins[i], LOW);}
  }
}

```

To make my tests on the 74HC4067, I connect my multiplexer, I put the pin 8 of my Arduino to the "LOW" state and with the help of a jumper cable I test each of the pins via the following code:

```
#include "Multiplexer.h"

//**************************************************************

Mux Mux0(16, 6, 2, 3, 4, 5);

//**************************************************************

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

//**************************************************************

void loop() {

  //Set pin 8 to LOW for the test with a jumper
  analogWrite(8, LOW);

  //For this test, we print the name of the multiplexer's channel if it's LOW

  bool channel0 = Mux0.muxRead(0);
  if(!channel0)
    Serial.println("Channel 0");

  bool channel1 = Mux0.muxRead(1);
  if(!channel1)
    Serial.println("Channel 1");

  bool channel2 = Mux0.muxRead(2);
  if(!channel2)
    Serial.println("Channel 2");

  bool channel3 = Mux0.muxRead(3);
  if(!channel3)
    Serial.println("Channel 3");

  bool channel4 = Mux0.muxRead(4);
  if(!channel4)
    Serial.println("Channel 4");

  bool channel5 = Mux0.muxRead(5);
  if(!channel5)
    Serial.println("Channel 5");

  bool channel6 = Mux0.muxRead(6);
  if(!channel6)
    Serial.println("Channel 6");

  bool channel7 = Mux0.muxRead(7);
  if(!channel7)
    Serial.println("Channel 7");

  bool channel8 = Mux0.muxRead(8);
    if(!channel8)
    Serial.println("Channel 8");

  bool channel9 = Mux0.muxRead(9);
  if(!channel9)
    Serial.println("Channel 9");

  bool channel10 = Mux0.muxRead(10);
  if(!channel10)
    Serial.println("Channel 10");

  bool channel11 = Mux0.muxRead(11);
  if(!channel11)
    Serial.println("Channel 11");

  bool channel12 = Mux0.muxRead(12);
  if(!channel12)
    Serial.println("Channel 12");

  bool channel13 = Mux0.muxRead(13);
  if(!channel13)
    Serial.println("Channel 13");

  bool channel14 = Mux0.muxRead(14);
  if(!channel14)
    Serial.println("Channel 14");

  bool channel15 = Mux0.muxRead(15);
  if(!channel15)
    Serial.println("Channel 15");
}

```

For most of the channels it works quite well. When I connect the jumper (pin 8) to a channel of the multiplexer, the name of the corresponding pin is displayed in the console.

However, two channels are problematic. Channel 0 and channel 8. No matter if I connect the jumper to one or the other, I see in the console "Channel 0" and "Channel 8" as if both were connected and the change of state of one would cause the change of state of the other.

Any idea why?

Thanks

# Answer
> 2 votes
I gather it is part of a learning experiment. Logically this does not compute however there are many reasons something like this could happen. A bad IC is the first thing that comes to mind but they are generally very rugged devices. If you have a scope probe the power supplies to be sure they are clean and stable, if so start by holding it in one of the bad states and take voltage measurements on VCC, Ground, several other pins and the related pins. Your voltage on each pin should be within 0.1V of the appropriate power supply pin. If not it would indicate a short especially if it goes somewhere mid supply voltage. If this is a breadboard flip the bad pins out and test again. If everything is in speck it is a short, if it still show you probably have a bad IC.

---
Tags: c++, multiplexer, arduino-zero
---


# Question
Title: Selenoid motor not responding to NodeMCU instructions
I just start a project migrating from Arduino Uno to NodeMCU, basically this projects control some selenoid motors triggered by a website instructions. For example: if website returns 2, the motor #2 start work.

I hace everything ready, fetching from the website but, the motors are not working. In Arduino Uno works but in NodeMCU did not.

The selenoid motor is this one from AliExpress: the 3v --\> https://es.aliexpress.com/item/4000807560712.html

The circuit I made is like this:

**NodeMCU / Motor**

D2 -\> Positive motor wire (red wire).

3.3V -\> Positive motor wire (red wire).

GND -\> Negative motor wire (black wire).

All this is attached to a protoboard for easy my work, but those are the connections of the circuit.

At otherwise, the code looks something like this:

```
void setup() {
  Serial.begin(115200);
  pinMode(D2, OUTPUT);

}

void loop() {
  digitalWrite(D2, LOW);
  delay(3000);
  digitalWrite(D2, HIGH);
  delay(3000);

}

```

I also tried instead of pin name `D2` use `4` corresponding of the GPIO number. Didn't work.

The wired part is in Arduino Uno the same code and same circuit works perfectly, but in NodeMCU not.

# Answer
> 2 votes
So you connected 3.3V and pin D2 both to the positive motor wire. When the pin is high the motor runs and gets its current from the 3.3V pin. When you set the pin to LOW you essentially short the 3.3V pin to ground through the output hardware of the pin. That is highly risky. The output hardware of the pin only can withstand a certain amount of current (around 20mA, 40mA absolute max). Since you have nothing that would limit the current in this path you can easily fry the output hardware of the pin. **Don't do that!** The same is valid for driving a motor directly only from the digital output pin.

The correct way of controlling a motor with an Arduino or ESP is by using a fitting driver. For just turning it on and off a simple transistor or MOSFET is sufficient (depending on the current draw of the motor a MOSFET is better than a bipolar transistor). Google something like "MOSFET as switch" and you will get many tutorials on that. You can also add the term "Arduino" and you will get tutorials specifically for Arduinos.

Why it worked for the Uno but not for the NodeMCU? You didn't describe how exactly you connected it on the Uno (to the 3.3V pin or the 5V pin?). Probably the digital output pin on the NodeMCU cannot sink enough current so that it is not able to lower the voltage enough. Though if it would be able to do this it would also cause a power failure for the whole microcontroller. Maybe that also happened with your Uno difficult to say without more information.

---
Tags: esp8266, motor, nodemcu
---


# Question
Title: "Simple" code...but what have I done wrong?
This code compiles without problem, but doesn't work at all... The switch does not set the LED low and the while loop doesn't work, plus the serial print doesn't print.... Until I put the while loop in pressing either button would change the LED state. I wanted to make the sequence "button one, LED change, THEN button two" I'm certain to have missed something...

```
const int buttonPin1 = 2;     // the number of the pushbutton 1 pin 2
const int buttonPin2 = 7;     // the number of the pushbutton 2 pin 7
const int ledPin = 13;      // the number of the LED pin

// variables will change:
int buttonState1 = 0;         // variable for reading the pushbutton status
int buttonState2 = 0;
int i = 0;

void setup() {
// initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin 1 as an input:
  pinMode(buttonPin1, INPUT);
// initialize the pushbutton pin 2 as an input:
  pinMode(buttonPin2, INPUT);
  Serial.begin(9600);
}

void loop() {

  digitalWrite(ledPin, HIGH);

// read the state of the pushbutton value:
  buttonState1 = digitalRead(buttonPin1);

// check whether a  pushbutton is pressed.
// if it is, the buttonState is HIGH:

  if (buttonState1 == HIGH) {
// turn LED off:   //
    digitalWrite(ledPin, LOW);
    while (1) {
      (buttonState1 == LOW);
      if (buttonState1 == LOW) {
        Serial.println("1");
      }
      {
        break;
      }
    }

    delay[1000];

    digitalWrite(ledPin, HIGH);

// read the state of the pushbutton 2 value:
    buttonState2 = digitalRead(buttonPin2);
    if (buttonState2 == HIGH) {
// turn LED off:
      while (1) {
        if (buttonState2 == LOW) {
          break;
        }
      }
      digitalWrite(ledPin, LOW);

      delay(10000);
      digitalWrite(ledPin, HIGH);

    }
  }
}

```

# Answer
> 1 votes
I think there’s a misunderstanding of how variables work.

Your code is only reading the real state of *buttonPin1* once (before the first `if ()` statement) and copies the value read from the I/O port *as it is at that moment* to the variable *buttonState1*, by executing `buttonState1 = digitalRead(buttonPin1);`.

After you’ve copied the value read from the *buttonPin1* port to the *buttonState1* variable, this variable will no longer change or reflect the actual button status. I.e. the value of the variable *buttonState1* will not automagically change when you push or release button 1. *buttonState1* is a normal program variable and not coupled to the I/O port.

If you want to continue to check the current button status, you have to continuously read the I/O port, by using `digitalRead()` statements where appropriate.

The same goes for *buttonPin2* and *buttonState2*.

---
Tags: programming
---


# Question
Title: Arduino ESP8266 HTTPS Request returning empty response
I want to get some JSON data from a HTTPS secured Webserver using a ESP8266. For some reason I'm getting an empty response, I believe there's an error parsing the GET request. In Chrome I get the JSON response without problems.

GET Request:

```
httpsClient.print(String("GET ") + path + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");

```

Host and Path:

```
const char *host = "www.adler-mannheim.de";
const char *path = "/jsonapi/game/current";

```

**UPDATE:**

I tried fetching some JSON from another Server and it worked finde, so i can rule out my code. Fiddling around with the host and path I observe this:

* Hostname without "www" results in a 301
* Hostname with "https://www" results in no HTTPS connection at all

So it seems that a "www" is required although it unfortunately leads into a empty response.

The output is as follows:

```
headers received
reply was:
==========
==========
closing connection

```

In the first case, without using "www" in ahead of host there's some 301 HTML in between the two lines of "=".

Whole function:

```
void connect() {
  WiFiClientSecure httpsClient;    //Declare object of class WiFiClient

  Serial.println(host);
  httpsClient.setInsecure();

  Serial.print("HTTPS Connecting");
  int r=0; //retry counter
  while((!httpsClient.connect(host, httpsPort)) && (r < 30)){
      delay(100);
      Serial.print(".");
      r++;
  }
  if(r==30) {
    Serial.println("Connection failed");
  }
  else {
    Serial.println("Connected to web");
  }

  String getData, Link;

  //GET Data

  Serial.print("requesting URL: ");
  Serial.println(host+Link);

  httpsClient.print(String("GET ") + path + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");

  Serial.println("request sent: ");
  Serial.println(String("GET ") + path + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" +
               "Connection: close\r\n\r\n");
  while (httpsClient.connected()) {
    String line = httpsClient.readStringUntil('\n');
    if (line == "\r") {
      Serial.println("headers received");
      break;
    }
  }

  Serial.println("reply was:");
  Serial.println("==========");
  String line;
  while(httpsClient.available()){
    line = httpsClient.readStringUntil('\n');  //Read Line by Line
    Serial.println(line); //Print response
  }
  Serial.println("==========");
  Serial.println("closing connection");

  delay(2000);  //GET Data at every 2 seconds
}

```

**UPDATE 2:**

I tried the following code from the ESP8266HTTPClient Library examples:

```
void connect2() {

  WiFiClientSecure client;

  //client.setFingerprint(fingerprint);
  client.setInsecure();

  HTTPClient https;

  Serial.print("[HTTPS] begin...\n");
  if (https.begin(client, "https://github.com/esp8266/Arduino/issues/3417")) {  // HTTPS

    Serial.print("[HTTPS] GET...\n");
    // start connection and send HTTP header
    int httpCode = https.GET();

    // httpCode will be negative on error
    if (httpCode > 0) {
      // HTTP header has been send and Server response header has been handled
      Serial.printf("[HTTPS] GET... code: %d\n", httpCode);

      // file found at server
      if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
        String payload = https.getString();
        Serial.println(payload);
      }
    } else {
      Serial.printf("[HTTPS] GET... failed, error: %s\n", https.errorToString(httpCode).c_str());
    }

    https.end();
  } else {
    Serial.printf("[HTTPS] Unable to connect\n");
  }

  Serial.println("Wait 10s before next round...");
  delay(10000);
}

```

This one gives me a 200 but no payload. Other sites work

**UPDATE 3:**

I had a look on the headers.

```
https.headers()

```

This gives me 0 headers on every page, even when there's a payload.

I also had a closer look at the payload that returns from my desired api and its filled with NULL. In a weird way this is only the case with my desired page and only my desired subpages. Requesting something more at top level e.g "https://www.adler-mannheim.de/jsonapi" which is basically a SilverStripe Welcome page, I get a fully fetched beautiful HTML payload.

I got literally no Idea why. Do I have to set a specific User Agent or something so that the Server responds?

# Answer
Okay I have no Idea what I changed apart from deleting some imports which might have collided, but now it works. Regular call with "https://www" does the thing.

Thanks anyways
> 1 votes

# Answer
I had this same problem and I realized it was because I was using an `WiFiClientSecure` to try to an endpoint over HTTP instead of HTTPS. If anyone else is having this same problem, I would check that.
> 0 votes

---
Tags: esp8266, http
---


# Question
Title: Proteus potentiometer value always highest
```
#include <Servo.h>

#define potpin A0
int savebutton=2;
int button1=3;
int button2=4;
int button3=5;

Servo servo1;
Servo servo2;
Servo servo3;

int servo1ipos=90;
int servo2ipos=90;
int servo3ipos=90;

int val=0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(savebutton,INPUT);
  pinMode(button1,INPUT);
  pinMode(button2,INPUT);
  pinMode(button3,INPUT);

  servo1.attach(6);
  servo2.attach(7);
  servo3.attach(8);
  servo1.write(servo1ipos);
  servo2.write(servo2ipos);
  servo3.write(servo3ipos);

}

void loop() {
  // put your main code here, to run repeatedly:
  servocontrol();

}

int servocontrol(){
  if(digitalRead(button1)==LOW){
    potvalue();
    Serial.println(val);
    servo1.write(val);
    delay(200);
  }
}
int potvalue(){
    val=analogRead(potpin);
}

```

Basicly I only read 1023 value instead of potentiometer value I couldnt figure it out need help.

Update: I came up solution by connecting 5V into Arduino's VCC pin.

# Answer
> 1 votes
I came up solution by connecting 5V into Arduino's VCC pin.

---
Tags: potentiometer
---


# Question
Title: How to use HM-10 as client, and send messages to specific services/characteristics?
I have been messing around with this module, unfortunately i bought a fake one, but got the original firmware running inside it (V550).

So far i can set the **HM-10** up as **client/master** and by using an peripheral emulator on Android, i set up a **peripheral** as my **server/slave**

The peripheral is able to write to its own characteristic and it sends a notification to the client HM10 that fetches this value and displays it correctly on my serial reader (cutecom and arduino serial monitor)

After this, i'd like to write to the peripheral's characteristic, but **i can't find any information about this**, but it should be in the realm of possibility, i think.

I am using the Arduino IDE to interface with the HM-10 module.

Any information pointing in the right direction is very, very welcomed. Its driving me crazy now...

# Answer
You can upgrade the firmware to V709 available on the manufacture's website and find instructions on how to update it. You'll need a USB to TTL converter or something that can act as one.

With firmware V709 you can use AT+FINDSERVICES? and AT+FINDALLCHARS? command to get the list of services and characteristics on the server and then read, write, notify, etc, on the characteristic you are interested in. It is outlined in the datasheet. They call it self learn function and there's a document outlining how to use it.
> 1 votes

---
Tags: arduino-uno, serial, bluetooth, ble
---


# Question
Title: Arduino Mega 2560 + BLE HM-10 - I cannot execute AT commands
I have an Arduino Mega 2560 and a HM10 Bluetooth module (this one)

I have connected the Bluetooth according to the manufacturer's specifications: VCC -\> 5v GND -\> GND

TXD and RXD of the Bluetooth, I have tried to put them in pins of Arduino, in Serial1, in Serial2, in Serial3, with the same result.

The code I use for my tests is this:

```
#define BTserial Serial1

int LED_BOARD = 13;
int LED_RED = 2;
int LED_GREEN = 3;

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

    pinMode(LED_BOARD,OUTPUT);
    pinMode(LED_RED,OUTPUT);
    pinMode(LED_GREEN,OUTPUT);
}

void loop() {
    if (Serial1.available()) {
        dato = Serial1.readStringUntil('\n');

        Serial.println("DATA RECEIVED: [" + String(dato) + "]");

        if (dato.equals("1")) {
            digitalWrite(LED_BOARD, HIGH);
        }
        if (dato.equals("0")) {
            digitalWrite(LED_BOARD, LOW);
        }

        if (dato.equals("RED_ON")) {
            digitalWrite(LED_RED, HIGH);
        }
        if (dato.equals("RED_OFF")) {
            digitalWrite(LED_RED, LOW);
        }

        if (dato.equals("GREEN_ON")) {
            digitalWrite(LED_GREEN, HIGH);
        }
        if (dato.equals("GREEN_OFF")) {
            digitalWrite(LED_GREEN, LOW);
        }
    }
}

```

I have an Android phone, and I use the Arduino Bluetooth Controller (HM-10 Module) app.

* I send the text 1, and the led of the Arduino board (pin 13) turns on.
* I send the text 0, and the led of the Arduino board (pin 13) turns off.
* I send RED\_ON, and the led of my breadboard, connected to pin 2, turns on
* I send RED\_OFF, and the led of my breadboard, connected to pin 2, turns off
* I send GREEN\_ON, and the led of my breadboard, connected to pin 3, turns on
* I send GREEN\_OFF, and the led of my breadboard, connected to pin 3, turns off

So the Bluetooth works.

My problem is trying to see the list of Bluetooth commands (AT+HELP command).

I have a method that is responsible for sending AT+HELP to bluetooth, but I have no response.

This is the method, which I run in the main:

```
String str_ii = "";
int ii_0 = 0;
void ble_help(){
    Serial.println("ble_help");

    BTserial.println("AT+HELP"); // list all AT+ commands
    while (true){ // loop to print all AT+ commands
        char in_char = BTserial.read();
        if (int(in_char)==-1 or int(in_char)==42){
            continue;
        }
        str_ii+=in_char;
        if (in_char=='\n'){
            if (str_ii==String('\r')+String('\n')){
                if (ii_0 == 0){
                    ii_0 = 1;
                    continue;
                }
                break; // break after more than 1 empty carriage return and newline
            }
            Serial.print(str_ii);
            str_ii = "";
        }
    }
}

```

When executing this method, in application Arduino Bluetooth Controller (HM-10 Module) app i see the text AT+HELP, but there is no reaction / response from the bluetooh. Neither in the Arduino Bluetooth Controller (HM-10 Module) application nor in the Arduino serial monitor

What am I doing wrong?

Thank you.

# Answer
First thing first you can see all AT commands available from the data sheet available from datasheet

Second to get strings from Serial to BTserial you can just use `c = Serial.readStringUntil('\n');` like here

```
#define BT_RX           0
#define BT_TX           1
#define BT_Serial       Serial1
#define BT_Timeout      100

String c, c2;

void setup() {
  BT_Serial.setTX(BT_TX);
  BT_Serial.setRX(BT_RX);
  BT_Serial.begin(9600);//baudrate
  BT_Serial.setTimeout(BT_Timeout); //set bluetooth read/write timeout

  Serial.begin(9600);
  Serial.setTimeout(100);
  delay(100);
}

void loop()
{
  if (Serial.available()) {
    c = Serial.readStringUntil('\n');
    Serial.println(c);
    BT_Transmit_AT(c);
  }
  if (BT_Serial.available()) {
    c2 = BT_Serial.readStringUntil('\n');
    Serial.println(c2);
  }
  delay(20);
}

void BT_Transmit_AT(String data) { //send AT commands
  unsigned long current_time = millis();
  while (BT_Serial.available() > 0) {
    if (millis() - current_time > 100){ //timer to get out incase not receiving anything
      Serial.println("Timeout");
      break;
    }
  }
  BT_Serial.print(data);
}

```

And lastly you need to make sure your HM-10 is genuine/has genuine firmware installed or it's a clone. Check if it respond to "AT" with "OK" at all. If it does then it's genuine and you can continue. If it doesn't then you need to flash genuine firmware onto it, then upgrade from there if you. Here is a good tutorial on flashing the genuine firmware onto the module.

After that you can follow a tutorial here on upgrading the firmware from an older genuine firmware. You can get the latest genuine firmware from the Manufacture's website.
> 1 votes

---
Tags: arduino-mega, ble
---


# Question
Title: Arduino Nano: Send a few bytes over Serial with as little delay as possible
My scenario is the following:

I have a few buttons connected to an Arduino Nano, which is connected to my PC over Serial. Now I want to send a few bytes whenever a button is pressed, to be interpreted by my Computer. However, I noticed a significant, unregular delay (feels like something between almost instantaneous transmission up to a delay of easily ~300 milliseconds), until the message is received by my computer, and I want to get rid of that.

I understand that Arduinos make use of a Serial Buffer, and only send over data once the buffer is full (or some sort of timeout probably), and I think that is the culprit - however I don't see a way of forcing the Arduino to send the data ASAP. I tried just sending over exactly 64 bytes (which, according to what I read, should be the buffer size), but that doesn't help as well (can I however decrease the buffer size or is there a way to send bytes exactly until the buffer is full?)

I don't think baudrate changes anything either, as I'm experiencing problems with the "ping" rather than with the bandwidth (and I also tried anything from 9600 to 115200).

Maybe I'm also completely wrong and the delay happens on the side of my computer, but I don't know if there is anything to change that - I'm looking at the Serial Monitor or at a small `pyserial` script, both of which have the delay:

```
arduino = serial.Serial(serial_port}, 115200, timeout=.1)
while True:
    data = arduino.readline().decode("UTF-8").strip()
    if data:
        print(data)

```

The code on the Arduino-side boils down to:

```
#include <digitalWriteFast.h>

#define button1_pin 2

int button1_state = 0;
int last_button1_state = 0;

void setup() {
  Serial.begin(115200);
  pinMode(button1_pin, INPUT_PULLUP);
  while (!Serial) { delay(50); }
  Serial.println("Started");
}

void loop() {
  button1_state = digitalReadFast(button1_pin);

  if (button1_state != last_button1_state) {
    if (button1_state == LOW) {
      Serial.write("d\n");
    } else {
      Serial.write("u\n");
    }
    last_button1_state = button1_state;
    delay(20);
  }
}

```

Then there's also the weirdest thing which I noticed but am not sure about if it's at all plausible: When the window of the Serial Monitor (the one that ships with the Arduino IDE) is not completely full (meaning there are only some 1-20 rows and the window doesn't need to scroll), I notice the aforementioned delay, but if the Serial Monitor is full (so new content will be on the last line and the window automatically scrolls a bit), I don't. As soon as I clear the output of the window, it's there again. I don't know what to make of this observation, because I definitely don't have any reasonable clue why that may be the case, so maybe it's also just my imagination :shrug:. Using the python-code there is no such behaviour, and the transimission always seems to have a ping of at least 200-300ms.

I hope my problem is understandable, and like I said I am really unsure what even is the culprit (and I see that it's also highly likely that it's on the side of my computer), but does anybody have any idea how I can decrease this delay? Thanks a lot!

# Answer
> 3 votes
> "Slowing down to speed up". *\- a Chinese proverb*

The problem is with your python code. Not sure what your computer's operating system is, but if you are using Mac or Linux, if you run `top` on command line, you will see you have a high CPU utilization causing by your python script. This is because your your python `while True` loop constantly looping without giving the chances for other processes on your computer to use the CPU, bear in mind that Linux, MacOS or Windows are not designed as a real-time operating system.

So how to solve the problem? put your `while True` loop to sleep for a short period of time, this allows other processes on your computer to have chance to run and you will see the CPU utilization go down significantly and everything will running smoothly.

```
import time
arduino = serial.Serial(serial_port}, 115200, timeout=.1)
while True:
    data = arduino.readline().decode("UTF-8").strip()
    if data:
        print(data)
    time.sleep(0.01)

```

With this slight delay, I've seen some CPU utilisation drop from 90% to 3.5%. This is quite a common mistake that many python programmers made, including some quite experienced programmers who are not familiar with network programming.

Try it out and let me know.

# Answer
> 0 votes
Answering my own question in case anybody experiences the same problem eventually: @hcheung's answer was almost correct after all - see the comments to that question.

Important take-away however: **don't trust the Serial Monitor or Python's `print` to check how quickly the arduino and your computer communicate**!

When ponging back to the Arduino to let it trigger an LED, I noticed that the actual transmission is definitely faster than my eye, far from the 200ms delay I mentioned in the question. So the problems for me were

a) the *other* code I used to test the connection but didn't post here was faulty
b) The delay I saw in the Serial Monitor/python's `print` is **not the delay of the serial communication** but apparently somewhere later in the printing of the respective content.

Serial communication is definitely faster than the human eye :)

---
Tags: serial, arduino-nano, communication, speed
---


# Question
Title: Arduino fast ADC sampling--which burst control is best?
If one wants to do quick bursts of free-running ADC conversions, should one pause and restart using:

The ADC enable bit: `bitClear(ADCSRA,ADEN)` & `bitSet(ADCSRA,ADEN)`,

The interrupt enable bit `bitClear(ADCSRA,ADIE)` & `bitSet(ADCSRA,ADIE)`,

The start conversion bit `bitClear(ADCSRA,ADSC)` & `bitSet(ADCSRA,ADSC)`,

The auto-trigger enable bit `bitClear(ADCSRA,ADATE)` & `bitSet(ADCSRA,ADATE)`,

or do you need some more complicated combination of the bits?

Here's some code where I'm trying to trigger a pulse and burst of samples and then report back to the host computer:

```
const int numSamples = 20;
const byte startPin = PD0; // start signal (pullup)
const byte pulsePin = PD6; // Normally low
const int pulse_us = 10 ; // output pulse length

int16_t sampleData[numSamples];
volatile int sample;
unsigned long t0, t;

// state machine:
typedef enum { STATE_NONE,  // idle
               STATE_SAMPLING, // record ADC
               STATE_DONE, // report data
 } states;
// current state-machine state
volatile states state = STATE_NONE;

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

  pinMode(startPin,INPUT_PULLUP);
  pinMode(pulsePin,OUTPUT);
  // Clear ADC
  ADCSRA = 0;
  ADCSRB = 0;
  ADMUX = 0;
  ADMUX |= (0b0000 << MUX0); // Choose ADC channel 0
  ADMUX |= (0b01 << REFS0);  // Choose VCC reference voltage
  bitSet(ADMUX,ADLAR);  // ADC left align ADC result into ADCH register

  // sampling rate is [ADC clock] / [prescaler] / [conversion clock cycles]
  // for Arduino Uno ADC clock is 16 MHz and a conversion takes 13 clock cycles
  //ADCSRA |= (0b101 << ADPS0); // /32 : 16M/32/13=38461Hz 26us
  //ADCSRA |= (0b100 << ADPS0); // /16 : 16M/16/13=76923Hz 13us 10 bit precision
  ADCSRA |= (0b011 << ADPS0); // /8  : 16M/8/13=153.8KHz 6.5us low precision
  //ADCSRA |= (0b010 << ADPS0); // /4  : 16M/4/13=307.6KHz 3.2us lower precision
  //ADCSRA |= (0b001 << ADPS0); // /2  : 16M/2/13=615.4Hz 1.6us  bad precision

  ADCSRB |= (0b000 << ADTS0); // Choose free running trigger mode

  bitSet(ADCSRA,ADATE); // enable auto trigger mode per ADSCRB:ADTSx
  bitSet(ADCSRA,ADIE);  // enable interrupts when measurement complete
  bitSet(ADCSRA,ADEN);  // enable ADC
  bitSet(ADCSRA,ADSC);  // start ADC measurements

}

ISR(ADC_vect) // Record samples
{
  sampleData[sample++] = ADC;  // read 10bit value from ADC
  if (sample >= numSamples) {
    bitClear(ADCSRA,ADEN); // stop recording
    state = STATE_DONE;
  }
}

void report(){
  t = micros()-t0;  // calculate elapsed time
  Serial.print("Sampling frequency: ");
  Serial.print((float)1000000/t);
  Serial.println(" KHz");
  for (int i = 0; i < numSamples; i++){
    Serial.print(i);
    Serial.print(' ');
    Serial.print(sampleData[i]);
    Serial.println();
  }
}

void startSampling(){
  sample = 0;
  t0 = micros();
  digitalWrite(pulsePin,HIGH);
  bitSet(ADCSRA,ADEN); // start ADC
  delayMicroseconds(pulse_us);
  digitalWrite(pulsePin,LOW);

}

void loop()
{
  switch (state){
    case STATE_NONE:
      if(digitalRead(startPin)==LOW){
        startSampling();
        state = STATE_SAMPLING;
      }
      break;
    case STATE_SAMPLING:
      break;

    case STATE_DONE:
        report();
        state = STATE_NONE;
        break;
    default:
    ;;
  }
}

```

Toggling `ADEN` was my first thought, but `ADIE` seems as if it would be faster, and `ADSC` seems cleanest, if it works to modulate free-running ADC mode. Which would be fastest and cleanest?

I have a Nano on order, but nothing available for testing right now.

# Answer
After some bumbling around, several bit are important:

```
ADCSRA &= ~(bit(ADATE) | bit (ADSC) | bit (ADIE)); // Disable

ADCSRA |=   bit(ADATE) | bit (ADSC) | bit (ADIE); // Enable

```

The interrupt enable bit `bitClear(ADCSRA,ADIE)` & `bitSet(ADCSRA,ADIE)`, would stop the current ADC measurement from triggering an interrupt event.

The auto-trigger enable bit `bitClear(ADCSRA,ADATE)` & `bitSet(ADCSRA,ADATE)`, triggers a new conversion as soon as the current one finishes.

The start conversion bit `bitClear(ADCSRA,ADSC)` & `bitSet(ADCSRA,ADSC)`, is important for kicking off the first conversion.

The ADC enable bit `bitClear(ADCSRA,ADEN)` & `bitSet(ADCSRA,ADEN)`, turns the ADC subsystem on and off, but there is a bit of a delay on start up.

Ultimately I left free-running automatic ADC enabled and switched the data recording on and off using the `ADCSRA&bit(ADIE)` as a "BURST" state variable. I think this is good enough for generic impulse-response testing:

```
//: ArduinoPulseADCSample.ino -- Pulse a pin and sample response on ADC
// For Arduino Uno/Nano/mega
// https://github.com/drf5n/foxyPulseInduction_Discrimination/tree/discrimination/ArduinoPulseADCSample
// Adapted from  http://www.gammon.com.au/forum/?id=11488&reply=5#reply5
//          and https://github.com/pedvide/ADC/tree/master/examples/analogContinuousRead
//
// This code emits a digital pulse on A1 and collects a sample of highspeed ADC from A0
// It sets up a free-running ADC to quickly record a set of ADC data in
// response to the pulse.  The size of the pulse, pins, number of samples,
// speed of sampling, etc... are all configurable.
// The ADC interrupt handler controls the pulse length and filling the sample buffer
//
// Serial Commands:
//
//  *  Write v and press enter on the serial console to get the value
//  *  Write c and press enter on the serial console to check that the conversion status,
//  *  Write s to stop the conversions, you can restart it writing r.
//  *  Write r to restart the conversions.
//  *  Write p to emit a pulse and record a burst of values
//  *  Write d to see the data recorded during the burst (compatible with SerialPlotter)
//  *  Write m to see metadata about the sample size and interval
//
//  Loopback test with a jumper or RC network between A1 and A2.
//

// Configurables:
const byte adcPin = 0; // A0 -- Pin to read ADC data from
const byte pulsePin = A1; // Next to A0 -- pin to pulse
const byte oneshot_pin = 12; // OC1B pin on Mega, controlled by Timer1
const int pulse_us = 50; // pulse duration
const int numSamples = 20; // sample set
// Change the sampling speed with the prescaler config in setup()

volatile uint16_t samples[numSamples];
volatile int sample = 0;    // position in sample state variable
#define BURST (ADCSRA & bit(ADIE)) /* Sampling burst state variable */
int adcReading;
unsigned long sampleEnd;
unsigned long pulseStart, pulseEnd;

// ########## Timer1 One-shot functions
// The one shot pulses are output on Digital pin OC1B (Arduino Uno D10, Mega D12, Nano D3)
// Modified by Dave Forrest 2020-01-11 for Timer 1
// Based on Josh Levine's Nov 23, 2015 work at https://github.com/bigjosh/TimerShot/blob/master/TimerShot.ino

// Setup the one-shot pulse generator and initialize with a pulse width that is (cycles) clock counts long
#define OSP_SET_WIDTH(cycles) (OCR1B = 0xffff-(cycles-1))
void osp_setup(uint16_t cycles) { // 1 idles, 0xffff never matches, 2-0xfffe makes pulses
  const byte prescaler = 0b010; // Choose /8 for 0.5us resolution
                                // 0b001: /1,      16MHz, 62.5ns resolution, 4ms max
                                // 0b010: /8,       2MHz,  0.5us resolution, 32ms max
                                // 0b011: /64,    250kHz,  4us  resolution, 263ms max
                                // 0b100: /256,  62.5kHz  16us  resolution, 1.048s max
                                // 0b101: /1024, 15625Hz, 64us  resolution, 4.194176s max
  TCCR1B =  0;      // Halt counter by setting clock select bits to 0 (No clock source).
  // This keeps anyhting from happening while we get set up
  TCNT1 = 0x00;     // Start counting at bottom.
  OCR1A = 0;      // Set TOP to 0. This effectively keeps us from counting because the counter just keeps resetting back to 0.
  // We break out of this by manually setting the TCNT higher than 0, in which case it will count all the way up to MAX and then overflow back to 0 and get locked up again.
  OSP_SET_WIDTH(cycles);    // This also makes new OCR values get loaded frm the buffer on every clock cycle.
  TCCR1A = 0b11 << COM1B0  | 0b11 << WGM10; // OC1B=Set on Match, clear on BOTTOM. Mode 15 Fast PWM.
  TCCR1B = (0b11 << WGM12) | (prescaler << CS10); // Start counting now. WGM 15=0b1111  to select Fast PWM mode
  // Setup the OC1B pin for one-shot output:
  //DDRB |= _BV(2);     // Uno Set pin to output (Note that OC1B = GPIO port PB2 = Arduino Uno Digital Pin 10)
  DDRB |= _BV(6);     // Mega Set pin to output (Note that OC1B = GPIO port PB6 = Arduino Mega Digital Pin 12)
  //DDRD |= _BV(3);     // Nano Set pin to output (Note that OC1B = GPIO port PD3 = Arduino Nano Digital Pin 3)
}

// Setup the one-shot pulse generator to idle:
void osp_setup() {
  osp_setup(1);  // 1 puts it in idle mode, 0xffff never triggers, 2-0xfffe produces pulses.
}

// Macro to Fire a one-shot pulse. Use the most recently set width.
#define OSP_FIRE() (TCNT1 = OCR1B - 1)

// Macro to Test there is currently a pulse still in progress
#define OSP_INPROGRESS() (TCNT1>0)

// Macro to Fire a one-shot pulse with the specififed width.
// Order of operations in calculating m must avoid overflow of the unint16_t.
// TCNT2 starts one count lower than the match value because the chip will block any compare on the cycle after setting a TCNT.
#define OSP_SET_AND_FIRE(cycles) {uint16_t m=0xffff-(cycles-1); noInterrupts();OCR1B=m;TCNT1 =m-1;interrupts();}

// ##########  End of Timer1 One-shot functions
ISR(TIMER1_OVF_vect) { //When overflow...
  //  OCRA1=ICR1; // Constant off in WGM 14, COM1A1:0==0b11
  TCCR1B &= ~(0b111 << CS10) ; //turn off clock
}

//######### ADC Bit-bang for free-running capture of A0
void adc_setup_freerunning(const byte adcPin){
  // set the analog reference (high two bits of ADMUX) and select the
  // channel (low 4 bits).  this also sets ADLAR (left-adjust result)
  // to 0 (the default).
  ADMUX = bit (REFS0) | (adcPin & 0x07);

  // Set the ADC ADPSx prescaler flags to control sampling speed/accuracy
  ADCSRA &= ~(bit (ADPS0) | bit (ADPS1) | bit (ADPS2)); // clear prescaler bits

  //ADCSRA |= 0b001 << ADPS0;   //   2    5 bit,
  //ADCSRA |= 0b010 << ADPS0;   //   4    6 bit, 5.36us
  //ADCSRA |= 0b011 << ADPS0;   //   8    9 bit, 6.51us
  ADCSRA |= 0b100 << ADPS0;   //  16   10 bit, 13us
  //ADCSRA |= 0b101 << ADPS0;   //  32     10 bit, 26us
  //ADCSRA |= 0b110 << ADPS0;   //  64     10 bit, 52us
  //ADCSRA |= 0b111 << ADPS0;   // 128     10 bit, 104us

  //enable automatic conversions, start them and interrupt on finish
  //ADCSRA |= bit(ADATE) | bit (ADSC) | bit (ADIE);
    ADCSRA |= bit(ADATE) | bit (ADSC) ;

}

void setup ()
{
  Serial.begin (115200);
  //pinMode(pulsePin, OUTPUT);
  osp_setup(); // Config Mega Digital 12 for oneshot output
  adc_setup_freerunning(adcPin);

}  // end of setup

// ADC complete ISR
ISR (ADC_vect)  // Store ADC burst values
{
  if (sample >= numSamples) // watch off-by-one
  {
    ADCSRA &= ~bit(ADIE);  // end of sampling burst so stop interrupting
    return;
  }
  // Handle samples
  samples[sample++ ] = ADC;
  //if ( sample == 0){
   // OSP_SET_AND_FIRE(pulse_us * 2); //
  //}
}  // end of ADC_vect

void loop ()
{
  char c;
  char buff[80];
  unsigned long sampleDuration;
  unsigned long pulseDuration;
  // if last reading finished, process it

  // if we aren't taking a reading, start a new one

  if (Serial.available()) {
    c = Serial.read();
    switch (c) {
      case 'c': // Converting?
        Serial.print("ADCSRA: ");
        Serial.println(ADCSRA, BIN);
        break;
      case 's': // stop conversions
        ADCSRA &= ~(bit (ADSC) | bit (ADIE));
        break;
      case 'r': // restart conversions
        ADCSRA |= bit (ADSC) | bit (ADIE);
        break;
      case 'v':
        adcReading = ADC;
        Serial.print(adcReading);
        Serial.print(' ');
        Serial.print((0.5 + adcReading) * 5.0 / 1024, 4);
        Serial.println(" V");
        break;
      case 'm':
        {
          unsigned long sampleDuration = sampleEnd - pulseStart;
          unsigned long pulseDuration  = pulseEnd - pulseStart;

          Serial.print("# Pulse: ");
          Serial.print(pulseDuration);
          Serial.print("us and ");
          Serial.print(numSamples);
          Serial.println(" samples.");
          Serial.print("# Time: ");
          Serial.print(sampleDuration);
          Serial.print("us burst of ");
          Serial.print(numSamples);
          Serial.print(" samples at ");
          Serial.print(1.0 * (unsigned long)(sampleEnd - pulseStart) / numSamples);
          Serial.println("us/sample");
          sprintf(buff, " sampleEnd, pulseEnd, pulseStart %02lu : %02lu : %02lu \n", sampleEnd, pulseEnd, pulseStart);
          Serial.print(buff);
          break;
        }
      case 'p': // start pulse
        sample = 0;  // reset sample SV
        pulseStart = micros();
        OSP_SET_AND_FIRE(pulse_us * 2); // pulse outside ISR
        ADCSRA |= bit(ADIF) | bit(ADIE); // clear existing ADInterruptFlag and enable ADC Interrupts
        while(BURST); // block until burst done
        sampleEnd = micros(); // Record times
        pulseEnd = pulseStart + pulse_us;
        break;
      case 'D':
      case 'd': {// report Data
          sampleDuration = sampleEnd - pulseStart;
          for (int ii = 0 ; ii < numSamples ; ii++) {
            if (c == 'D') {
              Serial.print(ii * sampleDuration / numSamples);
              Serial.print(' ');
            }
            Serial.println(samples[ii]);
          }
        }
        break;
      case ' ':
      case '\n':
      case '\r':
        break;
      case 'h':
      case '?':
      default:
        {
          Serial.println("\nArduinoPulseADCSample.in -- Pulse A1 and read a burst of samples from A0\n"
                         "based on serial commands");
          Serial.println("# https://github.com/drf5n/foxyPulseInduction_Discrimination/tree/discrimination/ArduinoPulseADCSample\nCommands: [vcsrpdm] ?");
          Serial.println("Commands:\n"
                         "p: Pulse -- Start a pulse cycle on A1 and record data on A0\n"
                         "d,D: Data -- Dump the data from the last pulse\n"
                         "m: Metadata -- Print the length of pulse, number of samples and rate\n"
                         "v: Voltage -- Conver voltage on A0\n"
                         "c: Converting? -- show ADCSSRA register\n"
                         "h?: Help -- Print this\n"
                        );
        }
        break;
        ;;
    }
  }

  // do other stuff here

}  // end of loop

```

This is the output from the p,m,d commands with a jumper connecting pin 12 to A0 with the /16 prescaler:

```
# Pulse: 50us and 20 samples.
# Time: 276us burst of 20 samples at 13.80us/sample
 sampleEnd, pulseEnd, pulseStart 19270968 : 19270742 : 19270692
0
1020
1023
1023
1023
3
0
0
0
0
0
0
0
0
0
0
0
0
0
0

```

And again with the /8 prescaler. 7.2us/sample or 139Ksamples/sec for 8-9bits isn't bad:

```
# Pulse: 50us and 20 samples.
# Time: 144us burst of 20 samples at 7.20us/sample
 sampleEnd, pulseEnd, pulseStart 4229952 : 4229858 : 4229808
0
792
1020
1022
1022
1020
1022
1022
1022
305
3
0
0
0
0
0
0
0
0
0

ArduinoPulseADCSample.in -- Pulse A1 and read a burst of samples from A0
based on serial commands
# https://github.com/drf5n/foxyPulseInduction_Discrimination/tree/discrimination/ArduinoPulseADCSample
Commands: [vcsrpdm] ?
Commands:
p: Pulse -- Start a pulse cycle on A1 and record data on A0
d,D: Data -- Dump the data from the last pulse
m: Metadata -- Print the length of pulse, number of samples and rate
v: Voltage -- Conver voltage on A0
c: Converting? -- show ADCSRA register
h?: Help -- Print this

```

Here's an R-C pulse-decay trace on the Serial Plotter with a 22K resistor across A0&12 and a 22uF capacitor from GND to A0.
> 1 votes

---
Tags: adc
---