text:
Can I read two PWM signals and output two square waves on an UNO?
My system requires that I read two independent PWM signals (60hz) and output two corresponding square waves. These output square waves vary in frequency according to their corresponding input duty cycle. The output frequencies will vary between 1-60Hz. (outside of tone() range)
I'm planning out the best way to approach this project.
My initial thought is to use the two available external interrupts set to CHANGE to measure the inputs. I believe I'll also need to reference a timer in this routine, to determine the time since the last change.
Unless I'm mistaken, it looks like I will also need a timer interrupt for each output, to control the frequency properly.
The Arduino UNO has 3 timers. timer0: 8bit (used internally), timer1: 16bit, and timer2: 8bit. In short, can I run all of these interrupts in the same code? Will I run out of timers, or can I multitask the timers between my requirements?
Thanks!

I never used timers/interrupts directly on an Arduino, and it is possible the best way. However, for so slow rates (upto 60 Hz), polling the 2 sensors and even use a delay would still be valid (1000 ms / 60 hz) = 16 ms. That is a lot of time , even for an Arduino.

If I approach it that way, I suppose I could probably read/write all the information with a timer interrupt every 100us or so, as long as I keep the code brief. Resolution isn't a large problem for me here, so that could work - thanks.

You can even not using a timer at all ... if resolution is not a problem, even polling (maybe with one ms delay) could work. But if you want to learn more about a better way, use timers/interrupts.

Your signals are slow enough that you may not need any timer. You can
just use the Arduino micros() function to handle all your timings. Of
course, micros() itself relies on Timer 0, but you don't need to
access any timer directly.
I would use the external interrupts in CHANGE mode to measure the duty
cycle. For example:
const uint8_t INPUT_0_PIN  = 2;  // digital 2 is also INT0
const uint8_t OUTPUT_0_PIN = 4;

// Measured duration of the HIGH level of input 0.
static volatile uint32_t input_0_high_time;

// Interrupt handler invoked when input 0 toggles.
static void on_input_0_change()
{
    static uint32_t time_rise;             // last time the signal rose
    uint32_t now = micros();
    if (digitalRead(INPUT_0_PIN) == HIGH)  // detected rising edge
        time_rise = now;
    else                                   // detected falling edge
        input_0_high_time = now - time_rise;
}

void setup()
{
    pinMode(INPUT_0_PIN, INPUT);
    pinMode(OUTPUT_0_PIN, OUTPUT);
    attachInterrupt(0, on_input_0_change, CHANGE);
}

For handling two inputs, you can duplicate everything that has a 0 in
its name and name it with a 1. If your signal is no slower than
60 Hz, you can also replace all uint32_t by uint16_t to make
the code slightly faster.
For generating the outputs, do something similar to the Blink Without
Delay example:
void loop()
{
    uint32_t now = micros();

    // Determine suitable period for output 0.
    uint32_t input_0_high_time_copy;
    noInterrupts();  // avoid race condition while reading
    input_0_high_time_copy = input_0_high_time;
    interrupts();
    uint32_t output_0_half_period =
            map(input_0_high_time_copy, 0, 16666, 8333, 500e3);

    // Toggle output 0 when needed.
    static uint32_t time_output_0_toggle;
    static uint8_t output_0_state;
    if (now - time_output_0_toggle >= output_0_half_period) {
        time_output_0_toggle += output_0_half_period;
        output_0_state = !output_0_state;  // toggle state
        digitalWrite(OUTPUT_0_PIN, output_0_state);
    }
}

Again, you can handle two outputs by duplicating the code and replacing
0 with 1. Note that you cannot replace uint32_t by uint16_t,
as it would not work for the slowest frequencies.
Edit: Now we may ask the question whether it is possible to use some
timers to make all this more accurate. The answer is yes, you could
achieve maximum accuracy by using four 16-bit timers:

You could use the input capture function of a 16-bit timer, with the
prescaler set to 8, to measure the transitions of one of your
inputs with a resolution of 0.5 µs.
You could use a 16-bit timer in CTC mode, with the prescaler set
to 256, to toggle one of your outputs at the desired frequency, with a
16 µs resolution.

For reference, micros() has a resolution of 4 µs. The 16 µs
resolution of the timer-generated output seems poor in comparison, but
the timer has the advantage of having zero jitter.
Now, for doing that that, you would need an Arduino Mega 2560. The Uno
has only one 16-bit timer, so it could help with only one of your two
channels.
There is still something you can do with a single 16-bit timer. Set it
to normal counting mode, with the prescaler at 8, and use it
instead of micros() for timing your inputs: in setup()
// Configure Timer 1.
TCCR1A = 0;          // normal counting mode
TCCR1B = _BV(CS11);  // clock at F_CPU/8

and in the interrupt handler, you replace uint32_t now = micros(); by
uint16_t now = TCNT1;

And now you have input_0_high_time (which should also be uint16_t)
in units of 0.5 µs.

Your approach is generally sound.
Depending on the square waves you are generating, one timer can generate two pulse train with independent duty cycles but dependent phases.
That leaves two times for measuring the duty cycles of the input pulse train.
But replicating the input pulse trains makes zero practical sense.


text:
Arduino and Optoisolators
I am looking for an efficient (and safe) way to use the Arduino to switch a higher voltage device off and on. The first option would be a relay, but they are fairly bulky. I was wondering if I should use an Optoisolator instead ?
Here is a link to the Data sheet for the Optoisolator I am using..
http://www.everlight.com/file/productfile/el817.pdf
I think (if I am reading it correctly) it expects an input voltage of 1V at about 20mA ?
However, I think it may be more involved than I originally thought. Here is a sort of simulation of what I am trying to achieve.
http://tinyurl.com/y9xd7lzb
As you can maybe tell, I am using a voltage divider to reduce the output from the arduino (from 5V to 1V).
My concerns are ..

Is this the best approach ?
Is it efficient ?
are there any problems I should be aware of ? Precautions I need to take ?
Is the voltage divider a good approach to feed the input to the Optoisolator ?

Also, efficiency is an issue as the Arduino (probably a Nano) will be running off batteries.
The target device is a 20V DC motor. I am a novice when it comes to electronics, so I would be grateful of any help or advice you can give.
Many thanks..
Dave.

How much current does the motor need ? An opto-isolator is always a safe solution. Often a opto-isolator is used to control a mosfet, but there are also opto-mosfets. The EL817 is 1 mA to 60 mA with 20 mA as normal. It is no problem to use 10 mA. For 10 mA, you need ( 5V - 1.2V ) / 20 mA = 380 ohm. Just one resistor of about 330 ohm to pin 1 is okay (and pin 2 to GND).

Is this the best approach ?

Not really, no.

Is it efficient ?

No, far from it.

are there any problems I should be aware of ? Precautions I need to take ?

You don't want a voltage divider to power an opto-isolator. An opto-isolator won't be powerful enough to cope with the motor current. You need flyback protection.

Is the voltage divider a good approach to feed the input to the Optoisolator ?

No, definitely not.
Unless you require galvanic isolation all you need is a simple NPN transistor or N-channel MOSFET circuit:

simulate this circuit – Schematic created using CircuitLab

your optocoupler's 2ndary side isn't powerful enough to switch a load.
use the 2ndary side to switch a switcher, instead.

source: Stack Exchange

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

sort: votes


text:
Analog read negative voltage inbuilt protection
I'm trying to read a -10 to +10V analog signal on my Arduino Mega (2560). I've been using a voltage divider to obtain a -5V to +5V signal (with two 10kOhm resistors), which used to work just fine.
I'm wondering if this -5V signal can damage the Analog Input pins of the Mega ?
Thank you in advance for your time !

I'm sorry, but what type of reading would you like to obtain from that signal?Because you'll not be able to read anything negative...

All the IO pins contain a pair of clamping diodes to protect against over-voltage and negative-voltage situations:

