title: I2C libraries for ATTiny85?

text:
# Question
Title: I2C libraries for ATTiny85?
I want to transmit I2C data, using a Digispark ATTiny85 board:

I've found the following I2C libraries. Which one is more lightweight, stable, bug-free, efficient, powerful, and easy to use?

Wire seems under-featured:

> "the default Arduino Wire() library does not support changes in bus speed or feature proper clock stretching support. This makes the default library only marginally functional" https://www.maxbotix.com/articles/095.htm

What other I2C libs are available for ATTiny? In the IDE i see Digispark SoftSerial, OneWire, and VirtualWire.

How do they all compare?

---

Note, these other answers do **not** seem relevant to my question:

# Answer
> 2 votes
> I want to transmit I2C data...

A little vague.

Transmit to what device? How fast is your data rate (100kHz, 400kHz)? Your only transmitting and not reading anything back? What is the idling voltage of your I2C bus (to then ask if you have chosen correct pull-up resistor values for your intended bus speed)?

You mention that the Wire library doesn't support core clock speed changes without some hacking, but don't talk about the speed you intend to run the microcontroller or how fast you intend to use the I2C. I can guess 400kHz, since you brought up speed, but that's not a great way to answer a question.

I have using the Wire library on an Arduino UNO at I2C bus rate of 100kHz and it's worked fine for my needs. I got bytes in and out.

At this point, the best suggestion I'd have is that if one of the above libraries you listed does not support a feature you'd like, fork it, and add support for your feature yourself. If you're only transmitting to one slave device, then you shouldn't need to worry about bus arbitration, like the TinyWire does. Adafruit is okay for the most part, but they seem (to me) slow to fix bugs and maintain code. But don't let the code's age get to you. I2C was created back in 1982, and you're still using it... :-P

Here's how I would approach choosing a library:

* Define features you need
* Look for a library which has most of those features
* Add any new features you need
* Possibly share your added features with the community with a Pull Request

# Answer
> 1 votes
bHogan seems to be the original developer of TinyWireM and TinyWireS. Andreas Spiess ("The guy with the Swiss accent") used rambo's implementation of the TinyWire library for his I2C sensor, and rambo on GitHub and bHogan on arduino.cc seem to be the same person...

I've also used rambo's TinyWire library, and managed to make it work. Adafruits version of TinyWire seems to be a fork of rambo's code.

---
Tags: i2c, attiny85, digispark
---


# Question
Title: expected primary-expression before ',' token
EDIT: have solved the problem. It was missing the quotation marks around each letter. Thanks for your help, st2000!

---

I am very new to Arduino and C++ (coding in general!). Have copied an example code, only modifying the notes to make my own tune. But when I click 'verify', I am getting the error above, and I can't for the life of me, work out what is wrong! I've searched and read several forums and FAQs, but am just coming up blank. This is the code I have, where the error is occuring:

```
  int melody[]={
    a,C,D,
    a,a,C,D,D,C,
    C,C,D,D,C,
    C,D,E,F,E,D,C};

```

Any help would be greatly appreciated!

# Answer
> 0 votes
To answer your question we will assume your project is based on the Melody example at www.arduino.cc.

Likely you wanted to enter the ASCII values of these letters into an array of type char (type int would work as well. But, in some cases, char would be more efficient). To do this you need to place single quotes around each letter. Specifically, you need to change your code:

```
int melody[]={ a,C,D, a,a,C,D,D,C, C,C,D,D,C, C,D,E,F,E,D,C};

```

...so that your line of code look like this:

```
int melody[]={'a','C','D','a','a','C','D','D','C','C','C','D','D','C','C','D','E','F','E','D','C'};

```

---
Tags: c++
---


# Question
Title: How to modify this code to simulate a binary encoder?
I have come across the following SPI slave code at this site:

```
#include <SPI.h>

char buf [100];
volatile byte pos;
volatile bool process_it;

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

  // turn on SPI in slave mode
  SPCR |= bit (SPE);

  // have to send on master in, *slave out*
  pinMode (MISO, OUTPUT);

  // get ready for an interrupt
  pos = 0;   // buffer empty
  process_it = false;

  // now turn on interrupts
  SPI.attachInterrupt();

}  // end of setup

// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR;  // grab byte from SPI Data Register

  // add to buffer if room
  if (pos < sizeof buf)
    {
    buf [pos++] = c;

    // example: newline means time to process buffer
    if (c == '\n')
      process_it = true;

    }  // end of room available
}  // end of interrupt routine SPI_STC_vect

// main loop - wait for flag set in interrupt routine
void loop (void)
{
  if (process_it)
    {
    buf [pos] = 0;
    Serial.println (buf);
    pos = 0;
    process_it = false;
    }  // end of flag set

}  // end of loop

```

How to modify the above code so that it responds to input clock signal just like in this SSI protocol? Uno or Nano can be used.

Basically I want to let an arduino act as an absolute encoder so that it will transmit 13-bit binary data(it can be any random fixed binary data) as shown in the above SSI protocol. So the Arduino will output 13-bit binary data along with with start bit and tm taken into account as shown in the document above without parity.

**The master's code I plan to use:**

```
const int CLOCK_PIN = 2;
const int DATA_PIN = 3;
const int BIT_COUNT = 16;
void setup() {
    pinMode(DATA_PIN, INPUT);
    pinMode(CLOCK_PIN, OUTPUT);
    digitalWrite(CLOCK_PIN, HIGH);
    Serial.begin(115200);
  }
void loop() {
    float reading = readPosition();
    Serial.println(reading,2);
    delay(25);
  }

//read the current angular position
float readPosition() {
 unsigned long graysample = shiftIn(DATA_PIN, CLOCK_PIN, BIT_COUNT);
 delayMicroseconds(100); // Clock must be high for 20 microseconds before a new sample can be taken
unsigned long binarysample = grayToBinary32(graysample);
 return ((binarysample * 360UL) / 65536.0); // ouptut value from 0 to 360 with two point percision
}
//read in a byte of data from the digital input of the board.
unsigned long shiftIn(const int data_pin, const int clock_pin, const int bit_count) {
 unsigned long data = 0;
 for (int i=0; i<bit_count; i++) {
 data <<= 1; // shift all read data left one bit.

 //digitalWrite(clock_pin,LOW);
 PORTD &= ~(1 << 5); // clock pin goes low
 delayMicroseconds(1);
 //digitalWrite(clock_pin,HIGH);
 PORTD |= (1 << 5); // lock pin goes high
 delayMicroseconds(1);
 data |= digitalRead(data_pin); // cat the new read bit to the whole read data.
 }
 return data;
}
unsigned int grayToBinary32(unsigned int num)
{
 num = num ^ (num >> 16);
 num = num ^ (num >> 8);
 num = num ^ (num >> 4);
 num = num ^ (num >> 2);
 num = num ^ (num >> 1);
 return num;
}

```

# Answer
> 0 votes
You may try to bit-bang the protocol using direct port access. This is less convenient, but way faster than `digitalWrite()`. Below is an example, untested program. I am assuming the pinout is

* data = PB0 = digital 8
* clock = PB1 = digital 9
* pins PB2 – PB5 (10 – 13) are unused

**Edit**: This updated program uses the clock as an input, and the data as an output. The previous version used both lines as outputs, which was due to a misunderstanding of mine.

```
#include <avr/io.h>

int main(void)
{
    uint16_t data = 0x155;

    DDRB  |= _BV(PB0);
    PORTB |= _BV(PB0);
    TCCR1B = _BV(CS10);  // start timer 1 @ F_CPU
    loop_until_bit_is_clear(PINB, PB1);

    for (;;) {
        loop_until_bit_is_set(PINB, PB1);
        PORTB = data & 1;
        data >>= 1;
        TCNT1 = -304;        // 20 us * 16 MHz - 16 cycles
        TIFR1 |= _BV(TOV1);  // clear overflow flag
        while (bit_is_set(PINB, PB1)) {
            if (bit_is_set(TIFR1, TOV1)) {  // timer overflowed
                PORTB = 1;  // data high
                data = 0x155;
                loop_until_bit_is_clear(PINB, PB1);
                break;
            }
        }
    }
}

```

This should be able to operate at frequencies up to about 200 – 250 kHz. There is a delay of about 0.5 µs between the rising edges of the clock and the data been sent out, with a jitter of 3 clock cycles.

The data word is sent least significant bit first, contrary to what the protocol diagram shows. However, if you send arbitrary data, this should not be an issue.

Note that this is a pure avr-libc program, which does not use the Arduino core. It uses polling to check the inputs and the timer. The interrupts are never enabled.

---
Tags: arduino-uno, arduino-nano
---


title: Arduino recognize specific sound?

text:
# Question
Title: Arduino recognize specific sound?
I'm wondering if Arduino is able to not just measure sound and work based on hearing a sound that is "loud enough", but if it is able to identify a specific sound (say the first few seconds of a song). Is this possible, and how would one go about doing so?

If identifying the first few seconds of a song isn't really feasible, is it at least possible to do so with a consistent (but particular) pitch (rather than a general loudness threshold)?

# Answer
No, you cannot recognize a song with an Arduino. It doesn't have enough computing power. I think most solutions, that recognize a song, are based on some kind of machine learning or similar, which is totally out of scope for an Arduino. For this you need a real processor like on a Raspberry Pi or similar Single Board Computers.

Identifying a specific pitch/frequency in a sound signal is possible, but you shouldn't expect great accuracy. As Duncan already wrote in his answer, you need a Fourier transformation for this. It transforms the audio signal (voltage level dependent on time) into the frequency domain (amplitude dependent on frequency). So, if you do a fourier transformation on a short audio signal, you get data about, what frequencies are in that signal with which amplitudes. You can then wait for a peak in a specific frequency range.

Doing a FFT (Fast Fourier Transformation) on an Arduino is slow and not accurate. You also only have very limited memory. So your analysed audio signals will be rather short.

---

There is another way to detect a specific pitch/frequency, which is more a hardware task. You can feed the audio signal into an RC resonator circuit, which is tuned to the frequency, that you are interested in. The circuit will amplify the frequency, that it is tuned to, and dampen all other frequencies (of course it is not really one specific frequency, but a small range of frequencies). The resulting signal can then be checked for threshold values, since it only contains frequencies around the tuning frequency.
> 0 votes

# Answer
As stated in other answers, sound recognition is completely out of the realm of what an Arduino can do, but recognizing a specific pitch is possible.

However, contrary to previous answers, I would recommend *against* using an FFT. The FFT is the right tool when you need to get *all* the frequency components. It is, however, overkill when you want to look at a single frequency. Given the low processing power at your disposal, I suggest you try instead an homodyne detection scheme. An Arduino Uno, or similar board, has enough resources to sample an input at 9.6 kHz, and extract in real time a specific frequency component. See for example this homodyne detection program.
> 2 votes

# Answer
It sounds like you need to do Fourier analysis on the sound. (Breaking up the sound into its component frequencies.) Most Arduinos are based on AVR chips, which do not have hardware support for floating point math. They use software to do floating point, which makes them a poor choice for this sort of thing.

There are FFT libraries for Arduino, but they will be slow and fairly crude. You'd probably be better off using a board like a Raspberry Pi that has an ARM processor for signal processing like this.
> 1 votes

---
Tags: audio, sound
---


title: Could i use a stepper motor?

text:
# Question
Title: Could i use a stepper motor?
i want to make a 3-axis gimbal with arduino but brush-less motors seem incredibly hard so would stepper motors work for this purpose?

if their is a way if not, is how can i connect 3 gimbal motors to one arduino board and control them seperately? (links if possible)