As long as the current flowing through one of those diodes doesn't exceed its maximum forward current all will be well and the Arduino won't be damaged. If too much current flows then you will damage the pin.
Since you have 10KΩ resistors, at -5V the maximum current that could flow (assuming a 0.7V drop on the diode) would be (-5 + 0.7) / (10,000 / 2) = -860µA (negative because it's flowing backwards out of the pin from ground to your negative voltage source, not into the pin to ground).
Unfortunately the datasheet doesn't provide a current limit specification for those diodes, but I would expect such a small amount of current to be safe enough.

It’s 860 µA. See my comments to KIIV’s answer.

Current through the clamping diodes shouldn't be more than 1mA according to Atmel's Zero Cross Detection Application Note (AVR182).
EDIT: As Edgar Bonet pointed out you have current about (-5+0.5)/(10000/2) = 0.9mA (tested) in the worst case, there is not much space for mistakes.

+1 for finding that important spec buried inside an obscure application note.

Well, it wasn't me: Max current for AVR IO protection diodes on AVRFreaks. I've seen that thread before so it wasn't so hard.

It should be noted that the voltage divider is Thévenin equivalent to a ±5 V source with 5 kΩ output resistance. Thus the max current is (5 V − 0.7 V) ÷ 5 kΩ = 0.86 mA. This is assuming a 0.7 V drop in the diode.

The pin might not be damaged, but he will never read anything on the negative side of the signal....

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


text:
Storing a counter to EEPROM - how to extend the life?
I am building a circuit that has a button, which when pressed, should increment a counter. I want to store this counter so that when I power off my circuit, it can be read when I power it back on. However, I am worried about the lifetime of the EEPROM - apparently it is only rated to handle 100k writes.
I am using an Adafruit Trinket Pro. Should I cycle my writes through different addresses so as not to write to a single cell over and over? What other strategies are there? I don't expect to be pressing the button many times in a short period of time - maybe at most one press per minute.
Is there some other external storage option I should look at? I really don't want my little project to die randomly one day because I've exceeded ~100k button presses!

Welcome to Arduino Stack Exchange.  Please take the tour at https://arduino.stackexchange.com/Tour to get the most out of this site.

There is an excellent application note on this subject. Please see AVR101 http://www.atmel.com/images/doc2526.pdf

Why not have a second button you push before powering off and have that trigger the write to EEPROM?  I have a sketch that modifies data once a second and need to be able to switch off without losing data, and this is how I am handling it.

Or have a storage cap and a circuit to trigger storing the counter into the eeprom on power loss suing the cap as a temp powersource.

If possible use a combination of wear-leveling like algorithm (as pointed out by Mikael Patel) and an power-down driven interrupt, to save onto EEPROM only when needed. At reset, load the last keypress count into a variable in RAM. Increment that variable in RAM on keypress, and save it to EEPROM only when a power down occurs (i.e. the interrupt is triggered). Optionally, when power down occurs, make sure to save the variable only if the new counter actually differs from the old value (i.e. if there actually were keypresses).
To implement the power-down driven interrupt use the built-in comparator to monitor a Vin (use a resistor divider!) against the internal Vref, and use the analog comparator interrupt to save the value. Remember to put enough capacitance between +5V and gnd, to make sure your arduino has enough time to save the state.
Alternatively, if you can afford errors (which might accumulate over time, and lead to a huge underestimation), save the value to EEPROM only every n keypresses.

maybe at most one press per minute.
That's great! You can just make some sort of timer to save every 2 or 3 minutes automatically. You said at most, so that should work. Here is example of code that can allow you to do so!
int cycleCnt = 0;    //Counter to count cycles
int cnt = EEPROM.read(0);         //Your press counter
bool currentlyCounting = false;   //Boolean to store if we are counting now or not
bool pressedBefore = false;

void loop() {
  if (digitalRead(button_pin) == HIGH) {    //You are holding the button
    if (!pressedBefore) {                   //And you didn't press it before
      //Here you do something you need with button
      currentlyCounting = true;       //After you pressed the button, we are starting to count time
      cycleCnt = 0;                        //and reset current counter (which would save us EEPROM writes!)
      cnt++;

      pressedBefore = true;                 //Mark button to be pressed so you don't do same code more then one time
    }
  }
  else pressedBefore = false;               //Mark, that you've unpressed the button

  delay(50);      //Delay in 50 mil won't affect speed of your button press, but it will allow us to count time
  if (currentlyCounting) cycleCnt++;          //Count cycles (every 50 mil)

  if (cycleCnt == 20 * 120) { //20 - amount of loop cycles to wait for one second. 120 - seconds in 2 minutes
    cycleCnt = 0;
    EEPROM.write(0, cnt);
    currentlyCounting = false;
  }
}

This might help you as well!
In case I misunderstood you and you meant "1 minute is the highest delay time beetween presses" then you should save automatically every half of minute or so

Use brown out detection. Keep the count in ram until the mcu is losing power - only then save it to eeprom. Read the datasheet on bor.

Cycling through the EEPROM is possible.
Is that button capable to last more than 100k presses ?
A button press every minute ? Really ? Is that during working hours ? That would take about year to get near the 100k writes (5 days per week, 8 hours per day, every minute).
If you want to count more than 100k key presses, then you probably store it in a 32-bit integer. That is 4 bytes. That means that when the Arduino is turned off while in the middle of writing that number to the EEPROM, that number is corrupted and lost forever.
With 1k EEPROM, you have 256 positions for the 32-bit integer. That means you can handle 25 million key presses.
My suggestion would be to store each new value of the 32-bit integer to the next location (circular). At startup you need code that interprets the numbers to find the last one and ignores a bad one and can handle a new Arduino with cleared EEPROM and even an Arduino that was used by you to develop the code. That means you need a command to clear the EEPROM.


text:
Initially my Arduino executes a series of PWM signals simultaneously, but after some iterations it adds around a second between PWM executions
I am using 2 adafruit PWM servo shield in order to generate 25 PWM signals. In particular I am using this shield: https://www.adafruit.com/products/1411
A python script sends the commands to the Arduino (Mega 2560) through pyserial. The commands are like "A0 P1 S500\n". Each argument separated by a space. The first chooses the shield, the second one the pin, and the third one the speed.
The code running in the Arduino is as follows:
#include <Adafruit_PWMServoDriver.h>

#define BUFFER_SIZE 200

// Init both adafruit boards
Adafruit_PWMServoDriver pwm0 = Adafruit_PWMServoDriver(0x40);
Adafruit_PWMServoDriver pwm1 = Adafruit_PWMServoDriver(0x41);

int read_command(char *buffer)
{

    static int pos = 0;
    int rpos;

    if (Serial.available() > 0) {
        Serial.println(Serial.available());
        char readch = Serial.read();

        switch (readch) {

            case '\n':
                rpos = pos;
                pos = 0; // Reset position index ready for next time
                Serial.println(buffer);
                return rpos;

            default:

                if (pos < BUFFER_SIZE -1) {
                    buffer[pos++] = readch;
                    buffer[pos] = '\0';
                } else {
                    Serial.println("666"); //buffer overflow
                }
        }
    }
    // no end line or char found, return -1
    return -1;

}

void parse_command(char* command)
{

    char* parameter;
    parameter = strtok(command, " ");
    long shield, pin, speed;

    while (parameter != NULL) {

        switch(parameter[0]) {

            case 'A':
                shield = strtol(parameter+1, NULL, 10);
                break;

            case 'P':
                pin = strtol(parameter+1, NULL, 10);
                break;

            case 'S':
                speed = strtol(parameter+1, NULL, 10);
                break;

        }
        parameter = strtok(NULL, " ");
    }

    for (int x=0; x < BUFFER_SIZE; x++)
        command[x] = '\0';

  if (shield == 0)
    pwm0.setPWM(pin, 0, speed);

  if (shield == 1)
    pwm1.setPWM(pin, 0, speed);

}

void setup()
{

  Serial.begin(9600);
  Serial.flush();

  pwm0.begin();
  pwm0.setPWMFreq(100);  //Max is 1600, Kevin was using 1000
  pwm1.begin();
  pwm1.setPWMFreq(100);

}

void loop()
{

  static char buffer[BUFFER_SIZE];

  if (read_command(buffer) > 0)
    parse_command(buffer);

}

As said, I am sending the commands from a Python script, where for example I have a function called "activate all", that will send 25 commands like "A0 P1 S500\n" (obviously with different values after the A and the P) to the serial port. I also have a function called "disable all", which is very similar to the previous command, but setting the S to 0 so like "A0 P1 S0\n".
So, as I start the serial communication, if I execute from Python "activate_all", I can how all the PWM signals are generated at the same time. I know it is actually 1 by 1, but it is fast enough to seem simultaneously to the human eye. If I then send a disable_all, I can see how all the PWM signals are set to 0 at the same time.
This works as expected for a while, but after some point, when I send an activate_all, it will indeed activate all of them, but it activates each PWM signal one by one, with a delay of around 1 second between activations (so you can clearly see them going one by one), and a very similar effect when disabling them all. From this point on, which seems slightly different each time, every time I want to activate more than one pwm signal at the same time, it will add this 1s delay between activations.
The only way I have to fix this is to send from the python a "flush()". which seems to be fix it. Doing flushes from the Arduino code, like when for example serial.available is 0, doesnt seem to fix it.
I don't know what exactly I am doing wrong. I guess the way I am handling the communication buffer is wrong, but I haven't seen where my mistake is.
A very similar code to the one pasted here was used in another project, in that case it was interfaced with Labview, and in that case everything seem fine.
In case you wonder about the code running in the Python script, it is like this:
import serial, time, json

class BZBoard:

    def __init__(self, port):

        self.ser = serial.Serial(port, 9600, timeout=120)
        time.sleep(2) # serial docs recommend a wait just after connection
        self.ser.flush(); self.ser.flushInput(); self.ser.flushOutput();

        self.motors = {
            just naming the pins
            }

    def __del__(self):

        self.disable_all()
        self.ser.close()
        del self.ser

    def close(self):

        self.disable_all()
        self.ser.close()
        del self.ser

    def activate_motor(self, motor_code, speed=300):
        ''' code as in A1 or C2 as marked in the actual board. See the dict motors'''

        shield, pin = self.motors[motor_code]
        command = "A%d P%d S%d\n" % ( shield, pin, speed )
        self.ser.write(command.encode())

    def activate_all(self, speed=300):

        for key in self.motors.keys():
            self.activate_motor(key, speed)

    def disable_motor(self, motor_code):

        shield, pin = self.motors[motor_code]
        command = "A%d P%d S0\n" % ( shield, pin )
        self.ser.write(command.encode())

    def disable_all(self):

        for key in self.motors.keys():
            self.disable_motor(key)

if __name__ == "__main__":

    board = BZBoard("/dev/ttyACM0")

So the user will do for example a lopp that repeats itself 20 times, where it will activate_all, wait 1 second, disable_all, wait 1 second. The first 10 iterations or so, everything will be fine and the PWM are generated all of them at the same time (with respect to the human eye), but after that, the PWM signals are generated 1 by 1, with a delay of 1s or so between them.

If you comment out all the Serial output (ie Serial.print() or  Serial.println()) does the problem still occur?

@jwpat7 yes. initially there was no serial output. I added it to debug

Your sketch generates greater output for each character of input, so unless you have pacing in your sending code, it will fall behind.  It's also possible that your sending code is filling up the transmit buffer that drip-feeds data through the slow serial link.  And it's not clear if you are claiming the response data or just letting it fill up an input buffer in the PC operating system.

@ChrisStratton by greater output you mean the PWM signals generated through Adafruit? I think also I have a lot of pacing. I have executed the same code with sleeps of 5 seconds, and the same problem appears. I don't understand what you mean about the transmit buffer, in particular when you say if I am claiming the response data or not. Could you help me with that? thanks for reading my question

There seems to be reason to think about filled buffers causing stalls and timeouts, but comments regarding 5-second sleeps between trials seem to rule that out.  To debug what's actually happening, you might blink an LED each time you receive a character, and another LED each time you call your parse_command() routine; and if you have an oscilloscope, look at the serial transmissions back and forth to see whether delay is due to something at the Arduino end vs at the host end.
That said, I think it would make sense to simplify the protocol by getting rid of your input buffer and just processing input as it comes.  For example, you could use the following letters as post-fix actions.
A  Select shield 1
B  Select shield 2
P  Set pin number, eg 11P selects pin 11
S  Set speed, eg 472S sets speed to 472
N  Send current speed to current pin, then increment pin number

For example, the command sequence for “disable_all” could look like:
0S0PANNNNNNNNNNNN 0PBNNNNNNNNNNNNN

This is easy to parse on the fly; declare int val=0 and any other needed variables before loop(), then within loop() say:
  char inc;   // For incoming character
  while (Serial.available()) { // Get characters
    inc = Serial.read();
    if (inc >= '0' && inc <= '9') {
      val = 10*val + (inc-'0');
    } else {
      switch (toupper(inc)) {
      case 'A':
        board = 0;
        break;
      case 'B':
        board = 1;
        break;
      case 'P':
        pin = val;
        break;
      case 'S':
        speed = val;
        break;
      case 'N':
        if (PinNumberIsOk(board, pin))
          pwm[board].setPWM(pin, 0, speed);
        ++pin;
        break;
      default :
        ; // handle blanks, returns, whatever
      }
      val = 0;  // Set val to zero on any non-digit
    }

As another example, the sequence 4PA 11SN13SN17SN would send speeds 11, 13, and 17, respectively, to motors 4, 5, 6 on the first shield.


text:
Arduino Serial Output Gone Wild!
I'm having a slight problem that I'm unable to work out. I am using an arduino Uno to print an incremental, but predefined wheel circumference. This is all working beautifully except it gives a negative reading during execution, and then runs into the positive etc. Without being exact, the output is something like the following:
1.85, 3.71, 5.56, 7.41, 9.27, 11.15....
When this multiple reaches 32.00 or greater, it then counts negatively back down to zero, then positively up to 32.00 again.
I can't quite work out why this would be, so hoping that one of you guys would be able to shed some light. The code is as follows:
#include <Arduino.h>

int InterruptPin = 2;
int circ = 1854; //mtrs
int km = 0;

void calculate(){
    km = km + circ;
    //float temp = km / 1000;
    float temp = (float)km / (float)1000;
    Serial.println(temp);
}

void setup(){
    pinMode(InterruptPin, INPUT);
    attachInterrupt(digitalPinToInterrupt(2), calculate, RISING);
    Serial.begin(9600);
}

void loop(){

}

km is never reset but continously incremented.
km = km + circ;

This leads to an overflow of the value after some time.
When you declare int km;, then int  on an Arduino Uno is int16_t, it thus has a maximum positive value of 2^15 - 1 = 32767. Since circ is constant 1854, after executing the ISR a total of CEIL(32767 / 1854) = 18 times, km becomes greater than that maximum positive value. Thus an integer overflow occurs which takes you back to the maximum negative value of the int16_t. (See https://en.wikipedia.org/wiki/Integer_overflow)
You might want to use uint32_t or similiar from stdint.h if you want to cover a greater value range. I think however your underlying algorithm is flawed, since even then km will  overflow after some later time. You must reset it at some point or only store the number of revolutions, which is a much smaller number. If you want to get the traveled distance then, you take the number of revolutions and multiply it by the circumference.
Also you should not not use any Serial printing within in interrupt service routine! And you should also declare your used interrupt variables as volatile. Read this article for more info.

I would recommend unsigned long for large integer values. (it is uint32_t on 8-bit AVR)

Thanks, some very constructive critisism and a brilliant explanation.


text:
Arduino program has suddenly stopped updating
I am writing a speedo/odometer program which was all working beautifully until I introduced an LCD screen and code for the LCD.
The screen works on power up, displays the distance recorded on an SD card, toggles from miles to km on the press of a button, but no longer runs my calculate method when invoked. The method has stopped working, or at least it's not updating with the latest information anymore when the method instructs it to. Any help would be greatly appreciated.
In case it matters, I am powering the project from an HTC one M8. Maybe it's lack of juice that is causing the issue, or just bad programming?
My code:
#include <Arduino.h>
#include <SPI.h>
#include <SD.h>;
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

int InterruptPin = 2;
//int PowerPin = 3;
int ButtonPin = 4;
int SDPin = 7;

volatile long km = 0; // SAVE
volatile float kmTemp = 0; // SAVE
volatile int kmrevs = 0; // SAVE
volatile long miles = 0; // SAVE
volatile float milesTemp = 0; // SAVE
volatile int milesrevs = 0; // SAVE

volatile int kph = 0;
volatile int mph = 0;
volatile unsigned long start = 0;
volatile unsigned long stop = 0;
volatile float secs = 0;
volatile float speed = 0;
volatile float temp = 0;

volatile int buttonState = 0;
volatile int lastButtonState = 0;
volatile boolean riding = false;

File myFile;

LiquidCrystal_I2C lcd(0x27, 16, 2);

void calculate(){
    riding = true;

    // KPH SPEED CALCULATOR
    stop = millis() - start;
    start = millis();
    temp = (float)stop;
    secs = temp / 1000;
    speed = 1.854 / secs;
    speed = speed * 3.6;
    kph = speed;

    // MPH SPEED CONVERTOR
    float x = kph * 0.6214;
    mph = x;

    // KM DISTANCE CALCULATOR
    kmrevs++;
    if (kmrevs == 540){
        km++;
        kmrevs = 0;
        kmTemp = kmTemp + 0.00116;
    }
    if (kmTemp >= 1.0){
        km++;
        kmTemp = kmTemp - 1.0;
    }

    // MILES DISTANCE CALCULATOR
    milesrevs++;
    if (milesrevs == 868){
        miles++;
        milesrevs = 0;
        milesTemp = milesTemp +0.072;
    }
    if (milesTemp >= 1.0){
        miles++;
        milesTemp = milesTemp - 1.0;
    }

    // PRINT DATA TO LCD & SERIAL
    buttonState = digitalRead(ButtonPin);
    if (buttonState == HIGH){
        lastButtonState = buttonState;
        Serial.print(kph);
        Serial.print("kph  ");

        Serial.print(km);
        Serial.print("km  (");
        Serial.print(kmTemp, 6);
        Serial.println(")  ");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(kph);
        lcd.print("kph");
        lcd.setCursor(0,1);
        lcd.print(km);
        lcd.print("km");
    }
    if (buttonState == LOW){
       lastButtonState = buttonState;
        Serial.print(mph);
        Serial.print("mph  ");

        Serial.print(miles);
        Serial.print("miles  (");
        Serial.print(milesTemp, 6);
        Serial.println(")");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(mph);
        lcd.print("mph");
        lcd.setCursor(0,1);
        lcd.print(miles);
        lcd.print("miles");
    }

    // SAVE DATA TO SD CARD
    SD.remove("test.txt");
myFile = SD.open("test.txt", FILE_WRITE);
    if (myFile) {
        myFile.print(km);
        myFile.print(" ");//
        myFile.print(kmTemp, 6);
        myFile.print(" ");//
        myFile.print(kmrevs);
        myFile.print(" ");//
        myFile.print(miles);
        myFile.print(" ");//
        myFile.print(milesTemp, 6);
        myFile.print(" ");//
        myFile.print(milesrevs);
        myFile.close();
    }
    else {
        // SD SAVE ERROR
        Serial.println("Save Error");
    }
}

void setup(){
    pinMode(ButtonPin, INPUT_PULLUP);
    pinMode(InterruptPin, INPUT);

    // POWER LCD SCREEN
    //lcd.begin(16,2);
    lcd.init();
    lcd.backlight();

    // LAUNCH SERIAL CONNECTION
    Serial.begin(9600);

    // LOAD DATA FROM SD CARD
    SD.begin(7);
    myFile = SD.open("test.txt", FILE_READ);
    if (myFile) {
       while (myFile.available()) {

       km = myFile.parseInt();
       kmTemp = myFile.parseFloat();
       kmrevs = myFile.parseInt();
       miles = myFile.parseInt();
       milesTemp=myFile.parseFloat();
       milesrevs = myFile.parseInt();

       }
    myFile.close();
    }
    else {
        Serial.println("Read Error");
    }

    // ATTACH INTERRUPTS
     attachInterrupt(digitalPinToInterrupt(2), calculate, RISING);

    // LOAD START SERIAL & LCD SPEED
    buttonState = digitalRead(ButtonPin);
    if (buttonState == LOW){
        // MPH DISPLAYED
        lastButtonState = buttonState;
        Serial.print("0mph  ");

        Serial.print(miles);
        Serial.print("miles  (");
        Serial.print(milesTemp, 6);
        Serial.println(")");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(mph);
        lcd.print("mph");
        lcd.setCursor(0,1);
        lcd.print(miles);
        lcd.print("miles");
    }
    if (buttonState == HIGH){
        // KPH DISPLAYED
        lastButtonState = buttonState;
        Serial.print("0kph  ");

        Serial.print(km);
        Serial.print("km  (");
        Serial.print(kmTemp, 6);
        Serial.println(")  ");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(kph);
        lcd.print("kph");
        lcd.setCursor(0,1);
        lcd.print(km);
        lcd.print("km");
    }
}

void loop(){
    buttonState = digitalRead(ButtonPin);

    // ZERO SPEED ON SLOW ROTATION
    if (riding == true){
    long period = millis() - start;
    if (period == 4150){
    if (buttonState == LOW){
        // MPH DISPLAYED
        lastButtonState = buttonState;
        Serial.print("0mph  ");

        Serial.print(miles);
        Serial.print("miles  (");
        Serial.print(milesTemp, 6);
        Serial.println(")");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(mph);
        lcd.print("mph");
        lcd.setCursor(0,1);
        lcd.print(miles);
        lcd.print("miles");
    }
    if (buttonState == HIGH){
        // KPH DISPLAYED
        lastButtonState = buttonState;
        Serial.print("0kph  ");

        Serial.print(km);
        Serial.print("km  (");
        Serial.print(kmTemp, 6);
        Serial.println(")  ");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(kph);
        lcd.print("kph");
        lcd.setCursor(0,1);
        lcd.print(km);
        lcd.print("km");
    }
    }
    }

    // CHANGE READING WHEN PRESSED
    if (buttonState != lastButtonState){
        long period = millis() - start;
        if (buttonState == HIGH && period < 4150){
        // KPH DISPLAYED
        lastButtonState = buttonState;
        Serial.print(kph);
        Serial.print("kph  ");

        Serial.print(km);
        Serial.print("km  (");
        Serial.print(kmTemp, 6);
        Serial.println(")  ");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(kph);
        lcd.print("kph");
        lcd.setCursor(0,1);
        lcd.print(km);
        lcd.print("km");
        }
        if (buttonState == HIGH && period > 4150){
        // KPH DISPLAYED
        lastButtonState = buttonState;
        Serial.print("0kph  ");

        Serial.print(km);
        Serial.print("km  (");
        Serial.print(kmTemp, 6);
        Serial.println(")  ");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(kph);
        lcd.print("kph");
        lcd.setCursor(0,1);
        lcd.print(km);
        lcd.print("km");
    }
    if (buttonState == LOW && period < 4150){
        // MPH DISPLAYED
        lastButtonState = buttonState;
        Serial.print(mph);
        Serial.print("mph  ");

        Serial.print(miles);
        Serial.print("miles  (");
        Serial.print(milesTemp, 6);
        Serial.println(")");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(mph);
        lcd.print("mph");
        lcd.setCursor(0,1);
        lcd.print(miles);
        lcd.print("miles");
    }
    if (buttonState == LOW && period > 4150){
        // MPH DISPLAYED
        lastButtonState = buttonState;
        Serial.print("0mph  ");

        Serial.print(miles);
        Serial.print("miles  (");
        Serial.print(milesTemp, 6);
        Serial.println(")");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(mph);
        lcd.print("mph");
        lcd.setCursor(0,1);
        lcd.print(miles);
        lcd.print("miles");
    }
    }
}

Its usually a bad idea to do so much in an ISR (interrupt service routine)   Those other functions you call from in there may need interrupts to be enabled to operate properly.   You should do as little as possible in there (maybe just update the tick count) then do all your other processing in another function called from the main loop.

using your current configuration, you may miss some ticks, even if it was working, as updating the LCD,printing all that information, and saving it to an SD card probably takes longer then the time in between ticks.  It would be much better to write to the SD card is larger 'chunks' of data, to eliminate the overhead of opening and closing the file everytime.

You are using millis, doing serial prints and SPI transfers inside an ISR, all of which are red flags. I'd re-program it to just switch a boolean variable and push the needed data into globalal variables; then process the values and save them in loop. See https://arduino.stackexchange.com/questions/22212/using-millis-and-micros-inside-an-interrupt-routine/22237#22237 and https://arduino.stackexchange.com/questions/30968/how-do-interrupts-work-on-the-arduino-uno-and-similar-boards/30969#30969

Clearly, it looks as though everyone agrees that the problem probably lies in the lengthy ISR....I do remember reading that once upon a time. I think I may reprogram it along the lines you guys have said. I would have been  removing all the print() statements anyway as its only for testing, but looks like I'd have a problem regardless. Further, you said to save to SD in bigger chunks......do you mean something like whack all the values into one variable and save that, rather than making 6 tasks?

Thanks guys, taking the labour out of the ISR has solved the problem perfectly. Unfortunately, the advice wasn't given as an answer so I'm unable to credit you for it, but appreciate the solutions given. Thanks.

Looks like I can't accept my answer either!  .....can someone throw a few words in an answer do that I can accept. Cheers.

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


text:
Problem with Micro SD card breakout
I was connecting my arduino uno to a adafruif micro SD card breakout and everything worked just fine, i could read the sd, write to it and see all the info about it. To do it i just followed the tutorial in here.
My problem is that when I arrived home the exact some thing wouldn't work and I couldn't read the SD card anymore.
I was thinking it could be a bad contact problem since sometimes i get:
Initializing SD card...initialization failed. Things to check:
* is a card inserted?
* is your wiring correct?
* did you change the chipSelect pin to match your shield or module?

And other times (almost never), i would just get:
Initializing SD card...Wiring is correct and a card is present.
Card type: SD2
Could not find FAT16/FAT32 partition.
Make sure you've formatted the card

I would like to know if I can assume it is the breakout board failling and I would buy a new one, or if it can be any other thing.
Thank you in advance!

Did you try:

Reading the SD card in your computer ... if  you can read (or write) files, that means the SD card is intact
Use a SD card that worked before or similar. Some bigger SD cards (like SDHC, SDXC have less good compatibility). Preferably use a 2 GB or smaller card (unless you have used bigger cards successfully and of the same or smaller type, e.g. SD, SDHC, SDXC).
Try different formattings, like FAT, FAT16, FAT32. I think FAT is the mostly recognized formatting.
Check connections/wires to/from SD breakout, maybe during your leave accidentally you (or someone else) or due to pressure/tension, a contact/wire got loose.
Check another SD card in the SD breakout where the SD card you know is good. If this also does not work, it must be the breakout (or Arduino).
Replace every piece of hardware (including wires) one by one and recheck if it works (after you are sure the SD card itself is ok).

Thanks for your answer, yes i tried a new sd card that i just bought for this and still nothing, and i also formated both cards to fat32 (they are 8 GB), and both of them work on my laptop. I remade alreadythe wiring a thousand times with new material, thats a thing i didnt think of, how can i check if it is the arduino? I have accessonly to a breadboard, wires and the sd breakout

Was your original SD card that worked also 8 GB and formatted by FAT? I will add some more items in my answer (for you and possibly others).

First time i used and worked it was a 8 GB micro SD HC, it worked before and after i formated it. So i guess now i will try a new SD breakout board.

If you ruled out that all other components are still working, probably yes I'm afraid.


text:
2D cross correlation code for small images
I am working on a arduino Uno project* to detect eye pupil movement and I am thinking of using a serial low-res jpeg camera. I am thinking of implementing a cross-correlation function to detect when the pupil is turned towards the camera.
I am looking, so far unsuccessfully, for a c source code that performs a 2D cross-correlation without using FFT (Fourier Transform). I think such code might have good enough performance even on an Arduino Uno board when running on a low-res image, something like a 32x32 pixels image.
I'd appreciate if you could direct me to such a piece of code or alternatively tell me that this can't be done on an Arduino board due to CPU\RAM limitations.
Current Device is using an IR range finder to detect IR reflected from the retina when looking directly into the device.
P.S.

The project is intended to provide ALS patients the capability to use eye-motion to call for help, using a low-cost device.

32×32 is 1024 pixels. Assuming one byte per pixel, you would need 2 KiB only to store the two images you want to cross-correlate. And that's the total amount of RAM of an Arduino Uno, so you would have no RAM left for doing anything!

A Raspberry Pi is probably better suited to this task, IMHO.


text:
Get Speed Using GPS Neo with TinyGPS++
I am trying to get the current speed of my car using the GPS Neo, but my code always returns that the speed from the GPS is invalid. The green led of the GPS Neo is blinking. What is the isValid() function? Below the code:
#include <EEPROM.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
//LOAD WIRE LIB
#include<Wire.h>
static const int RXPin = 10, TXPin = 9;
static const uint32_t GPSBaud = 9600;
// The TinyGPS++ object
TinyGPSPlus gps;
// The serial connection to the GPS device
SoftwareSerial ss(RXPin, TXPin);
//***************************************************************
int aux = 0;
int vel_prog = 20; //programed SPEED
float vel_atual;//  actual SPEED
int val_inc = 0;
int val_dec = 0;
int led0 = 2;//led pin
int led20 = 3;//led pin
int led60 = 4;//led pin
int led80 = 5;//led pin
int ledsinal = 6;//led pin
int buzzer = 7;//buzzer pin
int incrementa = 8;//button pin
//****************************************************************
void setup()
{
  Serial.begin(115200);
  ss.begin(GPSBaud);
  pinMode(incrementa, INPUT);
  pinMode(led0, OUTPUT);  // declare LED as output
  pinMode(led20, OUTPUT);  // declare LED as output
  pinMode(led60, OUTPUT);  // declare LED as output
  pinMode(led80, OUTPUT);  // declare LED as output
  pinMode(ledsinal, OUTPUT);  // declare LED as output
  pinMode(buzzer, OUTPUT);  // dbuzeer
  delay(10);
}

void loop()
{

  smartDelay(1000);
  val_inc = digitalRead(incrementa);  // read increment button
  if (val_inc == 1) {
   if (vel_prog > 80) {
      vel_prog = -20;
   }
      vel_prog = vel_prog + 20;
  }

  if (vel_prog == 0) {
    digitalWrite(led0,HIGH);
    digitalWrite(led20,LOW);
    digitalWrite(led60,LOW);
    digitalWrite(led80,LOW);
  } else if (vel_prog == 20) {
    digitalWrite(led0,LOW);
    digitalWrite(led20,HIGH);
    digitalWrite(led60,LOW);
    digitalWrite(led80,LOW);
  } else if (vel_prog == 60) {
    digitalWrite(led0,LOW);
    digitalWrite(led20,LOW);
    digitalWrite(led60,HIGH);
    digitalWrite(led80,LOW);
  } else if (vel_prog == 80) {
    digitalWrite(led0,LOW);
    digitalWrite(led20,LOW);
    digitalWrite(led60,LOW);
    digitalWrite(led80,HIGH);
  }

  if (gps.speed.isValid()){
  Serial.print(gps.speed.kmph());
  } else {
  Serial.print("*");
  }

 if (gps.speed.isValid()) {
  if (gps.speed.kmph() >= vel_prog && aux == 0) { //comparacao da velocidades
    digitalWrite(ledsinal, HIGH);  // turn LED OFF
    tone(buzzer, 2200);
    delay(5000);
    digitalWrite(ledsinal, LOW);  // turn LED OFF
    noTone(buzzer);
    aux = 1;
  }
}
}

static void smartDelay(unsigned long ms)
{
  unsigned long start = millis();
  do
  {
    while (ss.available())
      gps.encode(ss.read());
  } while (millis() - start < ms);
}

What specific device are you using?

Arduino Nano AtMega 168, and a GY-GPSV3- NEO M8N GPS

No, I mean which GPS device!

Sorry, I edited the post

Looks like it should support Velocity reporting. Maybe you don't have a good enough fix, or maybe it needs turning on in the config. Step 1 is to examine exactly what NMEA messages it's sending while running. Use the ubiquitous serial pass-through sketch to read the raw NMEA data.

Using the standar example from Arduino, it shows only "*"

These lines of code will wreak havoc with reading the GPS data:
tone(buzzer, 2200);
delay(5000);
digitalWrite(ledsinal, LOW);  // turn LED OFF
noTone(buzzer);

The Arduino is "blocked" at these lines for seconds.  During that time, the GPS keeps babbling and eventually overflows the input buffer.  The next call to smartDelay only waits for 1 second, and it may not get a complete sentence.
Here is a NeoGPS version of your sketch that does not block:
#include <EEPROM.h>
#include <NMEAGPS.h>
#include <NeoSWSerial.h>
#include <Wire.h>

NMEAGPS gps;

static const int RXPin = 10, TXPin = 9;
static const uint32_t GPSBaud = 9600;
NeoSWSerial gpsPort(RXPin, TXPin);

//***************************************************************
int aux = 0;
int vel_prog = 20; //programed SPEED
float vel_atual;//  actual SPEED
int val_inc = 0;
int val_dec = 0;
int led0 = 2;//led pin
int led20 = 3;//led pin
int led60 = 4;//led pin
int led80 = 5;//led pin
int ledsinal = 6;//led pin
int buzzer = 7;//buzzer pin
bool buzzing = false;
uint32_t buzzTime;
int incrementa = 8;//button pin
//****************************************************************
void setup()
{
  Serial.begin(115200);
  gpsPort.begin(GPSBaud);
  pinMode(incrementa, INPUT);
  pinMode(led0, OUTPUT);  // declare LED as output
  pinMode(led20, OUTPUT);  // declare LED as output
  pinMode(led60, OUTPUT);  // declare LED as output
  pinMode(led80, OUTPUT);  // declare LED as output
  pinMode(ledsinal, OUTPUT);  // declare LED as output
  pinMode(buzzer, OUTPUT);  // dbuzeer
  delay(10);
}

void loop()
{
  // Check the buttons
  val_inc = digitalRead(incrementa);  // read increment button
  if (val_inc == 1) {
   if (vel_prog > 80) {
      vel_prog = -20;
   }
      vel_prog = vel_prog + 20;
  }

  if (vel_prog == 0) {
    digitalWrite(led0,HIGH);
    digitalWrite(led20,LOW);
    digitalWrite(led60,LOW);
    digitalWrite(led80,LOW);
  } else if (vel_prog == 20) {
    digitalWrite(led0,LOW);
    digitalWrite(led20,HIGH);
    digitalWrite(led60,LOW);
    digitalWrite(led80,LOW);
  } else if (vel_prog == 60) {
    digitalWrite(led0,LOW);
    digitalWrite(led20,LOW);
    digitalWrite(led60,HIGH);
    digitalWrite(led80,LOW);
  } else if (vel_prog == 80) {
    digitalWrite(led0,LOW);
    digitalWrite(led20,LOW);
    digitalWrite(led60,LOW);
    digitalWrite(led80,HIGH);
  }

  // Check the GPS
  while (gps.available( gpsPort )) {
    gps_fix fix = gps.read();

    if (fix.valid.speed) {

      if ((fix.speed_kph() >= vel_prog) && (aux == 0)) { //comparacao da velocidades
        digitalWrite(ledsinal, HIGH);  // turn LED OFF
        tone(buzzer, 2200);
        aux = 1;
        buzzing = true;
        buzzTime = millis();
      }

      Serial.print( fix.speed_kph() );
    } else {
      Serial.print( '*' );
    }
  }

  // Check the buzzer
  if (buzzing && (millis() - buzzTime > 5000)) {
    digitalWrite(ledsinal, LOW);  // turn LED OFF
    noTone(buzzer);
    aux = 0; // Need this?
    buzzing = false;
  }
}

Notice how it checks millis() every time through loop to see if the buzzer has been on for 5 seconds.  It doesn't block for 5 seconds.
It only checks the speed when a new GPS fix arrives.  This happens once per second, not every time through loop.
Your original version uses 11472 bytes of program space and 786 bytes of RAM.
The NeoGPS version uses 10722 bytes of program space and 590 bytes of RAM, a significant savings.
NeoGPS is smaller, faster and more accurate than all other libraries.  If you want to try it, NeoGPS is available from the Arduino IDE Library Manager, under the menu Sketch -> Include Library -> Manage Libraries.
The above sketch also uses my NeoSWSerial.  It is much more efficient than SoftwareSerial.  SoftwareSerial blocks interrupts for long periods of time, which can interfere with other parts of your sketch.
It would be even better to use AltSoftSerial on pins 8 & 9 (on an UNO).

Thanks, now it's working, but another doubt, If I put the antenna pointing to the sky towards the front glass of the car, can the glass disturb the signal? Or should I put the antenna out of the car?

It should be fine inside the car.  Unless you have a metallic mirror coating...


text:
ST7735 display with esp32
I have edited the adafruit ST7735 library so that it supports esp-32.I made some edits in Adafruit_ST7735.h file. which are as follows.

The code works fine but I had expected the screen to work faster with esp-32(due to higher processing power) but it does not do that.
I checked the time for fill screen operation for esp-32 and arduin mega. They come out to be almost the same. (around 0.12 seconds). Can anyone explain why this is happening and can I increase the speed?

Because you're using bitbanged SPI...?

Is copy pasting code really that hard?

The ST7735 uses SPI to communicate. It will always be slow compared to parallel connected screens.
The fact that you appear to be using bitbanged SPI (manually toggling IO pins) makes it even slower.
The fastest you will be able to get with that screen will be to use hardware SPI instead (which most likely limits which pins you can use - I am not familiar with the ESP32 though) but that will still be somewhat slow.
If you want really high speed screen updates then you will need a parallel interface screen, ideally a 16-bit parallel interface screen. However, for that you need around 20 IO pins to drive it.

Even with bitbanged SPI, the ESP32 should be do better than the Mega regarding screen refresh rates, that is assuming OP's ESP32 has a much higher clock frequency than 16 MHz, as befits it.

@TisteAndii And assuming there aren't specific length delays used in the bit banging, which would remain the same regardless of clock speed.

I checked. There are no delays. https://github.com/adafruit/Adafruit-ST7735-Library/blob/master/Adafruit_ST7735.cpp#L90

The mega uses hardware SPI which will be faster than bit banging. Bit bang on a fast CPU and you get similar speed to hardware SPI on a mega.

If the OP is in fact comparing ESP32 bit-banging with Mega hardware SPI (default speed DIV4 = 4 MHz), then you'd be right. It seems the fastest toggle speed possible on the ESP32 is 10 MHz, and that's when writing to the CPU registers directly to get fairly optimized assembly. https://www.esp32.com/viewtopic.php?t=1595


text:
Why is this looping?
I am trying to do something very simple.  I want the LED to fade from full brightness to off.  This works... However, the LED turns back on to full brightness and fades again, in a loop.  I am not sure why.  I think I am missing something obvious.  Once the legThreeBrightness decrements to 0, nothing should happen...
int legThreeBrightness = 255;

void setup() {

    pinMode(3, OUTPUT);

}

void loop() {

    if (legThreeBrightness = 255){
        do {
              analogWrite(3, legThreeBrightness);
              delay(30);
              legThreeBrightness = legThreeBrightness -5;
           } while (legThreeBrightness >= 0);
    }
}

legThreeBrightness = 255 doesn't do what you think it does. Turn up your compiler warnings and pay attention to what it says.

This line:
if (legThreeBrightness = 255){

assigns the value 255 to legThreeBrightness.  That is non-zero so it enters the block and runs the fade now that the variable has been set to 255.
If you just want to compare the value to 255 then use:
if (legThreeBrightness == 255){

and that way when the loop function repeats it isn't there setting the value back to 255.  This way it will stay at 0.

sigh...  that was it.  I completely forgot that its a double == for comparison.

@Keltari Rookie mistake, we've all made it. Make sure you keep an eye on your operators whenever you're debugging :-)

https://en.m.wikipedia.org/wiki/Yoda_conditions

There are also some compilers that will warn you about this. If you count up the time you spent debugging this, it might be a better use to figure out if/how your compiler can.

@Keltari if you'd like, you can follow @JonathanZsupportsMonicaC's suggestion to enable compiler warnings. Go to File -> Preferences -> Compiler warnings: and set it to More. If you'd like the compilation to fail instead of just issuing a warning, add #pragma GCC diagnostic error "-Wparentheses" to the top of your program.

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


text:
changed behaviour in I2C LCD
I reinstalled a previously working sketch to my UNO and now the behaviour of the lcd has changed.
Previously this example worked perfectly:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

void setup()
{
  lcd.init();                      // initialize the lcd

  // Print a message to the LCD.
  lcd.backlight();
  lcd.print("Hello, world!");
}

void loop()
{
}

Now it only displays the very first character 'H'
This version does work though:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display

void setup()
{
  lcd.init();                      // initialize the lcd

  // Print a message to the LCD.
  lcd.backlight();
  lcd.print("H");
  lcd.print("e");
  lcd.print("l");
  lcd.print("l");
  lcd.print("o");
  lcd.print(" ");
  lcd.print("W");
  lcd.print("o");
  lcd.print("r");
  lcd.print("l");
  lcd.print("d");
}

void loop()
{
}

Can anyone shed me any light what is the reason of this change in behaviour and how to solve it?
Running version 1.8.3 on a W7pro PC

Where does it print the letter H, at position 0, 0? If not, try lcd.home(); right after lcd.backlight();.

ok thanks, I tried that but the result is exactly the same

I've tried both of your sketches and they work fine. What happens if you remove the "!" character from your first sketch?

Removing the '!' gives the same problem, I also tried removing the ',' without any improvement..

Have you updated your IDE to a newer version or the LiquidCrystal_I2C library recently?

Yes the IDE was updated pretty recently (v1.8.3), the library is the same as before (LiquidCrystal_I2C1602V1).

ok got it, see my answer, thanks for the suggestions

There seems to be an incompatibility between recent versions of the IDE and the library I was using.
Installing the latest version of the library from GitHub and replacing the lcd.init() command with lcd.begin() in my sketches solved the problem.

sorry, can't accept yet, I have to wait till tomorrow


text:
Powering the attiny85 with a separate power source
I have an LED project for which i'm using a 9v power supply. For part of the project I'm using an off the shelf LED driver that is compatible with 9v however I have one LED component that I want to drive with the attiny85 (random blinking pattern), which is not compatible with 9v.
Does it make any sense to power the attiny85 separately with say a 3v coin cell, while allowing my LEDs to draw from 9v? The attiny85 would only be tripping transistors. I assume the attiny85 itself doesn't consume much power so hopefully I wouldn't be changing out the coin cell too often.
I have a couple 5v buck converters on hand but they take up more space than a coin cell would.
P.S. It's a Guy Manuel Daft Punk Helmet.

They make voltage regulators that are even smaller than coin cells.

@IgnacioVazquez-Abrams I assume you aren't talking about the lm317 which I've already ruled out. I'll shop around and see what's out there. Thanks

Nah, I'd look at the LM78L05/33 or LP2985.

Does it make any sense...

Well, actually it does make sense and you already rationalize it in your question: less space consumed, expected life time of the coin cell is ok for your intended use case (though you could/should confirm the assumption about power consumption with the AVR's data sheet).
There is nothing wrong in powering the microcontroller with a different voltage than the "power" circuitry, assuming the ground lines are connected and the transistors mentioned are operated in a suitable mode, e.g. open collector/open drain type.


text:
Rechargeable USB "AA" Batteries. Has anyone used them?
I have a cosplay project where I'm creating a "Megaman" aka Rockman type of arm cannon (it's actually based on DC's Cyborg). Anyhoo, I've been weighing options like using 3xAA alks or 4xAA nicd (or otherwise 1.2V)--inclcuding various combinations of less or more cells with a voltage regulator; boost up or step down as appropriate.
there are 4 lighted segments (15 leds of WS2812B x 4). I also of course have to power the Arduino Nano as well. I'm flexible on led brightness so I'm just going to tune it [code it] to whatever looks adequate for my purpose. I am aware of the 50ma draw of these units at full brightness
My original plan was to just keep it easy (read lazy) and use 3 AA alks per 2 segments, and another 3 so the nano can have it's own supply. So 9 cells in total (without any additional regulation). Before you judge me--weight, volume, and especially area are definitely big factors in my decision.
So that's a long way to get to my actual question. Has anyone used these new types of USB rechargeable batteries? They seem to have the best of both worlds with the power of an alkaline but the consistency and sustainability of a NiMH /NiCD as they have internal regulators that produce a steady 1.5v (until they don't--which I'm more than cool with)
Short of having a properly regulated 5v power supply, are these a good option if I want to be slightly more responsible than throwing in whatever other AAs I have lying around? They definitely check the box on my space/mass requirements. I'm sure they do fine with most consumer electronics, but as far as arduino and any other custom/hobby 4.5-5v applications how reliable are these? Even if you haven't used them before I'd be curious of your thoughts. I'm a novice at best when it comes to elec engineering.
Yes, they are expensive. Thanks all!
examples:
https://www.amazon.com/Rechargeable-Batteries-Quick-Charge-Integrated-Protection/dp/B07F27PK2M/ref=sr_1_5?crid=1RTQUCZYG4KBM&dchild=1&keywords=usb+aa+batteries+1.5v&qid=1588280164&sprefix=usb+aa%2Caps%2C242&sr=8-5
https://www.amazon.com/Blackube-Rechargeable-Batteries-Lithium-1500mAh/dp/B07D9K2H9H/ref=sr_1_11?dchild=1&keywords=usb+aa+batteries+1.5v&qid=1588282813&sr=8-11

1500mAh is considerably less than what you'd get from a normal NiMH. And for the price of them you could get a pack of normal NiMH and a proper charger.

I think you can get a good LiIon or LiPo battery and a fitting charger/voltage regulator module for less than that. And it could output directly 5V, so you wouldn't loose more power with an extra voltage regulator. Or are you somehow bind to using AA sized batteries?

@chrisl I'm not necessarily stuck on AA, but I'm mounting them on the outer circumference of a 3" PVC pipe, aligned with the direction of the pipe openings. Imagine a small ammo bandolier around your forearm with nine 20ga shells surrounding...That's kind of what I'm thinking. So larger flatter batteries are going to have a weird footprint for my purpose. Mounting 9 or so individual AA battery holders seemed like a good way to make this look clean. The section of pipe is also on a spinning bearing, so the batteries have to be distributed somewhat evenly. A single large battery won't work.

If you want to fit it into PVC pipe, why not consider 18650 Li-ion rechargeable, it gives you anywhere from 2000 to 3500mAh with a single compact battery with 3.7v output. You could either add a boost converter or use 2 batteries feed into Vin of Nano.

@hcheung I like this. I'm actually thinking I would do two in a series and pop in a 5v reg since I'll be saving space with 2 cells instead of 3 or 4. Also an expensive option but other than that it's a good fit.

I use for this purpose the eneloop (2800 mAh) Keep up the mAh for 85-90% of the full load. Advantage same circuit as for batteries, quickly exchangeable, can be loaded with a normal loader and reliable with changing temperatures (used them from -5C to +40C). Disad: cost a bit more than a normal NiMh (four for around 10$)

Those "batteries" are actually a 3.7V¹ ~750mAh Lithium rechargeable cell with a 1.5V switching regulator and 5V charge circuit built in.
In about the same space as one of those, if you throw away the charge circuit and switching regulator, you can get a single 18650 Lithium rechargeable cell at 3.7V¹ (nominal) and three times the capacity. Two of those plus a small 5V switching regulator² would give you more power capacity and longer run time in a smaller space than the equivalent voltage of these strange "batteries".

¹ Nominal
² Use a good one with a Li-Ion battery protection circuit and maybe a built in 2S charger too for convenience

Thanks for the context on the USB AA cells! Taking your advice on the 18650's.


text:
Sine wave using arduino uno
I am an adruino hobbyist, i want to make sine wave using arduino uno,
for that i using timer0 as interrupt, OCR0A set to 17 for 3.6khz interrupt(16000000/(100hz*36 interval)/256-1),
If i am using only one pwm pin i am getting correct frequency but when i enable two pwm pin i am getting only half if the frequency, kindly advise what is wrong and how to correct it.
.................................
This code i am getting correct frequency at PWM pin 9.
//
ISR(TIMER0_COMPA_vect)
{
OCR1A=(256+((((sin(num*3.14/180))*256))))/2;
//OCR1B=(256+((((sin(num*3.14/180))*256))))/2;
     num=num+10;
    if(num >= 360)
{
       num = 0;
    }
}

//
............................
This code i am getting only half of the previous frequency at PWM pin 9,10
//
ISR(TIMER0_COMPA_vect)
{
OCR1A=(256+((((sin(num*3.14/180))*256))))/2;
OCR1B=(256+((((sin(num*3.14/180))*256))))/2;
     num=num+10;
    if(num >= 360)
{
       num = 0;
    }
}

//

How did you configure your timer ? 2. The sin() function takes something like 100 µs per call.

You could use OCR1B=OCR1A since both are the same. But, assuming the problem is as StarCat said due to the ISR taking to long, I'd look into creating a table of SIN values.

A better method would be to generate a simple square wave then filter it into a sine wave. No need to mess with complex calculations or even lookup tables.

You are doing complex calculations inside an Interrupt Service Routine. This is not a good idea. Computing sines takes a large amount of time as this consists of multiple, complex floating point operations. Interrupt Service Routines should be short and as simple as possible.
This is probably the reason you can't have two PWM signals active at the same time at the same frequency. The ISRs simply take too long.
The solution would be to pre-calculate the desired waveforms or greatly simplify the waveform calculations (preferably without floating point). If you decide to pre-calculate, take care to stay within the limited amount of memory you have available on your Arduino. You can minimize the memory used by calculating and storing just 1/4 of a complete waveform and constructing the remaining 3/4 from these values.
This leaves the conversion of your PWM output to a real sine wave. How are you planning to do that?

If the table get too bit (uses too much RAM) you can look into using PROGMEM to keep the table in flash memory.

the lookup table needs to store only a 1/4 of the sine wave


text:
Calculating fluid volume using arduino sensors
I would like to measure liquid sealant volume inside bike tires, using sensor located between rim beads.
I guess it would by possible, by using ToF sensor, that would measure distance between rim and fluid surface.

Yellow - fluid itself
Than I would like to calculate fluid volume by using a formula for torus ?cap?
In another words: drained fluid would look like this cut section (not to scale):

Is there any mathematical formula to calculate volume of such "cap", based on its height and two torus radiuses? I only found formula for "ball cap" volume...
Or maybe there is better approach to measure volume, and I am doing it wrong?

There certainly is a formula to calculate that torus cap volume, though this is Arduino SE and not Mathematical SE, thus off topic. How do you plan to get any kind of sensor inside the inner tube of the tire? You normally cannot cut them open and seal them again to still hold the typical 3 bar pressure

you could use a weigh scale to determine the mount of fluid inside the inner tube

Your question seems like about geometry. You should try another channel, not Arduino maybe.

How are you at integrals?

@chrisl - there are new bikes with tubeless tires and many users are converting to tubelesss. That's the only possibility for this type of measurement. I'm going to try another channel.

Ah, ok. Then it may be easier to make a capacitive sensor. Found this thread with a quick google  but there are certainly better resources, when you search for them

Thanks I would consider it.

This article doesn't have the answer, but it may be of some help in formulating an approach.

It may be helpful for someone: I haven't found any formula for torus cap yet. Only for ellipsoid cap, there: https://www.vcalc.com/equation/?uuid=7cbe5611-1e51-11e8-abb7-bc764e2038f2

If you need a ''small cap" compared to the rest of figure you can treat this cap as ellipsoid cap. Just tweak ellipsoid values, so that the curves matches circle of torus cross section in area I'm interested in.


text:
Using Arduino LMIC library with EnableInterrupt
I am using the EnableInterrupt library, infact the only library that I can find that allows me to use six interrupts to wake the Arduino. However when I use it with the LMIC library (Matthijs Kooijman ) the "Forward uplink data message" is not sent during initial registration, only if
#include <EnableInterrupt.h> is commented out does it work. I am using a RFM95 with the following LMIC pin assignments:
const lmic_pinmap lmic_pins = {
.nss = 10,
.rxtx = LMIC_UNUSED_PIN,
.rst = 9,
.dio = {3, 8, LMIC_UNUSED_PIN},
};
This must be something to do with the library sharing ISRs.  Could somebody point to which parts of the LMIC library so as not to have this conflict?
I have tried swapping 8 for A5 and it again only works when the line is commented. Any help would be greatly appreciated.

I have managed to get it to work by specifying
#define EI_NOTPORTD however it does not work with  #define EI_ARDUINO_INTERRUPTED_PIN which is needed for my project to function.

This is the best I can get to work with 6 available pin change interrupts - just enough!
#define EI_ARDUINO_INTERRUPTED_PIN
#define EI_NOTPORTB  // DISABLE FOR LMIC
#define EI_NOTPORTD  // DISABLE FOR LMIC


text:
Utilizing Array with RGB
I am trying to create a sketch that utilizes two arrays, one array to hold five buttons as input, assigned to pins, and another array to hold five musical notes.  I have attached a RGB LEDs with pull-down resistors and attached a 8 ohms resistor speaker.
The code is as followed:
 //Pentatonic Piano
 // C D E G A

 #define NOTE_C   262 //HZ
 #define NOTE_D   294 //HZ
 #define NOTE_E   330 //HZ
 #define NOTE_G   392 //HZ
 #define NOTE_A   440 //HZ

 const int SPEAKER = 9;   //speaker on pin 10
 const int BLED = 10;      //Blue LED on pin 9
 const int GLED = 6;      //Green LED on pin 6
 const int RLED = 5;      //Red LED on pin 3

 int buttonState = 0;

 //Button Array
 int Buttons[]= {11, 8, 7, 4, 3};

 //Tone Note Array
 int Notes[] = {NOTE_C, NOTE_D, NOTE_E, NOTE_G, NOTE_A};

 void setup()
 {
 pinMode(BLED, OUTPUT);
 pinMode(GLED, OUTPUT);
 pinMode(RLED, OUTPUT);
 pinMode(Buttons, INPUT);
 }

 void loop()
 {

   buttonState = digitalRead(Buttons);

   if (buttonState = Buttons[0])
   { tone(SPEAKER, Notes[0]);
    digitalWrite(BLED, LOW);
    digitalWrite(GLED, LOW);
    digitalWrite(RLED, HIGH);

   }
   else if (buttonState = Buttons[1])
   {tone(SPEAKER, Notes[1]);
    digitalWrite(BLED, LOW);
    digitalWrite(GLED, HIGH);
    digitalWrite(RLED, LOW);
   }
   else if (buttonState = Buttons[2])
   {tone(SPEAKER, Notes[2]);
    digitalWrite(BLED, HIGH);
    digitalWrite(GLED, LOW);
    digitalWrite(RLED, LOW);

   }
   else if (buttonState = Buttons[3])
   {tone(SPEAKER, Notes[3]);
    analogWrite(BLED, 127);
    analogWrite(GLED, 0);
    analogWrite(RLED, 127);

   }
   else if (buttonState = Buttons[4])
   {tone(SPEAKER, Notes[4]);
    analogWrite(BLED, 0);
    analogWrite(GLED, 127);
    analogWrite(RLED, 127);

   }

   else
   {
    digitalWrite(BLED, LOW);
    digitalWrite(GLED, LOW);
    digitalWrite(RLED, LOW);
    noTone(SPEAKER);
   }
 }

The problem is no matter what button I press, the RGB only emits a green light and there is absolutely no sound coming from the speaker.  I am truly stumped.

First, these statements:
if (buttonState = Buttons[0])

are doing an assignment, not a test for equality. You want:
if (buttonState == Buttons[0])
//               ^Notice

Next, pinMode takes two integers, but you are passing an array. You can use a loop to call pinMode multiple times:
for (int i = 0; i < sizeof(Buttons) / sizeof(Buttons[0]); i++) {
     pinMode(Buttons[i], INPUT);
}

Same goes for digitalRead(). You need to read the state for each button:
buttonState = digitalRead(Buttons[0]);
if (buttonState == HIGH) {
   ....
}
buttonState = digitalRead(Buttons[1]);
if (buttonState == HIGH) {
   ....
}
//etc


text:
256 (8x32) LED Matrix via ESP32-Pico-Kit_V4 possible? (Daft Punk Helmet)
I am currently planning on a Daft Punk Helmet. But the available kits are terribly expensive.
I am looking forward to using a 8x32 LED-Matrix(with 256 separate 5mm LEDs) and having a few different display modes which include static text and also repeating animations like a wave going back and forth, or digital eyes that wink. Also a Bluetooth connection would be nice and of course portability is important.
That's why I was looking at the ESP32-Pico-Kit_V4.
My question now: Is it possible to run such a big LED-Matrix off this ESP or would I need some extra boards/controllers and if so which would be necessary.
Or is this as a whole a much bigger project than I am expecting?
PS: I don't wanna use one of the prewired 8x32 panels because they are not see-through.
-- Arduino rookie needing some help

it is just a 256 LED light string folded 7 times ... research driving RGB LED strip with ESP32-Pico-Kit_V4

I'll need 4 display drivers like the MAX7219 CNG chips.
Thanks anyway.

i was under the impression that you wanted color .... good luck with your project


text:
ESP-NOW and WIFI and OTA at the same time on Sender and Receiver
I am trying to set up two ESP32s so that they can be updated via OTA and at the same time send sensor readings using ESP-NOW, from Sender Board to Receiver Board.
For this to work both boards must connect to wifi and simultaneously send messages over ESP-NOW.
I don't mind using a mode where a button is pressed and Wifi is only then enabled but switching wifi on and off seems to have intermittent success.
I have tried setting the channels to the same on both boards but this does not work.
In the example below I have stripped all the OTA code out and the code needed for ESP-NOW and just the line for WIFI enable

WiFi.begin(ssid, password);

which when enabled causes the delivery to fail.
Here is my Sender Code:
        #include <esp_now.h>
        #include <WiFi.h>
        #include <Wire.h>
        #define ssid "MYNETWORKSSID"
        #define password "mynetworkpassword"

         const int sNine = 33;

         #define CHAN_AP 2

        uint8_t broadcastAddress[] = {0x24, 0x62, 0xAB, 0xDC, 0x70, 0x90};
        int hall;

        String success;

        typedef struct struct_message {
            int hall;
        } struct_message;
        struct_message hallReadings;

        // Callback when data is sent
        void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
          Serial.print("\r\nLast Packet Send Status:\t");
          Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
          if (status ==0){
            success = "Delivery Success :)";
          }
          else{
            success = "Delivery Fail :(";
          }
        }

        void setup() {
          // Init Serial Monitor
          Serial.begin(115200);
          WiFi.mode(WIFI_STA);
         WiFi.begin(ssid, password); // PROBLEMATIC LINE

          // Init ESP-NOW
          if (esp_now_init() != ESP_OK) {
            Serial.println("Error initializing ESP-NOW");
            return;
          }
          // Once ESPNow is successfully Init, we will register for Send CB to
          // get the status of Trasnmitted packet
          esp_now_register_send_cb(OnDataSent);

          // Register peer
          esp_now_peer_info_t peerInfo;
          memcpy(peerInfo.peer_addr, broadcastAddress, 6);
          peerInfo.channel = CHAN_AP;
          peerInfo.encrypt = false;

          // Add peer
          if (esp_now_add_peer(&peerInfo) != ESP_OK){
            Serial.println("Failed to add peer");
            return;
          }
        }

        void loop() {
          // getReadings();

           hallReadings.hall = analogRead(sNine);

          esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &hallReadings, sizeof(hallReadings));

          if (result == ESP_OK) {
            Serial.println("Sent with success");
          }
          else {
            Serial.println("Error sending the data");
          }
          delay(100);
        }

Here is my Receiver code:
#include <esp_now.h>
#include <WiFi.h>
#include <Wire.h>

 const int sNine = 15;

//Wi-Fi channel (must match the gateway wi-fi channel as an access point)
#define CHAN_AP 2

// Define variables to store incoming readings
int incomingHall;

//Structure example to send data
//Must match the receiver structure
typedef struct struct_message {
    int hall;
} struct_message;

// Create a struct_message to hold incoming sensor readings
struct_message incomingReadings;

void updateDisplay(){

  Serial.print(incomingReadings.hall);
}

// Callback when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&incomingReadings, incomingData, sizeof(incomingReadings));
  incomingHall = incomingReadings.hall;
}

void setup() {
  // Init Serial Monitor
  Serial.begin(115200);
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);
  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  // Register for a callback function that will be called when data is received
  esp_now_register_recv_cb(OnDataRecv);
}

void loop() {

  updateDisplay();
  delay(100);
}

what is your specific question?

How can I have OTA enabled on both boards and also use ESP-now? when I activate wifi ESPnow stops working. Thanks!

If you want to switch the softAP connection On/OFF you can do like StefanL38 suggests and have the Receiver transmit a ESP-NOW message with a value to the Sender, but you don't need a reboot. You can drop softAP and come up as STA or vise versa, for example.
    if(incomingid == 3){
      incomingValue = incomingReadings.Value;

      // to allow OTA, using Elegant OTA, haven't tried others.

    if(incomingValue == 1){
      WiFi.softAP(ssid,password,6);
      Serial.print("Connecting to ESP32 SSID ");
      Serial.println(ssid);
      IPAddress IP = WiFi.softAPIP();
      Serial.print("AP IP address: ");
      Serial.println(IP);
      WiFi.printDiag(Serial);
    }

      // to disconnect and allow ESP-NOW via Station mode.

   else if(incomingValue == 0){
      WiFi.softAPdisconnect(true);
      delay(1000);
      WiFi.mode(WIFI_STA);
      delay(1000);
      WiFi.printDiag(Serial); // STA Defaults to channel 1
      esp_wifi_set_promiscuous(true);
      esp_wifi_set_channel(6, WIFI_SECOND_CHAN_NONE); // channel 6 setup
      esp_wifi_set_promiscuous(false);
      WiFi.printDiag(Serial);
    }
  }

Do you know where do you put this code. When I try to put this code anywhere other than Set up the ESP8266 crashes as it uploads the firmware.  Is the EEPROM a way to use it in set up section ?

It would go under the Callback when data is received function of ESP NOW ie… void OnDataRecv

I do something similar on a ESP8266 retrieving time from a NTP-server.
Though it is just a "work around".

I connect to the router retrieving the NTP-time.
storing the time-information into RTC-RAM including a flag that indicates "time received"
then do a software-RESET
the setup-function checks this flag to decide if the ESP8266 shall connect to the router or shall keep WiFi OFF and activate ESP-NOW

if you want to use this for OTA it could "work" like this
sending a special ESP-NOW-Message initiating setting a flag "do_OTA" in RTC-RAM and then re-boot
the setup-function looks for this flag "do_OTA" to be set does what its name says
clearing the "do_OTA"-flag
What I don't know is writing new code into flash is a different thing than just re-booting through a software-reset. So maybe the content of the RTC-RAM gets lost through the update-process.
If so you could write the flag into flash using LittleFS
best regards Stefan

Another method that works if you don't mind having both at the same time:
Instead of WiFi.begin(ssid, password);
I use WiFi.softAp(ssid,password,channel); for both Sender and Receiver.


text:
Implement two processes at the same time
I am a beginner in arduino and due to the lockdown I have been learning it by implementing it on tinkercad. I have made a simulation where I have attached :

Servo Motor

Ultrasonic Sensor

Led Bulb

LCD display

to an arduino uno 3
My AIM :  When something falls under 30cm of the ultrasonic sensor, the servo motor starts from zero position and goes upto 180 degrees in a span of 20seconds and then goes back to its initial position. At the same time and led switches on for 20s and switches off when the motor returns back to its position.
I was able to successfully implement this. But then I added an lcd to show the time i.e time is initialized at 0seconds and then goes to 20 seconds and when the motor resets. Time also resets.
I was able to make a timer on another simulation and I tried to run it in this one by placing the code correctly but I am not able to figure out how?
The present code I have written keeps blinking the led at an interval of one second and the servo moves very very slowly.
Any sort of help will be amazing.
This is my simulation, I have made it public, you may copy and simulate it if you have a tinkercad account. Even without an account you can see how it looks.
Here is the code:
(Please ask if you want me to add comments some areas)
//library code for lcd
#include <LiquidCrystal.h>
//setting up pins
const int rs = 9, en = 8, d4 = 5, d5 = 4, d6 = 3, d7 = 2;

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

unsigned long readTime=20;

//servo motor
#include <Servo.h>
Servo servo_9;
int pos = 0;
//servo motor end

//ultrasonic sensor pin
const int pingPin = 12;

//lcd
signed short seconds;
char timeline[16];

void setup()
{

  servo_9.attach(13); //servo pin
  Serial.begin(9600);

  pinMode(11,OUTPUT);// led

  //lcd initialize
  lcd.begin(16, 2);
  lcd.print("Time : ");

}

void loop()
{

  long duration, cm;
  //Ultrasonic start
  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);

  // The same pin is used to read the signal from the PING))): a HIGH
  // pulse whose duration is the time (in microseconds) from the sending
  // of the ping to the reception of its echo off of an object.
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);

  // convert the time into a distance
  cm = microsecondsToCentimeters(duration);

  // Print the distance
  Serial.print("Distance: ");
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  // ultrasonic end

  // the servo motor should activate when object is
  //less than 30cm close to the sensor

 if(cm < 30) {

  // sweep the servo from 0 to 180 degrees in steps
  // of 1 degrees
  for (pos = 0; pos <= 180; pos += 1) {

    // tell servo to go to position in variable 'pos'
    servo_9.write(pos);

     //LCD TIMER START
    lcd.setCursor(0, 1);
    sprintf(timeline,"%0.2d secs", seconds);
    lcd.print(timeline);
    delay(1000);
    seconds++;

    //led buld switch on
    digitalWrite(11,HIGH);

    // wait 20ms for servo to reach the position
    delay(200);

    //switch of the bulb
    digitalWrite(11,LOW);

  }

  //moving servo back to zero
  for (pos = 180; pos >= 0; pos -= 1) {
      // tell servo to go to position in variable 'pos'
      servo_9.write(pos);
      // wait 20 ms for servo to reach the position
      delay(20); // Wait for 15 millisecond(s)
            }

    } //if end

  delay(100);

}//loop end

//FUNCTIONS

long microsecondsToCentimeters(long microseconds) {
  // The speed of sound is 340 m/s or 29 microseconds per centimeter.
  // The ping travels out and back, so to find the distance of the
  // object we take half of the distance travelled.
  return microseconds / 29 / 2;
}

This program spends most of its time executing delay(), which does no useful work. Study the Blink Without Delay Arduino tutorial and see if it answers your question.

The servo moves with the speed you programmed it. (And there are delays between the moves. ) And don't think in "multiple processes". It's easier than that and you don't have an operating system on an uno.

@EdgarBonet thank you. I will check it out

@DataFiddler ok sure. Thanks for the guidance !!

Think of an Arduino as a circus clown spinning plates. It has to spend very little time on any one plate, and then it can keep a lot of plates spinning, moving quickly from one to the next.
That's how "multi-tasking" works on a realtime device like an Arduino. You write a loop function that buzzes through a bunch of sub-tasks, spending a few microseconds on each one, and then repeats the process. Each plate (sub-task) gets a little bit of time on each pass, but only a little.
The delay() function is the death of that. If you're in a delay(), everything comes to a screeching halt. Your program stops checking for button presses, stops switching output pins to control your motors, etc. It's like the clown taking a coffee break. The plates start crashing to the ground.
You might get away with single-digit delays for things like timing changes in output state (and delayMicroseconds() is rarely a problem since those delays are so short), but a delay(1000) means everything comes to a screeching halt for a full second.
You need to refactor your code to get rid of calls to delay() with delay values of more than a few milliseconds. Do a search on "Arduino blink without delay" to figure out how.
Note that on a single core device with preemptive multi-tasking, the circus clown analogy still holds, but now the OS serves as the clown's manager. The OS schedules the clown's time, and tells it when to switch between plates. If the clown gets distracted by a particularly shiny plate and tries to spend too long on that plate, the OS forces the clown to switch plates. The OS also saves the clown's current state each time it switches away from a task, and restores that state when it returns to that task.
On A multi-core device with preemptive multi-tasking, the manager (OS) has a team of clowns (cores). Each clown (core) gets assigned to different plates (tasks), and all the clowns work at the same time (The cores run concurrently.) The OS has to make sure the clowns (cores) don't bump elbows (have conflicting access to the same memory or other resources.)