# Answer
> 1 votes
DC Motors with a feedback line (so called PID Controller; https://en.wikipedia.org/wiki/PID\_controller) would be the best way to do it. You need the motor as an actor and some sensors that sense the direction of the axis's of the gimbal. The PID controller should be very fast for smooth operation. (Perhaps an ESP32 is a better MCU for this purpose).

The PID controller uses a motion sensors.

It's good to have strong motors that do not react "nervous" on on voltage changes. You probably will have to use motors with gears. Even fast PID controller won't be able to keep your camera from turning cartwheels if a 10.000 cycles per minute racing motor gets full voltage applied.

I searched the internet for videos of such a setup but the only thing I found, are the commercial (?) gimbal "alexmos" "how to" videos. I'm with you that it is hard to build such a gimbal without much knowledge of how PIDs work. I'm also not sure if there is an arduino that's fast enough to realize a PID that gets its feedback from motion sensors and drives dc motors with this information, then get's feedbach of the motor movements (from the motion sensors) and so on.

And probably a better/stronger servo and and very fast PID setup might eventually smooth the gimbals movements.

Here is a link that might help you as a start point for PID (if you are not discouraged yet): https://www.youtube.com/watch?v=9TTDmWiMg\_Y

And even professional setups can make problems: (It's a matter of the PID parameters) https://www.youtube.com/watch?v=UeeTXH2Qv2o

# Answer
> 0 votes
A stepper motor might work, but it is certainly not the best choice for what you try.

Instead you should use brushless motors. There are not so hard to use, as you think. Driving them directly is difficult, but no one does that. Instead just buy an ESC (Electronic Speed Control) (one for each brushless motor). That is an extra chip/board, where you need to connect a PWM signal and ground from the Arduino and the power source of the motor. Then connect the motor to the ESC and you will be able to control the brushless motor with a simple PWM signal.

For further information you can read this post in the Arduino forum, or you just google. There is plenty of information the web about ESCs.

---
Tags: motor, stepper
---


# Question
Title: Cannot understand why this code work but this not
I've done a simple aurduino sketch, I have this code, and this don't work:

```
#define voltageInput A0
int qntR;
float mr;
float qr;
float Distanza;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(voltageInput,INPUT);
  mr=(130-20)/float(1023-205);
  qr=20-mr*205;
  Serial.print(mr,4);
}

void loop() {
  // put your main code here, to run repeatedly:
  qntR=analogRead(voltageInput);
  Distanza=mr*qntR+qr;
  Serial.print("Distanza: ");
  Serial.print(Distanza);
  Serial.print(" cm");
  Serial.println("");
}

```

And the I have this code:

```
#define voltageInput A0
int qntR;
float mr;
float qr;
float Distanza;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(voltageInput,INPUT);
  mr=(130-20)/(1023-205);
  qr=20-mr*205;
  Serial.print(mr,4);
}

void loop() {
  // put your main code here, to run repeatedly:
  qntR=analogRead(voltageInput);
  Distanza=mr*qntR+qr;
  Serial.print("Distanza: ");
  Serial.print(Distanza);
  Serial.print(" cm");
  Serial.println("");
}

```

In which I have delete the `float` from `mr=(130-20)/float(1023-205)`;,and if I delete the float the code stop working (`mr` is always equal to 0), why?

# Answer
> 3 votes
Your problem is that you are doing integer maths.

```
mr = (130-20)/(1023-205)

```

reduces to:

```
mr = 110/818

```

Which normally equates to:

```
mr = 0.135

```

But since all those numbers are integers the result is an integer, and is truncated at the decimal point, which means that `mr` is assigned:

```
mr = 0

```

You can force floating point maths by either including a decimal point in one of the numbers, or adding the suffux `f`:

```
mr = (130-20)/(1023-205.0)

```

or

```
mr = (130-20)/(1023-205f)

```

Or casting a portion of the sum to a float as your other code does.

---
Tags: arduino-uno, float
---


title: Mosfet controlled motor runs while LOW

text:
# Question
Title: Mosfet controlled motor runs while LOW
I am using a mosfet (IRFZ44N) to control a dc motor, and a separate one to control a led strip. Both are using the same circuit running to different pwm pins on the arduino.

The light strip is working fine (can be turned on an off as expected), but the motor runs at a low level when the pin sends a LOW state, and revs up when it is sent a HIGH state.

They are both receiving power from the VIN pin of the arduino which in turn in plugged into a 12v 6a dc adaptor.

Any ideas what could cause this behavior?

(Apologies if this is a messy schematic, I am a beginner)

# Answer
There are some mistakes in the provided schematic:

* the nmos has to be connected to motor-
* the freewheeling diode has to be the other way around
* the resistor doesn't make sense. If it's meant to be a pulldown is has to connect the gate with ground and have a much higher value (~10kOhm). If it's meant to be an inrush limiter it has to be in series with the gate

Actually I don't trust you schematic at all, because I wonder why the motor runs at all without damaging your arduino. Have a look at the low-side transistor configuration here to see how it is done.

As I mentioned in a comment, this mosfet is a bad choice because it has a too high gate-source threshold voltage Vgs,th (that's the gate voltage at which the transistor **starts** to conduct. The voltage at which it has the specified on-resistance Rds,on is several times higher than this. Choose a device with a Vgs,th below 1V or go for a logic-level mosfet.
> 0 votes

---
Tags: arduino-uno, motor, mosfet
---


# Question
Title: Yet another basic and silly question about C++ strings
I made a sketch like this:

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

  char str1[64] = "test with spaces";
  char str2[32] = "test with spaces";

  Serial.println(str1);
  Serial.println(str2);

  if (str1 == str2) Serial.println("Equals");
  else Serial.println("Different");

  if (strcmp(str1, str2)) Serial.println("Equals");
  else Serial.println("Different");

//  if (strcoll(str1, str2)) Serial.println("Equals"); // <-- this won't compile for Arduino UNO { why ??? }
//  else Serial.println("Different");

  if (memcmp(str1, str2, sizeof(str2))) Serial.println("Equals");
  else Serial.println("Different");

  if (areEqual(str1, str2)) Serial.println("Equals");
  else Serial.println("Different");

  strcpy(str1, "test+with+spaces");
  strcpy(str2, "test with spaces");

  Serial.println();
  Serial.println(str1);
  Serial.println(str2);

  if (str1 == str2) Serial.println("Equals");
  else Serial.println("Different");

  if (strcmp(str1, str2)) Serial.println("Equals");
  else Serial.println("Different");

  if (memcmp(str1, str2, sizeof(str2))) Serial.println("Equals");
  else Serial.println("Different");

  if (areEqual(str1, str2)) Serial.println("Equals");
  else Serial.println("Different");

  strcpy(str1, "test+with++++++++++++++++++++++++++++++++++++spaces");
  strcpy(str2, "test with spaces");

  Serial.println();
  Serial.println(str1);
  Serial.println(str2);

  if (str1 == str2) Serial.println("Equals");
  else Serial.println("Different");

  if (strcmp(str1, str2)) Serial.println("Equals");
  else Serial.println("Different");

  if (memcmp(str1, str2, sizeof(str2))) Serial.println("Equals");
  else Serial.println("Different");

  if (areEqual(str1, str2)) Serial.println("Equals");
  else Serial.println("Different");

}

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

}

bool areEqual(char* string1, char* string2) {
  return ((strlen(string1) == strlen(string2)) && (strstr(string1, string2)));
}

```

Which produces this:

```
test with spaces
test with spaces
Different
Different
Different
Equals

test+with+spaces
test with spaces
Different
Equals
Equals
Different

test+with++++++++++++++++++++++++++++++++++++spaces
test with spaces
Different
Equals
Equals
Different

```

The first comparisson is silly (==), I know. It compares the address of the pointer, not of the string itself. I just put it there to show how hard it is for a programmer who comes from another language to understand such a thing.

The second comparison (strcmp), as the reference says "Compares the C string str1 to the C string str2.", NO, it doesn't. They are exactly the same, except for their pre-specified size. But the strings are equal to my eyes.

The third comparison (strcoll) uses locale to compare the two strings, but how come it says different when they are equal?

The fourth comparison (memcmp), given two pointers to the exact same sequence of characters, why does it say "different"?

The mind blowing part is the comparison "works" when you add as many "+" as you wish to only one of the strings. Isn't a "+" sign also a character?

It's obvious I must be missing something really basic about c++ style strings, but I dare to ask: what is it?

Thanks.

# Answer
The return value of `strcmp` does not have boolean semantics, as you seem to incorrectly assume.

`strcmp` is a *tri-state comparator*, which returns negative, zero or positive value. For equal strings it returns *zero*, which means that an equality comparison with `strcmp` should normally look as follows

```
if (strcmp(str1, str2) == 0) Serial.println("Equals");
else Serial.println("Different");

```

while your original code actually does the opposite.

There's a moderately widespread ugly habit of writing such comparisons as

```
if (!strcmp(str1, str2)) Serial.println("Equals");
else Serial.println("Different");

```

(note the application of `!` operator). It works properly, but it has poor readability. Avoid it. For tri-state comparators is a much better idea to spell out the comparison with `0` explicitly.

And you made exactly the same mistake with `memcmp`. `memcmp` is also a tri-state comparator, so it should be

```
if (memcmp(str1, str2, sizeof str2) == 0) Serial.println("Equals");
else Serial.println("Different");

```

The same applies to `strcoll`.

P.S. And in fact such zero-terminated strings represented by `char[]` arrays are called *C-style strings*, not C++-style strings.
> 5 votes

---
Tags: programming, arduino-ide, c++, string, c-string
---


title: Arduino vs 12bit ADC

text:
# Question
Title: Arduino vs 12bit ADC
12bit ADC will give us about 1.2mV per step:

```
5 / 4096 = 0.00122

```

But if we give Arduino a 1.2V voltage reference we get 1.1mV per step:

```
1.2 / 1024 = 0.00117

```

Does that means Arduino can be more accurate than a 12 bit ADC?

# Answer
In a word, no.

The Arduino uses a rather crude 10-bit ADC. If you feed it a small voltage reference, you can divide that small voltage into 1024 steps. (as you say, about 1.1mV/step)

If you feed the same small 1.2V reference voltage into a 12-bit ADC, you'll get 4 times as many steps for the same range. (about 293μV/step)

And, as mentioned before, the ADC's in Arduinos are not very good. They're slow, and not very accurate.

(To be technical, precision is how exactly you DESCRIBE your answer. A decimal reading using more decimal places is more precise than a reading with less decimal places. Accuracy is how close the measured value is to the actual value. If you're sloppy with your measurements but use lots of decimal places to write it down, and the answer is very far off, you have a precise but inaccurate answer. (e.g you measure something as 1.0000001 millimeters, but it's really 2.5 mm.

A 12-bit ADC is more precise than a 10-bit ADC, but it may or may not be more accurate. Given the crude nature of the ADCs in Arduinos, a dedicated 12-bit ADC is likely to be more accurate than built-in one.)
> 3 votes

---
Tags: adc, analogreadresolution
---


# Question
Title: Can you use an Arduino UNO as an EEPROM programmer
Hi I have an Arduino UNO and a AT28c64B and a single shift register, is it possible to make an EEPROM programmer with it? I’m not too good with the Arduino to do a lot of trial and error... I would just like to know if it’s possible or not, not how to...

# Answer
You need 24 GPIO pins to control that EEPROM chip. The Arduino has 19, and a typical shift register has 8 outputs. It takes 3 or 4 (depending on the shift register) to drive the shift register.

That's `19 + 8 - 4 = 23` for a shift register that needs 4 pins, or `19 + 8 - 3 = 24` for one that needs 3 pins.

However I would assume that you want to communicate with your computer as well, and that means that pins 0 and 1 of the Arduino are out of bounds, since they are used for the PC communication.

That means, at best, you have 22 pins when you need 24.

So, no, with that combination you can't, due to a lack of pins.

However an IO expander, such as the MCP23017, would give you enough pins and need fewer pins to drive. They also work in both directions, so can be used for pins that want to be read as well as written (data pins).

Alternatively an SPI or I2C connected EEPROM would be the better option, since those are designed to be driven by a small microcontroller like an Arduino uses.
> 0 votes

---
Tags: arduino-uno, eeprom
---


title: Deep Sleep Reset with Shock Sensor

text:
# Question
Title: Deep Sleep Reset with Shock Sensor
I am trying to design a circuit that wakes my ESP8266 (Wemos D1 Mini) from deep sleep using a shock sensor. I can achieve this using the reset pin but I need it to ignore further requests to reset to give it time to run the code in my sketch. Provided there is still motion it will just continue to reset meaning the code only gets run after the 'shock' stops. I have tried all kinds of things with capacitors and transistors to delay subsequent resets but with very limited success. Can someone please point me in the right direction or suggest an easier way to do this? Many thanks in advance.

# Answer
This is actually somewhat more tricky than you would at first thing.

First off, the "shock sensor" is merely a spring inside a tube. This will create *lots* of triggers while it's being "shocked", which really is messy.

Secondly, you only want those shocks to make it through to the ESP when you are in deep sleep.

Thirdly, you don't want whatever you connect to adversely affect, or be affected by, other circuitry that is connected to the reset pin.

So you first really need to "condition" the output of your sensor so that it gives a clean pulse that can reset the ESP8266. Then you need to "gate" that signal so it can only get through while the board is asleep.

For conditioning the shock sensor signal I would be inclined to use a 55 timer in monostable mode. You can find a good circuit and description here which looks like this:

Now to gate that signal (which is active high) you need a signal to gate it with. Since all the GPIOs of the ESP8266 are "dead" while it's asleep you need it to be in a "default on" state and have the ESP8266 drive an "I am awake" signal to disable the output. So you'd have a pullup resistor on a GPIO to make it default HIGH (to match the trigger pulse for simplicity) and then use `pinMode()` and `digitalWrite()` as the first things after waking up (and at the start of `setup()`) to indicate it's awake by driving it LOW. Then you combine those two signals:

* If the trigger is HIGH and
* If the gate signal is HIGH
* Then pull reset LOW
* Otherwise don't affect reset

So you make a truth table:

```
Trig | Gate | Res
-----------------
  L  |  L   |  HiZ
  L  |  H   |  HiZ
  H  |  L   |  HiZ
  H  |  H   |  L

```

The tricky one here is the "HiZ" - This means "High Impedance" - or in effect "Don't affect the reset pin at all".

Apart from that the truth table is that for a NAND gate - if both inputs are HIGH then the output is LOW - otherwise the output is HIGH. Except we want HiZ not HIGH.

To make that HiZ there's two things you can do:

1. Use a NAND gate that has an "Open Collector" (or "Open Drain") output, or
2. Use an AND gate and create your own "Open Collector" that inverts the output by adding a transistor.

For option 1 you can use the 74AC01 which is a "Quad 2 input NAND gate Open Collector". For option 2 you can use the 74AC08 and any NPN transistor (or N-channel MOSFET with a suitable threshold).

simulate this circuit – Schematic created using CircuitLab
> 1 votes

---
Tags: esp8266, sleep, reset
---


title: How could i synchronize 2 signals

text:
# Question
Title: How could i synchronize 2 signals
```
unsigned long Htime;
unsigned long Ltime;
unsigned long Ttime;
unsigned long f;
int N;

void setup() {
  // put your setup code here, to run once:
cli();
  TCNT2 = 0;
  TCCR2A = 0;
  TCCR2B = 0;
  Serial.begin(9600);
  pinMode(5,INPUT);
  pinMode(3,OUTPUT);
  pinMode(11,OUTPUT);
  TCCR2A = (1 << COM0A1) | (1 << COM0B1) | (1 << WGM21) | (1 << WGM20);
  TCCR2B = (1 << WGM22) | (1 << CS22) | (1 << CS21) | (1 << CS20);
  TIMSK2 = (1 << OCIE2A);
}

void loop() {
  // put your main code here, to run repeatedly:
  Htime = pulseIn(5, HIGH);
  Ltime = pulseIn(5, LOW);
  Ttime = Htime + Ltime;
  f = 1000000 / Ttime;
  Serial.println(f);
  N = (16000000 / 1024 / f ) - 1;
  OCR2A = N;
  OCR2B = N/2;

}

```

Hi this is what i have written. and i need output a square wave with timer, its frequency is measured from input signal in pin 5. After connecting the oscilloscope, i see the problem, there is phase shift between 2 signals. How could i synchronize this 2 signals?(rising edge to rising edge, falling edge to falling edge) Thank u so much for your help!

# Answer
Given that only the falling edge of your input is sharp and well defined, I suggest the following approach:

* Use the input-capture feature of Timer 1 to get a timestamp on the falling edge and trigger an interrupt.
* In the ISR, start by toggling the output in order to set it low. Then compute the period of the signal (timestamp of this falling edge minus timestamp of the previous one) and program a compare register to trigger a compare match event after half a period.
* The compare match would automatically toggle the output pin again, by using the “toggle on compare match” timer output mode.

The following program attempts to implement this approach. Note that it is completely untested. Input is on pin 8 (i.e. PB0 and ICP1). Output is on pin 9 (i.e. PB1 and OC1A). The timer is set to run at `F_CPU/8` in order to accommodate frequencies as low as about 30.1 Hz. A different prescaler should be used if lower frequencies are needed. The program does not rely on the Arduino core, and thus defines its own `main()` instead of `setup()` and `loop()`.

```
ISR(TIMER1_CAPT_vect)
{
    TCCR1C = _BV(FOC1A);  // force output compare -> toggle output
    static uint16_t last_capture;
    uint16_t capture = ICR1;
    uint16_t period = capture - last_capture;
    last_capture = capture;
    OCR1A = capture + period/2;  // compare match after 1/2 period

    // If output is high, toggle again.
    if (bit_is_set(PINB, PB0))
        TCCR1C = _BV(FOC1A);
}

int main()
{
    // Set OC1A = PB1 = digital 9 as output.
    DDRB = _BV(PB1);

    // Configure Timer 1.
    TCCR1A = _BV(COM1A0);  // toggle OC1A on compare match
    TCCR1B = _BV(CS11);    // clock at F_CPU/8
    TCCR1C = _BV(FOC1A);   // force output compare -> toggle output
    TIFR1  = _BV(ICF1);    // clear capture flag
    TIMSK1 = _BV(ICIE1);   // enable capture interrupt
    sei();

    for (;;) {}
}

```
> 1 votes

---
Tags: arduino-uno
---


title: Waterproofing Arduino

text:
# Question
Title: Waterproofing Arduino
the project i'm working on is a weather station out door and for that i need to to give arduino at least some sort of protection from moisture.

https://www.instructables.com/id/Arduino-Weather-Station-AWS/

putting arduino in a box might work but the humidity where i live is very high it's rain a lot but the cold is not much. looking for ideas to waterproof arduino board please.

also can arduino work everyday of year without problem?

# Answer
> 2 votes
You can just solder everything you need to the Arduino (I would recommend using an Arduino Mini since it has no communication port) and coat it with Silicon Conformal Coating. It creates a silicon layer on top of the PCB that would not let any moisture through. Or you can just put it in a case and cover it with epoxy, that will be even more protection, but there will be no more access to the board unless you foresee it.

---
Tags: arduino-uno
---


title: Error reading file

text:
# Question
Title: Error reading file
What should be done to solve it? I have edited the `board.txt` file and none of my codes are getting verified it shows this error:

> "Error reading file (C:\Program Files (x86)\Arduino\hardware\arduino\avr\boards.txt:0): Invalid line format, should be 'key=value' "

# Answer
You can either reinstall the Arduino IDE (it will replace the file), or copy the original code back in the file (if you have a copy somewhere).

See the link: https://code.google.com/archive/p/arduino/wikis/Platforms.wiki for more background in case you are interested.

(note: I cannot copy the content of the file in the answer since it is more than 30000 characters.)
> 1 votes

---
Tags: arduino-uno, arduino-ide
---


title: Program for counting days

text:
# Question
Title: Program for counting days
I need a program to count days, from day 1 to day 21 for my project.

I'm making an artificial incubator and I need to show the days on an LCD.

# Answer
You can do that easily using Real Time Clock IC. ds1307/ds3231 ic will do the job. Adafruit has Arduino library for that. easy to interface.

I don't supprt using millis() function. you will lose your time if the system power downs or mcu resets. Using RTC chip is safe option as it has backup battery for time keeping.
> 0 votes

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


# Question
Title: double to char* conversion. Weird results from dtostrf
**Here’s the code:**

```
void setup()
{
    Serial.begin(9600);
    delay(300);

    double lat = 1111.11;
    double lon = 4444.44;

    const byte len{10};

    char sLat[len];
    char sLon[len];

    dtostrf(lat, len, 2, sLat);
    Serial.println(sLat);

    Serial.println("---");

    dtostrf(lon, len, 2, sLon);
    Serial.println(sLon);
    Serial.println(sLat); // <-- prints nothing!

    Serial.println("---");

    dtostrf(lat, len, 2, sLat);
    Serial.println(sLat);
    Serial.println(sLon); // <-- prints nothing!
}

void loop()
{
}

```

**Here’s the output:**

```
   1111.11
---
   4444.44

---
   1111.11
   4444.44   1111.11

```

As you see. Every next call for `dtostrf` ruins the previous results, in a weird way.

What’s the problem?

# Answer
If `len` is the text array size, you need space there for the terminating '\0'. So the second paramater to `dtostrf` has to be smaller than `len`.
> 2 votes

---
Tags: data-type
---


# Question
Title: How to solve problem AT+INQ ERROR (1F), AT+INIT ERROR(17) on Bluetooth Module HC-05?
i have problem with accessing **at-command in module Bluetooh HC-05**.

i just follow all tutorial to activate at-command like this, http://www.martyncurrey.com/arduino-with-hc-05-bluetooth-module-in-slave-mode/

or in this video https://www.youtube.com/watch?v=Vr4cdpsoVEo&t=31s

and just read some explanation and implemented to my problem HC-05 Bluetooth AT+INQ command not working

**but i just still get same error. i cant use AT+INQ command, always get ERROR(1F). AT+INIT get ERROR(17).**

i have module HC-05 with version 3.0-20170601

This is my code i use it.

```
#include <SoftwareSerial.h>
SoftwareSerial BTserial(8, 9); // RX | TX`

const long baudRate = 38400;
char c=' ';
boolean NL = true;

void setup()

{
   Serial.begin(9600);
   Serial.print("Sketch:   ");   Serial.println(__FILE__);
   Serial.print("Uploaded: ");   Serial.println(__DATE__);
   Serial.println(" ");

BTserial.begin(baudRate);
Serial.print("BTserial started at "); Serial.println(baudRate);
Serial.println(" ");
}

void loop()

{

// Read from the Bluetooth module and send to the Arduino Serial Monitor
if (BTserial.available())
   {
       c = BTserial.read();
       Serial.write(c);
   }

   // Read from the Serial Monitor and send to the Bluetooth module
if (Serial.available())
   {
       c = Serial.read();
       BTserial.write(c);

    // Echo the user input to the main window. The ">" character indicates
    the user entered text.
    if (NL) { Serial.print(">");  NL = false; }
    Serial.write(c);
    if (c==10) { NL = true; }
   }

}

```

# Answer
> 3 votes
I have a HC-05 with 3.0-20170601 that I managed to bind to a slave last night. It turns out that the v3 has two AT-modes.

The first is when you hold the button while you connect power. The led will blink slowly and you can connect at 38400 baud. But this is like a configuration mode, where AT+INQ is not available.

In this mode I did these commands:

```
AT
AT+UART
AT+RMAAD
AT+ROLE=1

```

(Press and hold the button)

```
AT+RESET

```

(Release the button after device restarts and led is slowly blinking)

```
AT+CMODE=1
AT+INQM=0,5,5
AT+PSWD="9999"

```

AT should give OK as answer to know connection is working

AT+UART will show configured baudrate. Default is 9600.

AT+RMAAD clears all saved connections

AT+ROLE=1 sets it as master

AT+RESET restarts the device to change to master

AT+CMODE=1 accepts all kinds of devices

AT+INQM=0,5,5 inquires in standard mode, with 5 max connections or 5 secs

AT+PSWD="9999" sets the pin code 9999, change to the pin you need

After this it is time to update the arudino code. In your case you should update line 4 from

```
const long baudRate = 38400;

```

to

```
const long baudRate = 9600;

```

...or what ever value you might have set the baud rate to. Then reflash your arduino.

Now enter the very irritating second AT command mode.

Power up without holding the button. You will get the fast blink speed. When its powered up, press and hold the button. The led will continue blinking fast, but while the button is pressed you can now connect to the device on the configured baud rate. So open the serial monitor and type AT to verify. Remember that the mode is only active while the button is pressed. So keep it pressed. I had a small clamp I put on there.

Then I entered these commands:

```
AT+STATE

```

AT+STATE will show current state, should be inquiring

Then power up the slave device and the adress should start popping up. It will be something like xyz:xy:xyzw,931F00,7FFF

The first part is the address you want (xyz:xy:xyzw)

Change : to , and get xyz,xy,xyzw

Check that you connecting to the correct device

```
AT+RNAME?xyz,xy,xyzw

```

Then bind

```
AT+PAIR=xyz,xy,xyzw,5
AT+BIND=xyz,xy,xyzw
AT+LINK=xyz,xy,xyzw

```

The AT+LINK command gave me FAIL as output. But it did not matter. I restarted and did not press any button before or after. Just normal start.

After 5-10s serial data showed up in my serial monitor.

Modules are bound. And will automatically connect at power up. If not you might have the wrong pincode. Make sure to change 9999 above to 0000 or 1234 or what ever it may be. When I hade the wrong pin I still got OK from the AT+PAIR and AT+BIND commands... It didnt work for me until I entered the correct pin.

Sorry for long post, but I wanted to be thorough since info about HC-05 v3 is very scarce on the internet right now.

A reference to all commands can be found here: http://www.electronicaestudio.com/docs/istd016A.pdf (Link valid 2018-08-13)

# Answer
> 1 votes
I have two modules:

(A) HC-05 with firmware version 3.0-20170601

(B) HC-05 with firmware version 2.0-20100601 (ok)

I have the same problem: when the AT command "AT+INQ" is sent on (A) module, the response is always "ERROR:(1F)". This error code seems not be reported in any document or specification available on internet. This BT module have firmware version (AT+VERSION) 3.0-20170601. Also I have noticed that command AT+INIT on (A) module returns always ERROR:(17), this error normally can be ignored if the command has been sent already (Initiate SPP lib), but the first time should be return "OK" as on (B) module.

The (B) module with firmware version 2.0-20100601 works ok with the following commands (set PIN34 high at power-up, or press button on module and keep pressed during commands):

AT+RMAAD -\> delete all paired devices list

AT+ROLE=1 -\> Set master mode

AT+RESET -\> reset module to enter into master mode

AT+CMODE=1 -\> Permit connection with any device

AT+INQM=0,5,9 -\> Set Search parameters(Query mode standard, 5 devices, 9secs)

AT+INIT --\> Init SPP profile mode (first time response: "OK")

AT+INQ --\> Start search devices (return device list after some seconds)

The differences between two modules are:

On AT+INIT the (A) module return always ERROR:(17), the (B) module return "OK" first time and ERROR:(17) if the command is sent twice. On (A) module the command AT+INQ return always ERROR:(1F), the (B) module return the list of the BT devices.

Also the (A) and (B) modules are physically different. The (B) module have some components (resistors/capacitors) between the two big black chips, the (A) module no.

Also I noticed that on (A) module the AT+CLASS? return "1f00" value (default?). The correct value should be "0" as (B) module ? Anyway setting AT+CLASS=0 on (A) module the result is always the same.

In slave mode (AT+ROLE=0) both modules works fine.

With (A) module I'm unable to use it as "MASTER" and connect it to any other slave BT modules because did not perform devices search. (INQ fails).

I think that in 3.0 firmware is needed to set other(s) parameter(s) in order to start SPP profile correctly (INIT) and then avoid ERROR:(1F) in INQ command (search).

Someone already solved the problem ?

# Answer
> 1 votes
Extending the Presidenten's answer, the easiest way to program HC-05 is to sonnect a wire to EN on the chip and set the UART console to 9600.

Then pull the EN high, send commands, wait for OK (after each one), and drive EN down.

You now have a chip in data state.

# Answer
> 0 votes
I have the same version module HC-05. This mode (INQ) is enabled for default and it's impossible switch it off. Seems that manufacturer removed this command in that version.

Another point, that it works only on default 9600 bod/s regardless of settings AT+UART=... and only in standart AT mode (key pin pull high after power on device).

Once connected to other module only one way to return to "inquiring" that I found is full reset it by command ORGL, and reconfigure it class and role.

Don't touch IAC settings - that also causes improperty working.

---
Tags: bluetooth
---


title: ESP-01 + UNO won't detect gateway

text:
# Question
Title: ESP-01 + UNO won't detect gateway
Apparently, this combination of hardware won't accept anything other than WiFiEsp.h together with SoftwareSerial.h (if anyone knows something better/newer than these two, please let me know). Thing is: I can connect to wifi, send and receive data (to an apache server inside my home network) just fine. After my project was almost done, I decided to connect it to a real server on the internet only to discover that ESP-01 couldn't detect my gateway.

```
#include "WiFiEsp.h"
#include "SoftwareSerial.h"

int pinWifiRX = 6;
int pinWifiTX = 7;

char ssid[64]    = "*****";
char pass[32]    = "************";

SoftwareSerial Serial1(pinWifiRX, pinWifiTX);

int wifi_status;

void setup() {

  Serial.begin(9600);

  Serial1.begin(9600);
  while(!Serial1) (true);

  WiFi.init(&Serial1);

  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println(F("No shield"));
    while (true) {}
  }

  IPAddress localIp(192, 168, 1, 60);
  IPAddress subnetMask(255, 255, 255, 0);
  IPAddress gateway(192, 168, 1, 36);

  WiFi.config(localIp);  // <--- this line is accepted and works, but the other 3 gives compilation errors
//  WiFi.config(localIp, gateway);
//  WiFi.config(localIp, gateway, subnetMask);
//  WiFi.config(localIp, gateway, subnetMask, gateway);

  wifi_status = WiFi.begin(ssid, pass);

  if (wifi_status == WL_CONNECTED) {

    IPAddress ip;

    ip = WiFi.localIP();
    Serial.print(F("[WiFiEsp] IP Address: "));
    Serial.println(ip);

    ip = WiFi.subnetMask();
    Serial.print(F("[WiFiEsp] Subnet Mask: "));
    Serial.println(ip);

    ip = WiFi.gatewayIP();
    Serial.print(F("[WiFiEsp] Gateway: "));
    Serial.println(ip);

//    ip = WiFi.getDNS();  // <--- function doesn't exist
  }

}