Thanks a lot for the answer. It clears a lot of things for me as I am new here and puts the functioning of arduino in a better perspective.

upvote for the best analogy of multitasking i have seen so far ... the spinning plate circus act may actually be something that almost everyone has seen

Best analogy I've heard for Arduino loops so far. I created an account over here to upvote it..

Thank you again. I was able to refactor my code to make it work after implementing the Arduino Work Without Delay Article


text:
Sending arduino sensor data via WiFi to a MySQL server
I'm aware this question has probably been asked many times but I'm pulling my hair out.
I'm trying to get sensor data from an arduino to a MySQL server. I've checked the apache access log and the request is there. But it just isn't being inserted into the database. Manually adding the data using the browser works so the php code seems fine. I've allowed apache through the firewall and updated the permissions all to no avail. Code below:
Arduino Main Code:
#include "thingProperties.h"
#include <Arduino_MKRENV.h>
#include <WiFi.h>

WiFiClient client;

void setup() {
  // Initialize serial and wait for port to open:
  Serial.begin(9600);
  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
  delay(1500);

  //Connect to WiFi network
  int status = WL_IDLE_STATUS;
  while (status != WL_CONNECTED){
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(SSID);
    status = WiFi.begin(SSID, PASS);
    delay(10000);
  }
  Serial.println("This is connected.");

  if (!ENV.begin()) {
  Serial.println("Failed to initialize MKR ENV shield!");
  while(1);
  }
  pinMode(2, INPUT);
}

void loop() {
 relativeHumidity = int(ENV.readHumidity());
 lightIntensity = (ENV.readIlluminance());
 airPressure = int(ENV.readPressure(MILLIBAR));
 temperature = int(ENV.readTemperature());
 if(digitalRead(2) == LOW){
   rain = 1;
 }else if(digitalRead(2) == HIGH){
   rain = 0;
 }
 Serial.println("httpRequest");
 httpRequest();
 delay(10000);
}

void httpRequest(){
  // if there's a successful connection:
  if (client.connect(SERVER, 80)) {
    Serial.println("Connecting to server...");
    // send the HTTP PUT request:
    client.print("GET /weather_data.php?temp=");
    Serial.println("GET /weather_data.php?);
    client.print(temperature);
    client.print("&pressure=");
    client.print(airPressure);
    client.print("&humidity=");
    client.print(relativeHumidity);
    client.print("&illumination=");
    client.print(lightIntensity);
    client.print("&rain=");
    client.print(rain);
    client.print(" ");
    client.println("HTTP/1.1");
    client.print(" Host: ");
    client.println(SERVER);
    client.println();
    Serial.println("Added.");
  } else {
    Serial.println("Not connected.");
  }
  if (client.connected()){
    client.stop();
  }
}

thingProperties.h:
#include <WiFi.h>
#include <SPI.h>

const char THING_ID[] = "c942a18f-7696-4431-952c-76eaea3214ea";

const char SSID[]     = SECRET_SSID;    // Network SSID (name)
const char PASS[]     = SECRET_PASS;    // Network password (use for WPA, or use as key for WEP)
const char SERVER[]   = SECRET_IP;      // Server IP Address

int airPressure;
float lightIntensity;
float relativeHumidity;
bool rain;
float temperature;

So your Arduino is using a WiFi library to submit HTTP commands to a server running an Apache web server stack? And you are seeing the commands logged to the server? If so, you're going to have to debug the sever side of this. Is the command well formed when received? What is being done with it? You say "Manually adding the data using the browser works so the php code seems fine." That is too much of a leap. Using a web client to submit your request vs. doing it from a raw HTTP GET command exercises a different path on your server.

does the record get inserted when you use a web browser? ... if it does, copy the URL and include as a comment in your code

The following is an example of the requests directly from the access log: 192.168.0.3 - - [24/Jun/2020:21:26:58 +0100] "GET /weather_data.php?temp=32.00&pressure=1009&humidity=40.00&illumination=3.23&rain=0 HTTP/1.1" 400 311

the 400 is HTTP response code? see the WebClient example on how to print the HTTP response in Arduino

So I don't quite know why, but I started from scratch and it works now. I've put the new code below in case it helps someone in my situation.
// Arduino Low Power - Version: Latest
//#include <ArduinoLowPower.h>
//#include <ArduinoIoTCloud.h>
#include "thingProperties.h"
#include <Arduino_MKRENV.h>
/*
  Repeating Wifi Web Client

  This sketch connects to a a web server and makes a request
  using a WiFi equipped Arduino board.

  created 23 April 2012
  modified 31 May 2012
  by Tom Igoe
  modified 13 Jan 2014
  by Federico Vanzati

  http://www.arduino.cc/en/Tutorial/WifiWebClientRepeating
  This code is in the public domain.
*/

#include <SPI.h>
#include <WiFiNINA.h>

int status = WL_IDLE_STATUS;

// Initialize the Wifi client library
WiFiClient client;

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

  // check for the WiFi module:
  if (WiFi.status() == WL_NO_MODULE) {
    Serial.println("Communication with WiFi module failed!");
    // don't continue
    while (true);
  }

  String fv = WiFi.firmwareVersion();
  if (fv < WIFI_FIRMWARE_LATEST_VERSION) {
    Serial.println("Please upgrade the firmware");
  }

  // attempt to connect to Wifi network:
  while (status != WL_CONNECTED) {
    //Serial.print("Attempting to connect to SSID: ");
    //Serial.println(SSID);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(SSID, PASS);

    // wait 10 seconds for connection:
    delay(10000);
  }
  // you're connected now, so print out the status:
  //printWifiStatus();
  //Start arduino cloud.
  //ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  //Begin ENV shield.
  if (!ENV.begin()) {
    Serial.println("Failed to initialize MKR ENV shield!");
    while (1);
  }
}