void loop() {}

```

Results in:

```
[WiFiEsp] Initializing ESP module
[WiFiEsp] Initilization successful - 2.2.1
[WiFiEsp] IP address set 192.168.1.60
[WiFiEsp] Connected to *****
[WiFiEsp] IP Address: 192.168.1.60
[WiFiEsp] Subnet Mask: 255.255.255.0
[WiFiEsp] Gateway: 192.168.1.0

```

As one can see, Subnet Mask is corret, but it "detects" Geteway **192.168.1.0** when it should be **192.168.1.36**. This way, I can connect to any device in LAN, but cannot access any address on the internet.

I even tried to send some AT commands directly to SoftwareSerial.h, but I don't get any response.

Will I have to start the whole project over from scratch (using another hardware combination), or is there a way to change gateway by hand? Better yet, is there a way to make it detect the gateway's address correctly?

EDIT: could it be related to the firmware I installed to the ESP-01? I followed this tutorial and got it from this link.

Thanks in advance.

**EDIT: in this example, i used the WiFi.config(localIp) function to set a fix IP. I don't really need that, it was just an attempt to make it get the correct Gateway address. Even if I comment that line, the Gateway is still wrong.**

# Answer
I've had some progress in my researches towards this problem.

In fact, Arduino gets the correct gateway address from my DHCP server, but displays the wrong one. There must be a bug somewhere in WiFiEsp library somewhere.

To debug this, I made a few changes to the following files:

* WiFiEsp-Master/src/WiFiEsp.h

> ```
> void config(IPAddress local_ip, IPAddress gateway);
> void config(IPAddress local_ip, IPAddress gateway, IPAddress subnetMask);
>
> ```

* WiFiEsp-Master/src/WiFiEsp.c

> ```
> void WiFiEspClass::config(IPAddress ip, IPAddress gateway)
> {
>   EspDrv::config(ip, gateway);
> }
> void WiFiEspClass::config(IPAddress ip, IPAddress gateway, IPAddress subnetMask)
> {
>   EspDrv::config(ip, gateway, subnetMask);
> }
>
> ```

* WiFiEsp-Master/src/utility/EspDrv.h

> ```
> static void config(IPAddress local_ip, IPAddress gateway);
> static void config(IPAddress local_ip, IPAddress gateway, IPAddress subnetMask);
>
> ```

* WiFiEsp-Master/src/utility/EspDrv.cpp

> ```
> void EspDrv::config(IPAddress ip, IPAddress gateway) {
>   LOGDEBUG(F("> config"));
>
>   // disable station DHCP
>   sendCmd(F("AT+CWDHCP_CUR=1,0"));
>
>   // it seems we need to wait here...
>   delay(500);
>
>   char buf_ip[16];
>   sprintf_P(buf_ip, PSTR("%d.%d.%d.%d"), ip[0], ip[1], ip[2], ip[3]);
>
>   char buf_gateway[16];
>   sprintf_P(buf_gateway, PSTR("%d.%d.%d.%d"), gateway[0], gateway[1], gateway[2], gateway[3]);
>
>   int ret = sendCmd(F("AT+CIPSTA_CUR=\"%s\",\"%s\""), 2000, buf_ip, buf_gateway);
>   delay(500);
>
>   if (ret==TAG_OK)
>   {
>     LOGINFO1(F("IP and gateway addresses set"), buf_ip);
>   }
> }
>
> void EspDrv::config(IPAddress ip, IPAddress gateway, IPAddress subnet)
> {
>
>   LOGDEBUG(F("> config"));
>
>   // disable station DHCP
>   sendCmd(F("AT+CWDHCP_CUR=1,0"));
>
>   // it seems we need to wait here...
>   delay(500);
>
>   char buf_ip[16];
>   sprintf_P(buf_ip, PSTR("%d.%d.%d.%d"), ip[0], ip[1], ip[2], ip[3]);
>
>   char buf_gateway[16];
>   sprintf_P(buf_gateway, PSTR("%d.%d.%d.%d"), gateway[0], gateway[1], gateway[2], gateway[3]);
>
>   char buf_subnet[16];
>   sprintf_P(buf_subnet, PSTR("%d.%d.%d.%d"), subnet[0], subnet[1], subnet[2], subnet[3]);
>
>   int ret = sendCmd(F("AT+CIPSTA_CUR=\"%s\",\"%s\",\"%s\""), 4000, buf_ip, buf_gateway, buf_subnet);
>   delay(500);
>
>   if (ret==TAG_OK)
>   {
>     LOGINFO1(F("IP, gateway and subnet mask addresses set"), buf_ip);
>   }
> }
>
> ```

These few changes should be enough to implement fix IP address and specify manual address for gateway and subnet mask (please feel free to correct me if I'm wrong).

But after doing this, I realized the gateway continued to be "192.168.1.**0**". Then I added this piece o code to the function EspDrv::readUntil, inside EspDrv.cpp:"

```
        ringBuf.push(c); // this line was already there
        Serial.print(c);