void loop() {
  //ArduinoCloud.update();
  // if there's incoming data from the net connection.
  // send it out the serial port.  This is for debugging
  // purposes only:
  while (client.available()) {
    char c = client.read();
    Serial.write(c);
  }
    //Serial.println("Start reading sensors.");
    relativeHumidity = int(ENV.readHumidity());
    //Serial.println(relativeHumidity);
    lightIntensity = int(ENV.readIlluminance());
    //Serial.println(lightIntensity);
    airPressure = int(ENV.readPressure(MILLIBAR));
    //Serial.println(airPressure);
    temperature = int(ENV.readTemperature());
    //Serial.println(temperature);
    UV_Index = int(ENV.readUVIndex());
    //Serial.println(UV_Index);
    if (digitalRead(2) == LOW) {
      rain = 1;
    } else if (digitalRead(2) == HIGH) {
      rain = 0;
    }
    //Serial.println(rain);
    //Serial.println("Sensor data read.");
    //Serial.println("Start http request.");
    httpRequest();
    //Serial.println("Stop http request");
    delay(60000);
}

// this method makes a HTTP connection to the server:
void httpRequest() {
  // close any connection before send a new request.
  // This will free the socket on the Nina module
  client.stop();

  // if there's a successful connection:
  if (client.connect(server, 80)) {
    //Serial.println("connecting...");
    // send the HTTP PUT request:
    client.print("GET /weather_data.php?temp=");
    client.print(temperature);
    client.print("&pressure=");
    client.print(airPressure);
    client.print("&humidity=");
    client.print(relativeHumidity);
    client.print("&illumination=");
    client.print(lightIntensity);
    client.print("&UV_Index=");
    client.print(UV_Index);
    client.print("&rain=");
    client.print(rain);
    client.print(" ");
    client.println("HTTP/1.1");
    client.println("Host: 192.168.0.29");
    client.println("User-Agent: ArduinoWiFi/1.1");
    client.println("Connection: close");
    client.println();
  } else {
    // if you couldn't make a connection:
    //Serial.println("connection failed");
  }
}

void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your board's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

I see you don't use the WiFi library but the WiFiNINA library

WiFi.h is for Arduino WiFi shield. Use the WiFiNINA library for MKR1010

Made that change but still doesn't seem to be working

@SamAnderson, maybe it doesn't work yet, but with WiFiNINA it has at least a chance to work.


text:
ESP32 + Attiny85 AC Dimmer
I am working on an AC Dimmer project using ESP32 and Attiny85.

Note : I know ATtiny85 is overkill for this project, And it can be done without Attiny85, I have already done this using ESP32 alone. But I have some PCB laying around designed in such a manner. So thought of doing this.

Here ESP32 communicates to Attiny over i2c.
ESP - Master
Attiny - Slave

Here Zero Cross Detector(ZCD) circuit is connected to PB1. and T1 to Triac Circuit
Depending on the commands over i2c from ESP to each Attiny, It controls the brightness.
The Problem
I am able to set the brightness using i2c (like LOW, MED, HIGH, OFF). But only once.
For example, if I set it to HIGH state initially it will get stuck in that state, Even if any other command is given, Similar for all others. Basically, it will only work once.
I think the interrupt is causing the problem, once interrupt is attached the i2c isn't responding
Here are codes
Slave https://pastebin.com/sqsMYLa0
#include "PinChangeInterrupt.h"
#include "TinyWireS.h"