```

This way, I could see exactly all responses for the AT commands sent by WiFiEsp library. When asked, the results were:

```
+CIPSTA:ip:"192.168.1.60"
+CIPSTA:gateway:"192.168.1.36"
+CIPSTA:netmask:"255.255.255.0"

```

Then I realized the problem wasn't the gateway, but the DNS. If the library sends command "AT+CIPSTART=3,"TCP","www.google.com",80", the result was:

```
Not connected

busy p...

```

And, if increased the timeout value to 15000 instead of 5000, the result was:

```
DNS ERROR

```

Now my problem is partially solved. I can connect to an external server if I use an IP address, but I can't set a domain name because it won't be resolved by the DNS.

Apparently the firmware version of my ESP-01 won't accept "AT+CDNSCFG=?" required to set/retrive DNS address. I tried to set 8.8.8.8 as the DNS, but the result was "NOT OK".

I will stick to this "solution" for now, but would be glad to hear any comment about what I described here and a more final solution.

Thanks.
> 1 votes

# Answer
Using a static IP address with a gateway is not implemented (as you can see from the source code).

To get out to the internet with that library you can only use DHCP (by omitting the `WiFi.config(localIp)` call).
> 0 votes

---
Tags: arduino-uno, esp8266, arduino-ide, wifi
---


# Question
Title: real-time reading of a quadrature encoder at full resolution with only one interrupt on ATmega328
I want to read a quadrature rotary encoders at full resolution with only one interrupt on Arduino Nano (ATmega328). So I found out that we can use XOR to reach a full resolution:

```