#define I2C_SLAVE_ADDR  2
int AC_LOAD = 3;
int ZCD_Pin = 1;
int dimming = 128;
int Speed[3] = {90, 50, 20};
int speedValue;
bool fan;

void setup() {
  pinMode(AC_LOAD, OUTPUT);
  TinyWireS.begin(I2C_SLAVE_ADDR);
  TinyWireS.onReceive(receiveEvent);
  pinMode(ZCD_Pin, INPUT_PULLUP);
}

void zero_crosss_int()  //function to be fired at the zero crossing to dim the light
{
  int dimtime = (75 * dimming);  // For 60Hz =>65
  delayMicroseconds(dimtime);    // Wait till firing the TRIAC
  digitalWrite(AC_LOAD, HIGH);   // Fire the TRIAC
  delayMicroseconds(100);         // triac On propogation delay  // (for 60Hz use 8.33) Some Triacs need a longer period
  digitalWrite(AC_LOAD, LOW);    // No longer trigger the TRIAC (the next zero crossing will swith it off) TRIAC
}

void receiveEvent(uint8_t howMany)
{
  byte byteRcvd = 0;
  if (TinyWireS.available()) {
    byteRcvd = TinyWireS.receive();     // get the byte from master

    if (byteRcvd == '0') {
      fan = false;
      detachPinChangeInterrupt(digitalPinToPCINT(ZCD_Pin));
      digitalWrite(AC_LOAD, LOW);
    }
    if (byteRcvd == '1') {
      fan = true;
      speedValue = Speed[0];
      attachPCINT(digitalPinToPCINT(ZCD_Pin), zero_crosss_int, RISING);
    }
    if (byteRcvd == '2') {
      fan = true;
      speedValue = Speed[1];
      attachPCINT(digitalPinToPCINT(ZCD_Pin), zero_crosss_int, RISING);
    }
    if (byteRcvd == '3') {
      fan = true;
      speedValue = Speed[2];
      attachPCINT(digitalPinToPCINT(ZCD_Pin), zero_crosss_int, RISING);
    }
    dimming = speedValue;
  }
}

void loop() {
  delay(100);
}

Master https://pastebin.com/E5U74LEx
#include <Wire.h>
//#define I2C_SLAVE_1_ADDR  1
#define I2C_SLAVE_2_ADDR  2

void setup() {
  Wire.begin(); // join i2c bus (address optional for master)
  Serial.begin(9600);
  Serial.print("Ready");
}

char x = 0;

void loop() {
  if (Serial.available() > 0) {

    x = Serial.read();

    if (x == '0') {
      Wire.beginTransmission(2);
      Wire.write('0');
      Wire.endTransmission();
      Serial.print("Send 0");
    }
    if (x == '1') {
      Wire.beginTransmission(2);
      Wire.write('1');
      Wire.endTransmission();
      Serial.print("Send 1");
    }
    if (x == '2') {
      Wire.beginTransmission(2);
      Wire.write('2');
      Wire.endTransmission();
      Serial.print("Send 2");
    }
    if (x == '3') {
      Wire.beginTransmission(2);
      Wire.write('3');
      Wire.endTransmission();
      Serial.print("Send 3");
    }
  }
}

For testing, I have used Serial monitor for sending commands. Later It will be done using MQTT

That's a pretty long delay in the ISR; have you tried setting a state and handling the rest in loop?

@DaveNewton Yes, but the output is flickering.
here is the code https://pastebin.com/FnTkE8hZ

https://arduino.stackexchange.com/questions/63631/fan-regulator-control-from-arduino/63674#63674