```

Where pin `3` is interruptable but `4` and `5` are not.

Our requirements are:

1. Full resolution: for example, the solution offered in this answer works at a half-resolution only, not detecting all the edges.
2. Real-time: being as fast as possible up to the level that this hardware allows and safe in terms of not missing any of the signal edges.
3. using only one interrupt. We need the other one for other purposes.

So far, I have developed two different codes, one aiming for safety and the other for performance:

# Preamble:

```
#include "digitalWriteFast.h"

#define pinT 3 // trigger pin comming from XOR

#define pinA 4 // channel A
#define pinB 5 // channel B

volatile long counter = 0;
long counter_ = counter;

```

where the `digitalWriteFast` library can be downloaded from here.

# Performant:

```
volatile short int increment = 0;
volatile bool tmpA;
volatile bool tmpB;
volatile bool lastA;

ISR(trigger) {
  tmpA = digitalReadFast(pinA);
  tmpB = digitalReadFast(pinB);
  counter += (1 - 2 * tmpA) * (1 - 2 * tmpB) * (1 - 2 * (lastA != tmpA));
  lastA = tmpA;
}

void setup() {
  pinMode(pinA, INPUT_PULLUP);
  pinMode(pinB, INPUT_PULLUP);
  pinMode(pinT, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pinT), trigger, CHANGE);
  lastA = digitalReadFast(pinA);
  Serial.begin(9600);
}

void loop() {
  if (counter != counter_) {
    Serial.println(counter);
    counter_ = counter;
  }
}

```

# Safe:

```
volatile unsigned long error = 0;
unsigned long error_ = 0;

volatile bool inputA;
volatile bool inputB;

volatile short state; // 100 110 101 111
volatile short state_;

void detectState() {
  inputA = digitalReadFast(pinA);
  inputB = digitalReadFast(pinB);

  if (inputA) {
    if (inputB) {
      state = 111;
    } else {
      state = 110;
    }
  } else {
    if (inputB) {
      state = 101;
    } else {
      state = 100;
    }
  }
}

ISR(trigger) {

  detectState();

  if (state_ != state) {
    switch (state_) {
      case 100:
        if (state == 110) {
          counter++;
        } else if (state == 101) {
          counter--;
        } else {
          error++;
        }
        break;
      case 110:
        if (state == 100) {
          counter--;
        } else if (state == 111) {
          counter++;
        } else {
          error++;
        }
        break;
      case 101:
        if (state == 100) {
          counter++;
        } else if (state == 111) {
          counter--;
        } else {
          error++;
        }
        break;
      case 111:
        if (state == 110) {
          counter--;
        } else if (state == 101) {
          counter++;
        } else {
          error++;
        }
        break;
      default:
        error++;
        break;
    }

    state_ = state;
  } else {
    error++;
  }
}

void setup() {
  pinMode(pinT, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pinT), trigger, CHANGE);

  pinMode(pinA, INPUT_PULLUP);
  pinMode(pinB, INPUT_PULLUP);

  detectState();
  state_ = state;

  Serial.begin(9600);
}

void loop() {
  if (counter != counter_) {
    Serial.print("counter: ");
    Serial.println(counter);
    counter_ = counter;
  }

  if (error != error_) {
    Serial.print(error);
    Serial.println(" errors");
    error_ = error;
  }
}

```

Now my questions are:

1. Is there any way to improve the speed/safety of the performant/safe code? Any way to improve this code is appreciated.
2. Is it possible to have maximum speed and safety together or some trade-off in between?
3. What is the maximum frequency we can get out of this configuration?

Thanks for your help in advance.

# Answer
This is just a partial, rushed answer.

You should be able to get a significant speed-up if you define your own ISR for handling the interrupt, as in:

```
ISR(INT1_vect) { ... }

```

The Arduino way of using interrupts is instead

```
void trigger() { ...}

void setup() {
    attachInterrupt(int_number, trigger, CHANGE);
    ...
}

```

but this is slow, as it involves the ISR provided by the Arduino core, which has to locate and call your interrupt handler. The way you wrote the handler is wrong: either you define a regular function, without the `ISR` macro, and go the Arduino way, or you go the plain AVR path and define the ISR yourself, which should be named `INTERRUPT_NAME_vect`, in which case you don't use `attachInterrupt()`. The way you did it is probably the slowest you can get, as the compiler will needlessly add an ISR-type prologue and epilogue to your handler.

As for the maximum frequency, that's hard to assess without testing, but you may get some idea by reading this answer on interrupt latency.

---

**Edit**: As I stated in my first comment to the question, a pin change interrupt can be used instead of an external logic gate. Here is how to do it.

First, one should look at the Arduino Uno pinout and see that:

* digital 4 = PD4 = PCINT20
* digital 5 = PD5 = PCINT21

Both pins are tied to the pin change interrupt request 2 (PCINT2\_vect). This interrupt can be configured in `setup()` as follows:

```
PCMSK2 = _BV(PCINT20)   // enable interrupt on pin PCINT20 = PD4
       | _BV(PCINT21);  // enable interrupt on pin PCINT21 = PD5
PCIFR  = _BV(PCIF2);    // clear interrupt flag
PCICR  = _BV(PCIE2);    // enable pin change interrupt request 2

```

Now, the interrupt will fire on every change of the logic levels of inputs 4 and 5.

Then, in the ISR, the whole port D can be read in a single cycle by just evaluating the corresponding pin input register, i.e. `PIND`. With some shifting and masking, one can get a phase between 0 and 3 (the count is in Gray code: 0, 1, 3, 2, 0...). From the previous and the current phase, one can compute the change that needs to be applied to the counter:

```
// Handle pin change interrupt request 2.
ISR(PCINT2_vect) {
    static uint8_t previous_phase;
    uint8_t phase = (PIND >> 4) & 0x03;  // read input pins
    counter += encoder_delta(previous_phase, phase);
    previous_phase = phase;
}

```

The implementation of `encoder_delta()` is left as an exercise to the reader. ;-)
> 1 votes

---
Tags: arduino-nano, interrupt, rotary-encoder, isr, performance
---


# Question
Title: Floating power supply for Arduino - Is it still connected to the USB ground?
I am trying to power my Arduino Mega 2560 from a benchtop power supply. I plan to essentially feed in a 9V supply directly on the Vin pin and connect the GND pin to the floating ground pin on the power supply. I noticed on the schematic that the UGND is connected to GND through this jumper. On the Arduino that I have these two pins are tied together. Does this mean that even with the external power supply the Arduino will be connected to the UGND, and in effect the protective earth?

What is the best way to float the Arduino? Would it be ok to remove the jumper connection between UGND and GND? Or should I try something like a linear USB isolator like this?

# Answer
> Does this mean that even with the external power supply the Arduino will be connected to the UGND, and in effect the protective earth?

Yes.

> Would it be ok to remove the jumper connection between UGND and GND?

No. I don't know quite why they provided that jumper. I can see no scenario in the datasheet where it suggests the two can be separate.

> Or should I try something like a linear USB isolator like this?

If you want it to float then you need galvanic isolation on *all* USB pins. The device you link to will do that for you. There are others as well.

Personally in these situations I prefer to use a wireless communication system so there is no worry about grounds and isolation - it's naturally isolated.
> 1 votes

---
Tags: power, atmega2560
---


# Question
Title: Specific ports on Teensy 3.6 not reading correct bit resolution using ADC library?
I have a basic circuit, where I'm reading analog values from 14 infrared receivers.

I set the bit resolution to 16 but specific ports are returning 10 bit values (from 0 - 1024) instead of 16 bit values (from 0 - 65536).

I can confirm this is not a problem with my circuitry because when I've tested reading each individual sensor with a port that "works" and the correct range is returned every time.

---

Here is my code:

```
#include <ADC.h>

ADC *adc = new ADC();
const int* RECIEVERS = (int[14])
{
    A15, A16, A17, A19, A20, A21, A22, A1, A2, A3, A6, A7, A8, A9
};

void setup() {
    Serial.begin(4608000);
    adc->setAveraging(16); // set number of averages
    adc->setResolution(16); // set bits of resolution
    adc->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED_16BITS);
    adc->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED);
    for (int i = 0; i < 14; i++) pinMode(RECIEVERS[i], INPUT);
}

void loop() {
    for (int i = 0; i < 14; i++) {
        Serial.print(adc->analogRead(RECIEVERS[i]));
        Serial.print(" | ");
        delay(1);
    }
    Serial.println("");
}

```

---

**Is there a problem with my code or is my Teensy damaged?**

# Answer
The Kinesis 66 (the chip on the Teensy 3.6) has *two* ADC modules. Each one talks to different pins.

By default the configuration functions in that library configure ADC0, so unless you tell it otherwise, you will only be configuring half the ADC pins.

You should call each of the configuration functions twice, once for ADC0 and once for ADC1:

```
adc->setAveraging(16, 0); // set number of averages
adc->setResolution(16, 0); // set bits of resolution
adc->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED_16BITS, 0);
adc->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED, 0);

adc->setAveraging(16, 1); // set number of averages
adc->setResolution(16, 1); // set bits of resolution
adc->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED_16BITS, 1);
adc->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_HIGH_SPEED, 1);

```
> 2 votes

---
Tags: analogread, adc, teensy
---


title: Sim800 FTP Arduino

text:
# Question
Title: Sim800 FTP Arduino
I've been unable to FTP anything using an Arduino and SIM800L. I have reduced the code as far as possible:

```
#include <SoftwareSerial.h>

//Create software serial object to communicate with SIM800L
SoftwareSerial mySerial(3, 2); //SIM800L Tx & Rx is connected to Arduino #3 & #2

String moduleAnswer = "";

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

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

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

  SoftwareATCommand("AT"); //Once the handshake test is successful, it will back to OK
  SoftwareATCommand("AT+CSQ"); //Signal quality test, value range is 0-31 , 31 is the best
  SoftwareATCommand("AT+CCID"); //Read SIM information to confirm whether the SIM is plugged
  SoftwareATCommand("AT+CREG?"); //Check whether it has registered in the network

  //APN and GRPS Setup
   SoftwareATCommand("AT+SAPBR=0,1"); //Close GPRS before connecting
   SoftwareATCommand("AT+SAPBR=3,1,\"Contype\",\"GPRS\""); //Configure bearer profile

  SoftwareATCommand("AT+SAPBR=1,1"); //Connect to GPRS

  //FTP Connection
  SoftwareATCommand("AT+FTPCID=1");
  SoftwareATCommand("AT+FTPSERV=127.189.249.205"); //Not real IP
  SoftwareATCommand("AT+FTPPORT=21");
  SoftwareATCommand("AT+FTPUN=user");
  SoftwareATCommand("AT+FTPPW=pass");

  //FTP Upload
  uploadFTP();

 }

void loop()
{
}

void uploadFTP()
{
  SoftwareATCommand("AT+FTPPUTNAME=\"test.txt\""); //Filename
  SoftwareATCommand("AT+FTPPUTPATH=/home/arduino/SolarDataLogger/"); //Path
  SoftwareATCommand("AT+FTPPUT=1"); //Start FTP
  delay(10000);
  SoftwareATCommand("AT+FTPPUT=2,100"); //Send 100 bytes of data
  delay(10000);
  SoftwareATCommand("Hello12345"); //Send Data
  SoftwareATCommand("AT+FTPPUT=2,0"); //Close FTP

}

String SoftwareATCommand(String strAT)
{

  String strNotice = "Sending: " + strAT;
  Serial.println(strNotice);
  mySerial.println(strAT);

  delay(500);
  moduleAnswer = "No Response";

  while(mySerial.available())
  {
    moduleAnswer = mySerial.readString();

    char* buf = (char*) malloc(sizeof(char)*moduleAnswer.length()+1);
    moduleAnswer.toCharArray(buf, moduleAnswer.length()+1);
    Serial.write(buf);//Forward what Software Serial received to Serial Port
     - Module answer sent to screen
    free(buf);
   }

   return moduleAnswer;
}

```

The serial output where the trouble is:

I've tried waiting longer for the `+FTPPUT: 1,1,1360` response or sending something twice, but nothing seems to work. The file gets created but no other data is ever sent.

# Answer
Maybe its too late to respond but the line +FTPPUT: 1,65 indicates a server error.

https://www.elecrow.com/wiki/images/2/20/SIM800\_Series\_AT\_Command\_Manual\_V1.09.pdf \- page 275.

Please check a sequence of commands , maybe something is missing ?

I use the following sequence :

```
"AT+CREG?"
"AT+SAPBR=3,1,\"Contype\",\"GPRS\""
"AT+SAPBR=3,1,\"APN\",\"NAME OF YOUR PROVIDER \""
"AT+SAPBR=1,1"
"AT+SAPBR=2,1"
"AT+FTPCID=1"
"AT+FTPSERV=\"SERVER ADDRESS\""
"AT+FTPPORT=21"
"AT+FTPTYPE=\"I\""
"AT+FTPUN=\"USERNAME\""
"AT+FTPPW=\"PASSWORD\""
"AT+FTPPUTNAME=\"" + NAME OF FILE + "\""
"AT+FTPPUT=1"
"AT+FTPPUT=2," + STRING OF BUFFER SPACE ( Get from response of FTPPUT=1 )
"AT+FTPPUT=2,0"

```

Look on the manual for the commands above.

Sorry about my grammar
> 2 votes

# Answer
what I observed in your code-I think you did not follow the proper sequence of connecting the GPRS context mentioned in the sim800l datasheet. Please follow the section 3.1. bearer configuration. I also attached the screenshot herewith. So you missed setting the Access Point Name(APN). After you query the GPRS context(last step in the image), if you get the proper IP address, then you are sure to send the data over FTP. Please follow the FTP sequence mentioned in the datasheet.
> 1 votes

---
Tags: arduino-uno, softwareserial, gsm
---


title: Using a class inside of another class

text:
# Question
Title: Using a class inside of another class
I have a seemingly simple problem that seems to be popular, but after searching several forums I still have not found the answer: How do you use a class inside of another class?

I have simplified my problem:

```
class A {
  const int pin;
  public:
  A(int attachPin) : pin(attachPin) {
  }

  void setup() {
    pinMode(pin, INPUT_PULLUP);
  }
};

class B {
  A myA;
  public:
  B(int a_attach) : myA(a_attach) {
  }

  void setup() {
    myA.setup();
  }
};

B test;

void setup() {
   test.setup();
}

void loop() {
}

```

# Answer
I think, the problem in that line `B test`. You are define a variable, but you forget to define default constructor ( B() ). You try to setup an A class with unknown pin! To avoid this you may define test variable in that way `B test(2);` or in that way `const int test_pin = 2; B test(test_pin);`. Also to avoid this problem you may to set default value to the constructor sucha as  `B(int attach=2) : myA(attach) {}` and define test variable, as you do in your code `B test;`.
> 1 votes

---
Tags: arduino-ide, class, compilation-errors, object-oriented
---


# Question
Title: I2C communication between arduino and raspberry pi breaks under stress for unclear reasons. Why?
I am having a behavior I cannot explain while using arduino mega as a I2C slave for a raspberry pi master.

I am showing here an idealised program that shows the issue. I experience pretty much the same behavior in the real application (a keyboard firmware). What I am doing is the following:

* the arduino issues an interrupt on pin 23 at evert loop to inform the raspi that there's some data to be read.
* the raspi sends a request as master to the arduino.
* arduino receives the request in the Wire handler, and issues a reply of 32 bytes. I fill these 32 bytes with a uint8 counter just as a check.
* the cycle starts again.

This is the code for the raspi

```
import time
import RPi.GPIO as GPIO
import smbus

GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

bus = smbus.SMBus(1)
address = 0x42

def callback(channel):
    data = bus.read_i2c_block_data(address, 0x00, 32)
    print(data)

GPIO.add_event_detect(4, GPIO.RISING, callback=callback)

while True:
    time.sleep(1)

GPIO.cleanup()

```

and this is the code of the arduino

```
#include <Wire.h>

byte IRQ_PIN = 23;

volatile unsigned int counter;

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

    pinMode(IRQ_PIN, OUTPUT);
    digitalWrite(IRQ_PIN, LOW);
    Wire.begin(0x42);
    Wire.onRequest(requestEvent);
    Wire.onReceive(receiveData);

}

void signalMaster() {
  noInterrupts();
  irq();
  interrupts();
}

void irq() {
  digitalWrite(IRQ_PIN, HIGH);
  digitalWrite(IRQ_PIN, LOW);
}

void requestEvent() {
  byte buf[32];
  counter++;
  memset(buf, counter, 32*sizeof(byte));
  Wire.write(buf, 32);
}

void receiveData(int byteCount){
  while(Wire.available()) {
    Wire.read();
  }
}

void loop() {
  signalMaster();
  delay(1);
}

```

As you can see, the point is that I am banging the I2C really, really fast, and the loop is very tight and fast. This is the point of the exercise and the problem to solve arises from this.

Now, once in a while I get an occasional IO error with the raspi python code. This code occasionally fails once, and then everything resumes to normal, but once in a while, it completely breaks down and never recover.

I attached a logic analyser to it, and this is what I found. D3 is the interrupt pin. The others the I2C bus. In a normal transaction, I can see everything working properly (disregard the different content of the response, it was an earlier run)

and a zoom in to the master request and the reply:

When I have a permanent failure, however, the picture is very different

Zoom in:

This makes little sense to me. Why would it perform a data write, and who is writing 0x85FF... in my buffer?

Thanks

# Answer
> 2 votes
Use a logic level conversion IC.

picture source http://msx-elektronika.pl/en/logic-level-converter

---
Tags: i2c, raspberrypi, atmega2560
---


# Question
Title: How to post HTTP POST requests on my website?
I am working on a NodeMCU board to post sensor data on my website service. Basically my project is about POST and GET requests both in single code.

I am succeeding in sending GET requests from my website. However, I just can't post data to my website.

To post I have 2 different links (asp services): one will post data and another will be used to get data same as transmitted by first link.

Here is my code, and also *how to post 2 variables in http post request*?

```
#include (ESP8266WiFi.h)
#include (ESP8266HTTPClient.h)

const char* ssid = "oppo";
const char* password = "11111111";
int giSwitchNum = 1, buttonPin = 2;

void setup () {
  Serial.begin(115200);
  WiFi.begin(ssid, password);
  pinMode(D1, OUTPUT);
  pinMode(D2, INPUT);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.print("Connecting..");
  }
  giSwitchNum = 1;
  Serial.print("Connect");
}

void loop() {
  if (WiFi.status() == WL_CONNECTED) { //Check WiFi connection status
    HTTPClient Post;
    Post.begin("http://lemontechnologies.net/Services/Service.svc/SetData");
    Post.addHeader("operator", "text/plain");
    Post.POST("Key=hi&val=jagrut1");
    String payload = Post.getString();
    Post.end();
  }
  delay(500);
}

```

# Answer
```
void wifi_connect(){
  WiFi.mode(WIFI_OFF);        //Prevents reconnection issue (taking too long to connect)
  delay(1000);
  WiFi.mode(WIFI_STA);        //This line hides the viewing of ESP as wifi hotspot
  //WIFI_STA It's very important !!!!

  WiFi.begin(ssid, password);     //Connect to your WiFi router
  while(WiFi.status() != WL_CONNECTED){
    delay(1000);
    Serial.print(".");
  }

  Serial.println("Wifi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  return;
}

```
> 1 votes

---
Tags: arduino-uno, nodemcu, http, iot
---


title: Reading data from the MCP3002

text:
# Question
Title: Reading data from the MCP3002
I am using a MCP3002 to convert an analog signal to digital data. It works fine actually, sends good data. However; After a while, when the power is turned off and on again a few times, it only returns zeros. If I Power it on the next day, it works for a while again.

I am just beginning with SPI, so I do not know 'all' the basics. Is there something I should reset when powering on or something? (Clock, Timing, etc.)

This is the code I am using (pretty straightforward):

```
#include <SPI.h>
SPISettings spiSettings(7280000, MSBFIRST, SPI_MODE0);
const int SPI_CS = 2;

void setup() {
    pinMode (SPI_CS, OUTPUT);
    SPI.begin();
    SPI.setBitOrder(MSBFIRST);
    SPI.setFrequency(7280000);
}

void loop() {
    SPI.beginTransaction(spiSettings);
    digitalWrite (SPI_CS, LOW);

    uint8_t cmd = 0b11000000;
    byte msb, lsb;
    word assembled;

    msb = SPI.transfer(cmd);
    lsb = SPI.transfer(0);

    assembled = word(msb, lsb);
    Serial.println(assembled);

    digitalWrite (SPI_CS, HIGH);
    SPI.endTransaction();
}

```

Is there something wrong, or should something be added to this?

# Answer
I thin the following is happening:

The MCP transmits 1 measurement per SPI transaction, which consists of activating chip select, reading data and deactivating chip select. To distinguish between different transactions, the time between deactivation and reactivation of chip select need to have a bit delay between them. Currently your code runs really fast, a few microseconds between the transactions at max.

This may also be connected to the MCP needing time to measure the analog signal.

I think there is some kind of race condition, so that the MCP does not have a new value to transmit, either because the MCP hasn't finished measurement yet, or because the delay between the transactions were just a bit too short, maybe a combination of both.

When the MCP is once in this situation, it will only send zeros at that point (read chapter 5.1 in the datasheet. Last sentence in the left column).

You need to give the MCP more time between the transactions. I suggest using a small delay at the end of the `loop()` function. You can experiment with the actual value, I would guess, that you can go down to the microseconds range.
> 1 votes

---
Tags: spi
---


# Question
Title: Nano 33 IoT rescue from the dead: No USB. No upload mode
First of all: my board used to work fine.

Now my Nano 33 IoT turns ON (green light) when connected to USB on Mac but:

1. doesn't enter in upload mode after pressing twice on board button.
2. doesn't shows up in any serial port: nor `/dev/cu.usbmodem14*01`, neither `/dev/tty.usbmodem14*01`

For reasons too long to explain, I want to connect via ANY pins to the SAMD21 and force the burning of a new bootloader.

Is that possible in any way? Any idea is welcome!

Tx

# Answer
> 2 votes
Use the SWD interface and a programmer to burn the bootloader to SAMD.

source of the picture https://medium.com/@manuel.bl/arduino-in-circuit-debugging-with-platformio-9f699da57ddc

I had luck with Adafruit DAP library using an Arduino M0 to burn a bootloader to MKR Zero.

---
Tags: bootloader, reset
---


title: Esp8266 + Atmega328p as flash

text:
# Question
Title: Esp8266 + Atmega328p as flash
Being clear I'm **not talking about** **How to flash ESP8266 using arduino**. I want to ask **how can I use atmega328p as flash with esp8266** (instead of that 8 pin small chip on ESP-01) so that I can burn Webserver code on Atmega328p and it simply works with esp8266?

Thanks in advance.

# Answer
> 2 votes
It can't be done (also, why would you think that would ever be a good idea?!)

The 8 pin chip on the ESP-01 is a 512kB SPI flash that runs at (at least) 40MHz. So to emulate that you would need:

* More than 512kB of flash,
* A slave SPI interface that can operate at a minimum of 40MHz, and
* The knowledge, time and energy to write the firmware to emulate an SPI flash chip

The first two are certainly beyond an ATMega328P with 32kB flash and an 8MHz maximum speed SPI interface. The third is probably beyond you since you have to ask the question in the first place (which shows a certain lack of knowledge on what it is you are proposing).

There are plenty of examples for creating a web server using an ESP8266 using either the standard AT firmware or by directly programming the ESP8266's flash chip through the ESP8266's built-in UART bootloader. Personally I find the use of AT firmware clumsy at best and prefer to always program my ESP8266's directly. If you feel the need to also add an ATMega328P into the mix for some reason then the communication protocol that you use between them is entirely up to you.

---
Tags: arduino-uno, esp8266, wifi, web-server
---


title: When does interrupt get fired

text:
# Question
Title: When does interrupt get fired
When does the ISR mapped to SPI\_STC\_vect (SPI transmission complete) get fired? Does it fire after a byte has been received (eight clock cycles) of when the slave select changes back to high to deselect the slave? Or: does "transmission" mean the transmission of a byte or the whole bunch of bytes that belong to the command sequence?

# Answer
> 0 votes
It fires after a single byte has been sent or received (the two are one and the same). This is because there is only room for one byte in the buffer, so you need to get it out of that buffer (or put a new one in) after each 8-bit transfer.

---
Tags: interrupt, atmega328, spi
---


# Question
Title: Measuring Battery level with ADC already in use
I have NodeMCU v3 with ESP8266 and I am running small project where I am measuring the input from IR phototransistor via ADC pin (A0) and everything is working flawlessly.
But now I want to transfer it to battery source (powerbank -\> microUSB) and I want to be able to tell the remaining battery capacity, but all tutorials I found were going through switching ADC(A0) to internal, thus disabling it. Is there any other way I can either measure the battery OR input from phototransistor?
Thanks!

# Answer
As @dandavis rightly says in the comments, you can't measure the battery voltage from a power bank. This is because the power bank typically includes a step-up converter to turn the batter voltage (3.2 to 4V) into a stable 5V. That 5V will alwaye be 5V (or thereabouts) until the battery runs out and the power bank shuts itself off.

To measure the battery state you will have to directly interface with the batteries (disassemble the power bank) and tap into the battery terminals themselves.

Some power banks also have LEDs in them to display the power remaining. It could be possible to interface directly with these as well.

One thing to note, though, is that using a power bank for an ESP8266 board is pretty silly. You are taking nominal 3.6V, stepping it up to 5V, then linearly dropping it back down to 3.3V again. Both stages involve power wastage - the 5V to 3.3V most of all (a linear regulator turns the waste voltage into heat).

You would be better removing the batteries from the power bank and wiring them directly to the power input - or better still, feed them through a high efficiency switching regulator to get a stable 3.3V and feed that directly into the 3.3V pin. be sure to include some way of monitoring the battery voltage and shutting off the power when it gets too low. Since your ADC input is already in use the simplest way is to add an external ADC chip to your design.
> 4 votes

---
Tags: esp8266, battery, adc
---


# Question
Title: Connect arduino nano and ESP32 with I2C on the GPIO7 and GPIO8?
I made a mistake connecting SD0 (GPIO7) and SD1 (GPIO8) with the SDA and SCL on my arduino nano. I got confused with GPIO21 and pin21 and GPIO22 and pin 22!

Since I made a PCB prototype, I would avoid to add some wires and cut the traces, so I would ask if I could use these pins (GPIO7 and GPIO8) as SDA and SCL.

If the answer is affirmative, using Arduino library how could I assign them?

Wire.begin (7,8)?

Another question, I would use a dedicate 2x4.7K pull up resistors. On the arduino side I wrote:

digitalWrite(SDA, 0); digitalWrite(SCL, 0);

It is correct to do the same thing on the ESP32 side?

Update November 01: After the question from Majenco I think I need more help for the I2c setup.

I designed the PCB having in mind that the esp32 was 5V tolerant, so at the moment I pull-up the SDA, SCL from the 5V that I input in the esp power pin. Note that this 5V doesn't come from the Nano due to the high current required by the esp. I take my 12V power supply input and regulate it to 5V with a 7805, only dedicated to the esp (I know, a lot of dissipation! In the next PCB version I have to change the things, having in mind that I need both 12V and 5V in my circuit).

Now, I read that the esp32 is not 5V tolerant. In order to avoid level shifter can I pull up the SDA and SCL from the 3.3V line (the arduino 3.3V or esp32 one?)?

I would use the esp32 as master.

Thanks.

# Answer
> Since I made a PCB prototype, I would avoid to add some wires and cut the traces, so I would ask if I could use these pins (GPIO7 and GPIO8) as SDA and SCL.

No, you can't. Those pins are used by the internal flash chip. If you connect things to them you will end up not being able to read the flash and thus won't be able to run any code. In other words, the chip will not boot. So you will have to bite the bullet and cut traces and add bodge wires.

> Wire.begin (7,8)?

Yes. That will control the bus matrix to route the I2C through different pins - but of course you can't use those pins, as noted above.

> On the arduino side I wrote:
>
> digitalWrite(SDA, 0); digitalWrite(SCL, 0);
>
> It is correct to do the same thing on the ESP32 side?

No. That exploits a quirk in the AVR GPIO system that doesn't exist in the ESP32. In the ESP32 the pins are configured with:

```
pinMode(sda, OPEN_DRAIN | PULLUP | INPUT | OUTPUT );

```

and

```
pinMode(scl, INPUT | PULLUP);

```

so you could *try* replicating that in your code but without the `PULLUP` flag. However the effect of this is unknown, so YMMV.

However, if your external pullups are pulling up to 3.3V then you really don't need to do anything on the ESP32. All you end up with is a large resistance in parallel with your 4.7kΩ, which will just cause your resistance to drop slightly (and since 4.7kΩ is arguably too high any way that's a good thing).
> 1 votes

---
Tags: i2c, esp32
---


title: Laser Controller using Arduino Uno

text:
# Question
Title: Laser Controller using Arduino Uno
---\> I am trying to create a controller using Arduino Uno that simply detects pulses from a waveform generator mimicking a Laser Machine and then switches between 4 state machines states at the output of a Pre-amp, it is a built on of this previous post so the connections are the same except for the waveform generator settings. The new waveform generator settings are :

**Type: Pulse, Freq:20Hz (50ms), Amp:5.0 Vpp, Offset:0V, Width = 100ns**

---\> I am trying to add 5 things in the project so any input is greatly appreciated:

1) **Initialize** all the **4 state machine states** into an **Array** so user can define as many states as they want from the declarations.

2) **ADD a digital** de-bounce to the input pin, **LASER\_PIN**.

3)(requires item #5 to be done first) **ADD a reset** to the system which moves the program back to **STATE\_00** from whatever it is doing.

4) Better code to wait until a pulse from Laser arrives before going to the state machine in **void loop()**.

5) (item #2 depends on this) Completely **Remove** delay from the **CountPulses()** function and replace with **millis()** function to allow the use of reset button

---\> Here is what i have so far, i started off by adding 4 state machine states and using the **delay()** function in the **CountPulses()** function just like in the previous post and it works fine and i am able to switch states while counting pulses, however, when i added the **millis() to replace delay()** function as shown below in the code, **i only get** **0s** in pulse count and the state machine is **stuck** in **STATE\_00** so i used a couple of print statements to debug and it turns out currentmillis() - startmillis() is actually less than period = 1000ms so i am stuck on how to set this up and without this i cannot move forward, any help would be appreciated. My code and serial monitor results are shown below:

--\> **UPDATE**: items #3 and #5 work perfectly fine , please see updated code. for item #4 i have not figured this one out yet. for item #2 ,there are a lot of libraries for debounce but not sure which libraries (Button, Bounce and etc) are most trusted by arduino community, any suggestions would help.

--\>**UPDATE 2:** The code has been update with the following changes, external interrupts are used to reset the system if switch is LOW, Polling with interrupts is used to wait for pulses.

**THE UPDATE TO QUESTION**: items#3, 4 and 5 were solved and now only 2 items remain to be added to the project with modifications to item #1 and item #2 based on comments:

1) I require the state machine to do the following:

a) Declared in an array where user can easily change the order of execution of states. (eg: state\_2--\> state\_1 --\>state\_3--\> state\_0).

b) User can easily decrease the number of states from MAX\_VALUE = 4 to only 1 state. (eg with MAX\_VALUE = 3: state\_0--\> state\_1--\> state\_2) .

2) **ADD a digital** de-bounce to the input pin, **RESET\_PIN**. Note: The debounce to LASER\_PIN was a mistake in understanding based on the comments, so i have updated this.

Updated code with current serial monitor results is shown below:

```
       //Objectives: Use input from laser to control pre-amp on adc. Multiplex the inputs on Pre-Amp
//Date:10/21/2019
//Type: Pulse, Freq:20Hz (50ms), Amp:5.0 Vpp, Offset:500mV, Width = 100ns

//-----------------------PROJECT LIBRARIES----------------------------------
#include <Bounce2.h>
#include <Arduino.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
//-----------------------DEFINES------------------------------------------
//Declare Laser Input Pin
#define LASER_PIN 2

//Declare Reset Pin
#define RESET_PIN 3

//Define the states of the machine
typedef enum {STATE_00, STATE_01, STATE_10, STATE_11} fsm_state_type;
fsm_state_type fsm_state = STATE_00;

// -------------------------CONSTANTS (won't change)-------------------------------------
const unsigned long period = 1000;  //the value is a number of milliseconds

//-------------------------VARIABLES (will change)-------------------------------------
bool only_for_print = false;//used only for print state ments

int reset_switch = 1;//Start HIGH to avoid reset
int PulseCount = 0; //Pulse count from X-RAY
int Output = 0;//Switch state on the Pre-Amp
int wait = 0;//wait for pulses count
int N = 20;//no. of pulses to count before switching states
volatile int IRQcount = 0;
volatile boolean reset_flag = false;

unsigned long start_time = 0;
unsigned long current_time = 0;

//----------------------------USER DEFINED FUNCTIONS---------------------------------
void fsm();
void loop();
void setup();
void WDT_RESET();
void IRQcounter();
void CountPulses();
//-----------------------------DEBOUNCE FUNCTIONS---------------------------------------

//--------------------------------MAIN SETUP--------------------------------------

void setup()
{

  Serial.begin(115200);

  //Pin Setup
  pinMode(LASER_PIN, INPUT_PULLUP);
  pinMode(RESET_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(LASER_PIN), IRQcounter, RISING);//attach interrupt handler to laser input
  attachInterrupt (digitalPinToInterrupt (RESET_PIN), RESET_ISR, FALLING);  // attach interrupt handler to reset, wait for user press button or switch
  start_time = millis();   //initial start time
  sei();//Turn on Interrupts

    WaitForPulses();//Waits to detect 20 pulses
}

//--------------------------------MAIN LOOP----------------------------------
void loop()
{

 current_time = millis();
 fsm();//State machine
}

//--------------------------------PULSE COUNT FUNCTION--------------------------------------------

void CountPulses()
{
  //  current_time = millis();
  if ((current_time - start_time) >= period)
  {
    start_time = current_time;
    cli();//disable interrupts
    PulseCount = IRQcount;
    IRQcount = 0;
    Serial.print(F("Pulse Count is = "));
    Serial.println(PulseCount);
    sei();//enable interrupts
  }
}

//--------------------------------STATE MACHINE FUNCTION--------------------------------------------
void fsm()
{
  switch (fsm_state)
  {

    case STATE_00:

/////////Print Statement only for debugging//////////
        while (only_for_print == false)
        {
            Serial.println("The state is 00");
            only_for_print = true;
        }

///////// Count Pulses Setup /////////////////
            current_time = millis();
            CountPulses();
            Output = 0;
            if (PulseCount == N)
            {
              PulseCount = 0;//Reset Pulse Count
              only_for_print = false; //used only for print statments
              fsm_state = STATE_01;//switch to next state
            }
      break;

    case STATE_01:
/////////Print Statement only for debugging//////////
      while (only_for_print == false)
      {
          Serial.println("The state is 01");
          only_for_print = true;
      }

///////// Count Pulses Setup /////////////////
          current_time = millis();
          CountPulses();
          Output = 2;
          if (PulseCount == N)
          {
            PulseCount = 0;//Reset Pulse Count
            only_for_print = false; //used only for print statments
            fsm_state = STATE_10;//switch to next state
          }
      break;

    case STATE_10:
/////////Print Statement only for debugging//////////
      while (only_for_print == false)
      {
          Serial.println("The state is 10");
          only_for_print = true;
      }

///////// Count Pulses Setup /////////////////
          current_time = millis();
          CountPulses();
          Output = 3;
          if (PulseCount == N)
          {
            PulseCount = 0;//Reset Pulse Count
            only_for_print = false; //used only for print statments
            fsm_state = STATE_11;//switch to next state
          }

      break;

    case STATE_11:
/////////Print Statement only for debugging//////////
      while (only_for_print == false)
      {
          Serial.println("The state is 11");
          only_for_print = true;
      }
///////// Count Pulses Setup /////////////////
          current_time = millis();
          CountPulses();
          Output = 4;
          if (PulseCount == N)
          {
            PulseCount = 0;//Reset Pulse Count
            only_for_print = false; //used only for print statments
            fsm_state = STATE_00;//switch to next state
          }

      break;

    default:
      fsm_state = STATE_00;
      break;
  }

}

//----------------------------------RESET SWITCH ISR-------------------------------------

void RESET_ISR()
{
  reset_flag = true;
  if(reset_flag == true)
    {
     // Serial.println("System will now Reset");// Only for debugging
      reset_flag = false;//Reset reset switch flag
      wdt_enable(WDTO_500MS);//Reset after 0.5 seconds
      while (1)
       {
         // wdt_reset();          // uncomment to avoid reboot
       }
    }
}

//-----------------------PULSE COUNT ISR---------------------------------------

void IRQcounter()
{
  IRQcount++;
}
//-----------------------WAIT FOR PULSES---------------------------------------
void WaitForPulses()
{
  while(wait<20)
 {
    if (bit_is_set(EIFR, INTF0))
    {
      Serial.println("Pulse is detected ");
      wait++;
    }
 }
 wait = 0;//reset
}
*/

```

\[!\[edited image\]\[3\]\]\[3\]

The serial monitor is shown below with added reset switch on pin 3 using watch dog timer library .

```
 Pulse is detected
Pulse is detected
Pulse is detected
Pulse is detected
Pulse is detected
Pulse is detected
Pulse is detected
Pulse is detected
Pulse is detected
Pulse is detected
Pulse is detected
Pulse is detected
Pulse is detected
Pulse is detected
Pulse is detected
Pulse is detected
Pulse is detected
Pulse is detected
Pulse is detected
Pulse is detected
The state is 00
Pulse Count is = 112
Pulse Count is = 20
The state is 01
Pulse Count is = 20
The state is 10
Pulse Count is = 20
The state is 11
Pulse Count is = 20
The state is 00
Pulse Count is = 20
The state is 01
Pulse Count is = 20
The state is 10
Pulse Count is = 20
The state is 11
Pulse Count is = 20
The state is 00
Pulse Count is = 20
The state is 01
Pulse Count is = 20
The state is 10
Pulse Count is = 20
The state is 11
Pulse Count is = 20
The state is 00
Pulse Count is = 20
The state is 01
Pulse Count is = 20
The state is 10
Pulse Count is = 20
The state is 11
Pulse Count is = 20

```

# Answer
> 0 votes
### Important note:

*After reading (again) your other question and its answers: **You are stressing the input of your Arduino with negative voltages!** Please set the offset of the signal to 2.5V (the middle between GND and VCC) and the amplitude to 5Vpp. **The signal must neither be lower than GND nor higher than VCC!** The input might withstand this for a while but given enough time and power it **will** get damaged.*

### Analysis of your problem:

**1. The measurement of the period**

Let's take a look at a "condensed" version of your time code:

```
void setup()
{
  startMillis = millis();
}

void loop()
{
  currentMillis = millis();
  if (currentMillis - startMillis <= period)
  {
    startMillis = currentMillis;
  }
}

```

I'm sure you see it now, too! Because right at the first call of `loop()` the time passed since `setup()` is short, the condition is `true` and `startMillis` is updated to the current time. This is repeated ever and ever again. The condition will always evaluate as `true`.

**2. The number of pulses**

In the function `CountPulses()` the counter is reset at the beginning. Then after some undefined very short duration (because your `if`-condition is always `true`) it is read. Chances are low for a pulse to be counted in that time span.

### Additional note:

Just one more tip. You can define and use your own data types to show your intentions. For example the states look so much better like shown below, and you'll get free error messages from code analyzers.

```
typedef enum {
    STATE_00, STATE_01, STATE_10, STATE_11,
} fsm_state_type;
fsm_state_type fsm_state = STATE_00;

```

**EDIT after you added new informations:**

### Item #2

Why do you think you need to debounce the laser pulse? Is it generated by a mechanical switch? Only those need debouncing. If the pulses are generated from some electronic circuit they should be clean.

### Item #4

You can reset the `IRQcount` and then wait for it to count up.

But as this involves disabling and enabling the interrupt and reading an `int` just for **1 event**, I'd rather set a flag if the interrupt occurs. Then the FSM could wait for the flag to be set.

Another alternative is to poll the input pin directly and to wait for the leading edge. But for this the pulse has to be wide enough.

As @EdgarBonet pointed out it will be even simpler to poll the interrupt flag. But IIRC the interrupt has to be disabled for this, else the call of the interrupt service routine will clear the flag with no chance for the main program to see it.

> A better alternative is to poll the interrupt flag (i.e. `if (bit_is_set(EIFR, INTF0)) { ... }`). Then you don't need a wide pulse: once the hardware detects the rising edge, the flag is set and remains set until you explicitly clear it (`EIFR = _BV(INTF0);`).

---
Tags: arduino-uno, interrupt, c
---


# Question
Title: Audio stops playing after rtc is connected
I am trying to play a song using arduino while at the same time display time using a rtc board using the tmrpcm library. However, if the rtc board is connected no sound is played.

I do understand that the tmrpcm may be interfering with the wire.h library but even commenting the same doesn't resolve the problem.

I am using the following code:

```
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
#include <RTClib.h>
#include<Wire.h>
#include <Arduino.h>
#include "SevenSegmentTM1637.h"
#include "SevenSegmentExtended.h"
#include "SevenSegmentFun.h"
#include "SD.h"
#define SD_ChipSelectPin 4
#include "TMRpcm.h"
#include "SPI.h"

TMRpcm tmrpcm;

const int ProxSensor=3;
int inputVal = 0;
#define CLK 8
#define DIO 7

// The amount of time (in milliseconds) between tests
#define TEST_DELAY   2000

SevenSegmentFun    display(CLK, DIO);

RTC_DS1307 rtc;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

void setup () {
  Serial.begin(9600);
  if(!SD.begin(SD_ChipSelectPin))
  {
    Serial.println("SD fail");
    return;
  }
  while (!Serial); // for Leonardo/Micro/Zero
  tmrpcm.speakerPin=9;
  Serial.begin(57600);
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(2019, 10, 19, 01,41,00));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
  pinMode(ProxSensor,INPUT);    //Pin 2 is connected to the output of proximity sensor
  display.begin();
}

void loop(){
  DateTime now = rtc.now();
  display.print((now.unixtime() / 86400L )-17963);
  Serial.print((now.unixtime() / 86400L )-17963);
  while(digitalRead(ProxSensor)==LOW)      //Check the sensor output
  {
    tmrpcm.setVolume(5);
    tmrpcm.play("test.wav");
      repeat:
    if(digitalRead(ProxSensor==LOW))
      goto repeat;
  }
}

```

Can anyone please help me?

# Answer
The TMRpcm and one of your other libraries might use the same timer on Uno which causes one of them to break. Either get a Arduino Mega which can run TMRpcm on TIMER3,4 or 5 or use libraries that don't require a timer.
> 0 votes

# Answer
The problem is

```
repeat:
if(digitalRead(ProxSensor==LOW))
  goto repeat;

```

`ProxSensor==LOW` is false so 0. **you read the pin 0** and the outcome is random. The surrounding wiring can affect that. If digitalRead(0) is zero the wav starts playing immediately again. At least use

```
while (digitalRead(ProxSensor) == LOW);

```
> 2 votes

---
Tags: arduino-nano, sd-card, audio, rtc, tmrpcm
---