body:
In modern timekeeping, there is a 10 MHz reference frequency (or any power of 10). The digital clock takes 32768 Hz frequency only (or some other power of 2 possible).

The problem is how to convert power of 10 to power of 2 nicely. It is done by a series of 1.25 (every 5 inputs output 4) and 2.5 dividers (every 5 inputs output 2).

I am interested in how this can be done by Arduino.
I have a high input frequency, say 1 MHz, therefore i have to use registers directly. Then I have output frequency 1/2 (counter of 2) of the input and 1/4 of the input frequency and I would like to have output 4/5 of the input (divide by 1.25 counter). So, do I need 3 output pins, 1 for counting twos, one for fours, and one for fives? Or can this be done somehow just by 1 input pin and 1 output pin with 4/5 input frequency?

I tried to modify the code but I can not tell how to skip every 5th cycle.
Let's say in the chaining of these counters I can get from 1 000 000 Hz frequency:
1000000 Hz - 800000 Hz - 640000 Hz - 512000 Hz - 409600 Hz - 327680 Hz - 2262144 Hz
so input = power of ten, then output = power of two
My question is how high could be the maximal input frequency to this code?
and can you please help me to modify that code?

```
/*
 * From one square wave generate 3 waves 1/2, 1/4 and 4/5 of the original frequency.
 *
 * Original sketch tried to be modified from here:
 *
 * https://arduino.stackexchange.com/questions/63202
 *                               _   _   _   _   _   _   _   _   _   _
 *  input:  digital 13 = PB7    / \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/  1 000 000 Hz
 *                              R1F0R1F0R1F0R1F0R1F0R1F0R1F0R1F0R1F0R1F0R
 *                               ___     ___     ___     ___     ___
 *  output: digital 10 = PB4    /   \___/   \___/   \___/   \___/   \___/    500 000 Hz
 *                              R 1 F 0 R 1 F 0 R 1 F 0 R 1 F 0 R 1 F 0 R
 *                               _______         _______         _______
 *  output: digital 11 = PB5    /       \_______/       \_______/       \    250 000 Hz
 *                              R   1   F   0   R   1   F   0   R   1   F
 *                               _   _   _   _       _   _   _   _
 *  output: digital 12 = PB6    / \_/ \_/ \_/ \_____/ \_/ \_/ \_/ \_____/    800 000 Hz
 *                              R1F0R1F0R1F0R1F00000R1F0R1F0R1F0R1F00000R
 */

int main(void)
{
    DDRB = _BV(PB4) | _BV(PB5) | _BV(PB6) | ~_BV(PB7);  // PB4 PB5 PB6 as outputs and PB7 as input
    for (;;) {
        loop_until_bit_is_clear(PINB, PB7);             // wait for rising input
        loop_until_bit_is_set(PINB, PB7);
        PORTB |= _BV(PB4);                              // rise PB4

        loop_until_bit_is_clear(PINB, PB4);             // wait for rising input
        loop_until_bit_is_set(PINB, PB4);
        PORTB |= _BV(PB5);                              // rise PB5

        loop_until_bit_is_clear(PINB, PB5);             // wait for rising input
        loop_until_bit_is_set(PINB, PB5);
        PORTB |= _BV(PB6);                              // rise PB6

        loop_until_bit_is_clear(PINB, PB7);             // wait for rising input
        loop_until_bit_is_set(PINB, PB7);
        PORTB &= ~_BV(PB4);                             // fall PB4

        loop_until_bit_is_clear(PINB, PB7);             // wait for rising input
        loop_until_bit_is_set(PINB, PB7);
        PORTB |= _BV(PB4);                              // rise PB4

        loop_until_bit_is_clear(PINB, PB4);             // wait for rising input
        loop_until_bit_is_set(PINB, PB4);
        PORTB |= ~_BV(PB5);                             // fall PB5

        loop_until_bit_is_clear(PINB, PB7);             // wait for rising input
        loop_until_bit_is_set(PINB, PB7);
        PORTB &= ~_BV(PB4);                             // fall PB4

        loop_until_bit_is_clear(PINB, PB7);             // wait for rising input
        loop_until_bit_is_set(PINB, PB7);
        PORTB |= _BV(PB4);                              // rise PB4

        loop_until_bit_is_clear(PINB, PB4);             // wait for rising input
        loop_until_bit_is_set(PINB, PB4);
        PORTB |= _BV(PB5);                              // rise PB5

        loop_until_bit_is_clear(PINB, PB5);             // wait for rising input
        loop_until_bit_is_set(PINB, PB5);
        PORTB |= ~_BV(PB6);                             // fall PB6

        loop_until_bit_is_clear(PINB, PB7);             // wait for rising input
        loop_until_bit_is_set(PINB, PB7);
        PORTB &= ~_BV(PB4);                             // fall PB4

        loop_until_bit_is_clear(PINB, PB7);             // wait for rising input
        loop_until_bit_is_set(PINB, PB7);
        PORTB |= _BV(PB4);                              // rise PB4

        loop_until_bit_is_clear(PINB, PB4);             // wait for rising input
        loop_until_bit_is_set(PINB, PB4);
        PORTB |= ~_BV(PB5);                             // fall PB5

        loop_until_bit_is_clear(PINB, PB7);             // wait for rising input
        loop_until_bit_is_set(PINB, PB7);
        PORTB &= ~_BV(PB4);                             // fall PB4
    }
}
```

---

Nick Gamon personally :D I saw you so many times here. what an honour.
I do need a source clock for multiplanetary clock, without fractions.
The least common multiple for periods of second for: Earth, Mars, Titan.

If I will keep the ratio between planets exactly, then even if the Earth clock using Arduino resonator will drift by a few tens of seconds per day, Mars clock and Titan clock will drift the same amount of time.

This does not matter to me because if I stop the clock and wait then All 3 planets will be aligned again. But if I would not keep the ratio between planets exactly, for Example Earth would drift 30 seconds per day, Mars would drift 31 seconds per day, and Titan would drift 29 seconds per day- it depends on how close approximation I will take. So, by stopping the clock for 30 seconds to set it correctly, Earth would go back to 0 seconds, but Titan would be 1 second behind and Mars would be 1 second before. I would not correct all 3 just by stopping the clock. I would have to stop the clocks 3 times individually (once for each planet, if not, the error for the 2 remaining planets would accumulate over time, even if correcting Earth)
And trust me, it's not easy to calculate Mars time (ok it is because NASA application already exists) but Titan Time I have only in my Excel, and that one I have to recalculate when setting the clock.

Periods for Earth: 1 s, Mars 1.027 491 251 7 s, Titan 0.998 068 437 5 s,

Obviously, Arduino math is not exact to the 10 decimal places, maximally
32 bytes which is 0.000 000 000 2 and something ... that is 2 to -32nd power.

The options for least common multiple: \
Earth:Mars = 291/299, Earth:Titan = 3624/3617\
Earth:Mars:Titan = integer:integer:1 054 584 (that is 291 x 3624)

so 1st option, is to generate 1 054 584 Hz (I call it golden Megahertz) which is slightly more than 15 Arduino clock cycles = to be exact 15 and 16 cycles would have to alternate with some leap cycle rule (analogous to our leap year rule) to get this frequency.

Find another, decimal frequency slightly off.

Option 1:
Earth:Mars = 812993/800000 and Titan could be 1/4 cycle off, so 800 kHz

Option 2:
Earth:Mars:Titan = integer:integer:3200000 so 3.2 MHz (5 clock cycles) and Mars, Titan, Earth are better aligned,

Option 3:
9600000 Hz frequency (5 clock cycles on 48 MHz Arduino Zero exactly, or 10 cycles on overclocked 96 MHz Arduino Due), and perfect planet alignment.

These options need to have 24 bit counter, up to 16777216 not just 16 bytes.
If I don't keep the ratio exactly, the clock would drift at different speeds and to correct the clock to stop all 3 clocks at once would not be enough.

Each one would have to be corrected individually (even though Earth would have the biggest error from Arduino resonator, some residual errors from not exact ratios will accumulate over time, and once in a while, additional 2 clocks would have to be stopped and set individually)

---

Also, i would like to have something like calendar for each planet, what would the fastest and shortest way to configure it? Earth: 365.2425 days, Mars 668.592 days and Titan 673.54388 days. For Earth we have 365 plus every 4th leap but every 100th not leap but every 400th leap. Days in month are 31,28/29,31,30,31,30,31,31,30,31,30,31. For Mars we would have: 56,56,55,56,56,55,56,56,55,56,56,55/56, and every odd and every 10th leap (thats .6) but not every 100  (thats .59 )but every 500 leap (thats .592). Leap month would be 12-th month. For Titan we would have 56,56,56,56,56,57,56,56,56,56,56,56/57, and every odd and every 20th leap (thats .55) but not every 160 th leap (thats .54388). Also, that lenghth mentioned is not 1 Titan day, but 1/16th Titan day, yes Titan day is almost 16 days long. So, i would like to have something like "days in a day" = 8 days week of 24 hours of 60 minutes of 60 seconds of 0.98 above mentioned earth seconds, and AM and PM week. The 8th day would be called "Earthday and would be between Sunday and Monday". For Mars we would have 7 day weeks as on Earth, and in a similar way, Monday 1st, Tuesday 2nd, .... But for Titan we would have 16 times 1st: AM Monday 1st, AM Tuesday 1st, ... AM Sunday 1st, AM Earthday 1st, PM Monday 1st, PM Tuesday 1st, ... PM Sunday 1st, PM  Earthday 1st, and then 16 times 2nd, ... again from AM Monday till PM Earthday. So we can divide terribly long 16 day day into weeks and days. do we have some reasonable function like RTC where i in/out put (year, month, day, week, weekday, hour, minute, second) when i in/out put "unix time" for Earth, Mars and Titan based on different length of seconds? We would have Unix Earth, Unix Mars and unix Titan. Obviously for Earth and Mars, the weekday and date would advance simultaneously and we dont need "week" for Earth and Mars (that would be dislabled) and for Titan there are 8 weekdays and then 2 weeks and then 1 titan day (2 weeks long) so yes 16 days day and 673.54 of them thats almost 30 years long year. the formulas among Earth Mars and Titan Unix time have to be ready yet, but how to break that unsigned long unix time for each planet into the components, and one more (week) component for Titan, an titan day is awfully long, do weekday (and week) here is time, not day, but day within a day, and week within a day.

---

Nick Gamon, i dont want to be disrespectful, this is my very first question after several years of reading these forums.

There is indeed a capability of Arduino Uno r4 generating 1/256 sec interrupt directly, as there is dedicated library for that, using its bult in RTC clock, which are already part of that Arduino.

Unfortunately, the nice round multiple for Earth, Mars, Titan would be 3.2 million Hz. As Arduino 4 is 32 bit processor 48 MHz, it does math up to 32 bits within one or two clock cycles. and 3.2 million Hz would be exactly 15 clock cycles, however that not much cycles for interrupt. But 256 Hz is plenty of time for 48 MHz 32 bit processor right? im not sure how exact are that RTC clock, need to find out as soon as ill get it. That Arduino uno R4 appeared just few days ago in the shop and its totally new and different. (32 bit, 48 MHz)

1/256 th of second is 12500 / 3200000 second. so Thank god 3.2 million is divisible by 256 without any fraction.

I am enclosing the example for Arduino r4 documentation:

https://docs.arduino.cc/tutorials/uno-r4-wifi/rtc#unix

```
#include "RTC.h"

const int LED_ON_INTERRUPT  = 22;

void setup(){
  RTC.begin();
  if (!RTC.setPeriodicCallback(periodic_cbk, Period::ONCE_EVERY_2_SEC)) {
    Serial.println("ERROR: periodic callback not set");
  }
}

void loop() {
}

void periodic_cbk() {
  static bool clb_st = false;
  if(clb_st) {
    digitalWrite(LED_ON_INTERRUPT,HIGH);
  }
  else {
    digitalWrite(LED_ON_INTERRUPT,LOW);
  }
  clb_st = !clb_st;

  Serial.println("PERIODIC INTERRUPT");
}
```

The period can be specified using the following enumerations:
```
ONCE_EVERY_2_SEC
ONCE_EVERY_1_SEC
N2_TIMES_EVERY_SEC
N4_TIMES_EVERY_SEC
N8_TIMES_EVERY_SEC
N16_TIMES_EVERY_SEC
N32_TIMES_EVERY_SEC
N64_TIMES_EVERY_SEC
N128_TIMES_EVERY_SEC
N256_TIMES_EVERY_SEC
```
---

Now, I am also strugglling with how to incorporate that calendar from Unix time, to break it into individual components for Earth, Mars and Titan. Unix time began on 01/01/1970 00:00:00, unix Mars would began on 01/01/192 00:00:00 and Titan Unix would began on 01/01/13 AM Monday 00:00:00, but i would like to have the initial years adjustable because. It will eventually run out of range after 136 earth years, 72 Mars years and some 4.6 Titan years so we could re-use it by shifting initial year, and also, i would like to have it valid at least till 2323, so, only with resolution 4 second, because 300 years has less than 2 to the 32th 4-second intervals. But that calendar is giving me a headache. I saw RTC library but i cant just change numbers to get Mars, and Titan calendar.

The reason i would like to have it, is because in some point in the future, the human colonisation of Mars will begin, and in more distant future, the human colonisation of Titan (Saturns moon) will begin (there is already a nuclear powered helicopter which will operate in Titan high density atmosphere and low gravity and very cold environment, in 2034 (the date is already approved by NASA, it will lift off in 2027, but as u can suppose the flight takes 7 years to cover one billion miles, or 1.6 billion kilometers to Saturn), and plan for nuclear powered submarine which will swim in its liquid methane seas, not sure when, but the concept already exists, its close to liquid nitrogen temperature, liquid methane has temperature of minus 180 degrees Celsius or like minus 300 degrees of Farenheit, so heating by and insulation have to be perfect) and for enery planet we do need different calendar

---

If i would have to be capable to construct PLL (phase-locked-loop) then i would have to be able to go from 32768 Hz exactly to 3.2 MHz (as exactly as the 32768 Hz crystal is exact), by 5 times multiplying it by 2.5 that is (multiply by 5 and divide by 2). Lol I could not do 5 times multiply by five because i would get 102.4 MHz (and then divide it 5 times by 2) and not even Arduino due is that fast enough to catch that interrupt. But pure TTL logic is capable to to do it (assuming it can multiply by fractions, that is 2.5 to the 5th power)

---

Hi guys, the lcd keypad shield 1602 A is compatible with which library and which arduino? how the pins have to be set? I just cant make it working

title: How to divide high input frequency by 1.25 like old-school TTL logic by Arduino?

Answers: 2

body:
What you are suggesting is far too complex. Use the internal timers, say timer 0, 1 or 2 on the Atmega328P (Arduino Uno) with a prescaler of 64 (which gives you 4 µs per timer tick) and then count up to 250, giving you a period of 1 ms.

The timer can be configured to toggle an output pin, giving you this frequency as an output. If you are toggling you may want to halve what you count to (one count for the leading edge and the second count for the trailing edge). Or use PWM mode with a duty cycle of 50%.

---

From a comment to a different answer:

>  I am planning to get Arduino Uno R4 which is capable to generate - fastest - 1/256 s interrupts using its in-built RTC - Clock

Not at all. The Uno timers can be configured to interrupt at practically any rate (the limit being how fast the interrupt routine can execute).

The software from the IDE configures Timer 0 to interrupt once every 1.024 ms, which is a lot more often than 1/256 s. However you can reconfigure that, or indeed the other timers, to interrupt at virtually any interval, within reason.

See [my page about timers](https://gammon.com.au/timers) for more information.

I could easily give you code that would generate an interrupt every 1/256s or indeed 1/32768s but I don't see how those rather unusual numbers, from the point of view of the planets, would help you.

In fact, probably better from your point of view is to simply keep track of elapsed time and do your calculations from that. For example, `millis()` tells you elapsed time since startup in milliseconds and will wrap around every 49.710 days. Or `micros()` which tells you the elapsed time in microseconds, and will wrap around every 71.58 minutes.

Now, you would need to handle wrap-around in any case, so that is no big deal.

It seems to me that your calculations for the planets' positions would simply be to take the current time (eg. using `millis()`) and then apply some arithmetic for each planet to work out where it must be.

Your desire to get interrupts, and your focus on 32768 as an interrupt interval seems to me to be be an XY problem. You know what they say, "if the only tool you have is a hammer, everything looks like a nail". Well, you have more tools than a hammer here.

body:
Your question is a perfect example of an [XY problem][]: you are asking
something that has little to do with your actual problem, but is rather
about your misguided idea of a solution. Counting Mars seconds or Titan
seconds is an easy problem. Dividing the frequency of a 1 MHz
signal by successive powers of 1.25 is a hard problem. There is little
value in turning an easy problem into a hard one.

I suggest a solution inspired by [Bresenham's algorithm][algo] for
drawing slanted lines:

 * configure a timer to deliver a periodic interrupt to your program,
   with a period shorter than your shortest relevant second
 * compute the ratio of your favorite planet's second to the interrupt
   period
 * approximate this ratio by a rational number _p_/_q_

In the interrupt service routine:

 * increment a counter by _q_
 * when the counter reaches _p_, decrement it by _p_ and note that one
   second has elapsed.

The lazy way of getting a periodic interrupt is to simply enable the
TIMER0\_COMPA interrupt. Timer 0 is already configured by the
Arduino core to count full cycle every 1,024 µs. You may want to
set OCR0A to something near 128 in order to prevent the overflow
interrupt (used by Arduino for timing) and your interrupt from getting
too close.

For the Earth, the ratio is

1 s / 1,024 µs = 1,000,000 / 1,024 = 976.5625 = 15625 / 16

For Mars and Titan, they can be approximated by 22,075/22 and 33,139/34
respectively, to within a fraction of a ppm.

Here is the interrupt service routine:

```c++
// Count of elapsed seconds on each planet.
volatile uint32_t earth_secs, mars_secs, titan_secs;

// Executed every 1,024 us on a timer interrupt.
ISR(TIMER0_COMPA_vect) {
    static uint16_t earth_ticks, mars_ticks, titan_ticks;
    earth_ticks += 16;
    if (earth_ticks >= 15625) {
        earth_ticks -= 15625;
        earth_secs++;
    }
    mars_ticks += 22;
    if (mars_ticks >= 22075) {
        mars_ticks -= 22075;
        mars_secs++;
    }
    titan_ticks += 34;
    if (titan_ticks >= 33139) {
        titan_ticks -= 33139;
        titan_secs++;
    }
}
```

Note that you can build better approximations of Mars and Titan seconds
by using rational numbers with larger _p_ and _q_, but then you would
have to do 32-bit arithmetics in the ISR. You could also configure
another timer to deliver an interrupt with a longer period: you would
then be able to achieve better accuracy with 16-bit arithmetics, at the
cost of increased jitter.

[XY problem]: https://xyproblem.info/
[algo]: https://en.wikipedia.org/wiki/Bresenham's_line_algorithm

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

**Edit**: Here is a variation on this idea that uses `millis()` instead
of interrupts. Of course, Nick Gammon is right: you do not need
interrupts for a clock that updates its display a few times per second.
It was just a bit easier to write an interrupt-based code, as the time
between successive calls of the function is a known constant.

Given that you are going to use a 32-bit processor, I wrote this using
32-bit arithmetic. The ratios should be a little bit more accurate.

```c++
uint32_t earth_seconds, mars_seconds, titan_seconds;

void update_planet_times() {
    // Compute number of elapsed milliseconds since last update.
    static uint32_t last_update;
    uint32_t now = millis();
    uint32_t elapsed_millis = now - last_update;
    last_update = now;

    // Update Earth time. 1 Earth second = 1000 / 1 ms.
    static uint32_t earth_ticks;
    earth_ticks += elapsed_millis * 1;
    uint32_t elapsed_earth_seconds = elapsed_earth_ticks / 1000;
    earth_ticks -= elapsed_earth_seconds * 1000;
    earth_seconds += elapsed_earth_seconds;

    // Update Mars time. 1 Mars second = 763426 / 743 ms.
    static uint32_t mars_ticks;
    mars_ticks += elapsed_millis * 743;
    uint32_t elapsed_mars_seconds = elapsed_mars_ticks / 763426;
    mars_ticks -= elapsed_mars_seconds * 763426;
    mars_seconds += elapsed_mars_seconds;

    // Update Titan time. 1 Titan second = 3193819 / 3200 ms.
    static uint32_t titan_ticks;
    titan_ticks += elapsed_millis * 3200;
    uint32_t elapsed_titan_seconds = elapsed_titan_ticks / 3193819;
    titan_ticks -= elapsed_titan_seconds * 3193819;
    titan_seconds += elapsed_titan_seconds;
}
```

Note that using this technique for the Earth may seem superfluous: one
may count seconds by simply computing `millis()/1000`. This, however,
would fail when `millis()` rolls over in 49.7 days. The code above
is immune to this rollover, and should count Earth seconds reliably for
the next 136.1 years.


body:
I have two functions that return an int16_t but I need to convert the ints to
char* is for an attiny13

It would be something like this

    const char* msg = "value1()"+','+"value2()"+','+"value3()"

like example

    #include "TinyRF_TX.h"

    void setup(){
      // transmitter default pin is pin #2. You can change it by editing Settings.h
      setupTransmitter();
    }

    void loop(){

      const char* msg = "Hello from far away!";

      //send function accepts an array of bytes as first argument
      //second argument is the length of the array
      send((byte*)msg, strlen(msg));

      //make sure there's at least a TX_DELAY_MICROS delay between transmissions
      //otherwise the receiver's behavior will be undefined
      delayMicroseconds(TX_DELAY_MICROS);

title: problem conversion value

Answers: 1

body:
You will need to build the string yourself. Probably the easiest way is using the `sprintf()` function which will take a bunch of arguments and convert them to a string based on formatting instructions you give it.

An apropos article here...
https://www.programmingelectronics.com/sprintf-arduino/


body:
I am working on a simple little robot to cure my boredom and all it has is a 64 x 32 OLED for the eyes, and a PAJ7620 Gesture recognition sensor with a Seeeduino Xiao as the main board.

Basically, when people swipe above the head where the sensor is, the robot will show the heart eyes. There are different reactions for different actions and all this is controlled through functions. When the sensor does not detect anything, the robot is supposed to cycle through a certain void which is determined based on how much it 'likes' the person.

Right now though, it just cycles through the function and does not respond to the sensor. My code is *very* inefficient because of all the functions, but it makes it more readable and more easily editable. With all my functions, the gesture sensor takes too long to respond to the actions.

What can I do to fix this? Can someone please help or give advice on how I can improve my code?
```c
    #include <Arduino.h>
    #include <U8g2lib.h>
    #include <Wire.h>
    #include <DFRobot_PAJ7620U2.h>

    int like_score = 3;//Score for how much the bot likes you: this will impact which voids are used.
    int max_like_score = 17;
    char buffer[9];

    unsigned long previousMillis = 0;
    const long interval = 1000;

    DFRobot_PAJ7620U2 paj;

    U8G2_SSD1306_64X32_1F_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE);

    // fonts https://github.com/olikraus/u8g2/wiki/fntlistall#4-pixel-height
    void setup(void) {
      u8g2.begin();
      Serial.begin(115200);
      delay(300);
      u8g2.clearBuffer();
      Serial.println("Gesture recognition system base on PAJ7620U2");
      while (paj.begin() != 0) {
        Serial.println("initial PAJ7620U2 failure! Please check if all the connections are fine, or if the wire sequence is correct?");
        delay(500);
      }
      Serial.println("PAJ7620U2 init completed, start to test the gesture recognition function");
      paj.setGestureHighRate(true);
    }

    void normalL() {       //normal forward expression
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, normal);
      u8g2.sendBuffer();
    }
    void blinkL() {        //blinks
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, blink);
      u8g2.sendBuffer();
    }
    void left() {          //looks left
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, blinkleft);
      u8g2.sendBuffer();
    }
    void right() {         //looks right
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, blinkright);
      u8g2.sendBuffer();
    }
    void angryL() {        //angry
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, angry);
      u8g2.sendBuffer();
    }
    void loveL() {         //in love
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, love);
      u8g2.sendBuffer();
    }
    void sleepL() {        //sleeping
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, sleep);
      u8g2.sendBuffer();
    }
    void susL() {          //suspicious
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, sus);
      u8g2.sendBuffer();
    }
    void stunL() {         //looks stunned
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, stun);
      u8g2.sendBuffer();
    }
    void upL() {           //Looks up
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, up);
      u8g2.sendBuffer();
    }
    void gleeL() {
      u8g2.clearBuffer();  // clear the internal memory
      u8g2.drawBitmap(0, 0, 8, 32, glee);
      u8g2.sendBuffer();
    }
    void randomEx() {
      int rand = random(1, 8);
      if (rand == 1) {
        normalL();
      } else if (rand == 2) {
        left();
      } else if (rand == 3) {
        right();
      } else if (rand == 4) {
        angryL();
      } else if (rand == 5) {
        loveL();
      } else if (rand == 6) {
        susL();
      } else if (rand == 7) {
        upL();
      } else if (rand == 8) {
        gleeL();
      }
    }

    void likeRoutine() {
      normalL();
      delay(random(1000, 6500));
      blinkL();
      delay(90);
      normalL();
      delay(random(1000, 4500));
      randomEx();
      delay(random(1000, 4500));
      blinkL();
      delay(90);
      loveL();
      delay(random(2500, 4000));
      blinkL();
      delay(90);
    }
    void kindofLikeRoutine() {
      normalL();
      delay(random(1000, 7000));
      blinkL();
      delay(90);
      normalL();
      delay(random(1000, 4500));
      randomEx();
      delay(random(1000, 4500));
      blinkL();
      delay(90);
      loveL();
      delay(random(1000, 3000));
      blinkL();
      delay(90);
    }
    void dislikeRoutine() {
      normalL();
      delay(random(1000, 7000));
      blinkL();
      delay(90);
      normalL();
      delay(random(1000, 6500));
      randomEx();
      delay(random(1000, 4000));
      blinkL();
      delay(90);
      angryL();
      delay(random(1000, 3000));
      blinkL();
      delay(90);
    }
    void hateRoutine() {
      angryL();
      delay(random(1000, 5000));
      blinkL();
      delay(90);
      normalL();
      delay(random(1000, 6500));
      randomEx();
      delay(random(1000, 4000));
      blinkL();
      delay(90);
      angryL();
      delay(random(1000, 3000));
      blinkL();
      delay(90);
    }

    void loop(void) {
      DFRobot_PAJ7620U2::eGesture_t gesture = paj.getGesture();
      if (gesture != paj.eGestureNone) {
        String description = paj.gestureDescription(gesture);  //Convert gesture number into     string description
        if (gesture == 256) {                                  //wave
          gleeL();
          delay(random(1000, 4500));
        } else if (gesture == 2 && like_score < max_like_score) {  //pet
          blinkL();
          delay(90);
          loveL();
          like_score++;
          Serial.println(like_score);
          delay(random(1000, 3000));
          if (like_score == max_like_score) {
            blinkL();
            delay(90);
            loveL();
            delay(random(1000, 3000));
          }
        } else if (gesture == 16 && like_score <= max_like_score) {  //thump
          stunL();
          like_score--;
          Serial.println(like_score);
          delay(random(1000, 4000));
          angryL();
          delay(random(1000, 3000));
        } else if (gesture == 128) {
          u8g2.clearBuffer();
          u8g2.setFont(u8g2_font_t0_11_tf);  // choose a suitable font
          dtostrf(like_score, 6, 0, buffer);
          String scoreStr = String(buffer);
          u8g2.drawStr(0, 20, scoreStr.c_str());
          u8g2.sendBuffer();
          delay(random(2000, 3500));
        }
      } else {
        if (like_score >= 11) {
          likeRoutine();
        } else if (like_score > 7 && like_score < 11) {
          kindofLikeRoutine();
        } else if (like_score > 0 && like_score < 7) {
          dislikeRoutine();
        } else if (like_score < 0) {
          hateRoutine();
        }
      }
    }
```

title: Functions delaying gesture sensor recognition

Answers: 1

body:
The code is being slowed down by the `delay()` function because it is a `blocking` function.

The delay function does not exit until delay time passes, so no other functions can run, such as sensor reading.

The simplest solution for your code may be an FSM library (finite state machine).  It would look after all of the timing for you.

You could also replace the `delay()` functions with your own delay function, something like

```lang-cpp

void myDelay(int totalDelay) {

   for (i = 0; i < totalDelay/100; i++) {

                           // do some housekeeping here, like reading sensors

      delay(100);          // this blocks for only 1/10 of a second
   }                       // adjust the delay value if housekeeping takes a lot of time
}
```
The delay gets broken into a lot of small delays with time to do other things in between.

Another way is to check at the begining of `loop()` to see how much time has elapsed.
See blinkWithoutDelay example code in the Arduino IDE.

Here is an example in a simulator that may help you.

https://wokwi.com/projects/362275278547275777


body:
I am trying to detect if the digispark device is actually connected to a host (i.e. the USB line is "active") vs. just powered.
The issue: if I send a keypress while the data line is disconnected, the code hangs perpetually in [```sendKeyPress```](https://github.com/digistump/DigistumpArduino/blob/111396ffe5163c3613b9315cbea1a3eabc9ba6dc/digistump-avr/libraries/DigisparkKeyboard/DigiKeyboard.h#L188).
My theory is that it keeps looping in while waiting for USB to be ready, which makes sense.
```
    while (!usbInterruptIsReady()) {
      // Note: We wait until we can send keyPress
      //       so we know the previous keyPress was
      //       sent.
     usbPoll();
     _delay_ms(5);
    }
```
I tried to use the macro ```usbInterruptIsReady()``` before calling ```sendKeyStroke``` in the ```main```, but with no success. I would expect to see a function that keeps track of this state, but apparently there is none.

Also: it doesn't seem like what I am trying to accomplish being extremely weird, so my expectation is that someone else could have stumbled upon this and figured out a reasonable workaround.
 I would like to avoid setting up a watchdog timer.

Code below for example hangs when the device is powered but not connected to a PC.
Thanks

Background: https://hackaday.io/project/191762-automatic-workstation-locker

```
#include "DigiKeyboard.h"
#include "Arduino.h"

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  DigiKeyboard.update();

  DigiKeyboard.sendKeyStroke(0);
}

void loop() {
  static uint8_t bit = 0;
  bit = 1 - bit;
  digitalWrite(LED_BUILTIN, bit);
  DigiKeyboard.update();
  DigiKeyboard.sendKeyStroke(KEY_Q);
  delay(2000);
}
```

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

title: Digispark: check if the USB host is connected

Answers: 1

body:
The Digispark does not have a proper hardware USB implementation. It is possible that you simply can't do what you are attempting to do. A search I did indicated you are not the only person attempting to do this.

You may want to switch to one of the Arduinos that have a hardware USB interface like the Leonardo or Micro.

I should point out that the Digispark is not an Arduino, and it has [its own forum](http://digistump.com/board/) where you may possibly get an answer from their own community.


body:
I am having trouble uploading code to my Arduino Nano. It has been very trusty in the past, but I am getting this new error when uploading any code to it:
```avrdude: ser_open(): can't set com-state for "\\.\COM15"```

This happened a while ago on my Windows 11 Laptop, and I was unable to resolve it, and now it has just started on my Windows 10 desktop.

I tried disabling and re-enabling the CH340 in device manager, restarted my computer, and uninstalled the CH340. After uninstalling it, it has dissapeared and does not even show up in Device Manager at all.

If anybody could provide some help explaining how to make it show up in Device Manager again, and also make it uploadable, I would greatly appreciate it!

Thank you in advance

title: Arduino Nano uploading problems

Answers: 1

body:
Apparently there was an update in ch340 drivers early in 2023 and it broke something for counterfeit ch340. Solution is using older version of the driver (and possibly disabling automatic updates for the drivers in the Windows).

[Issue description and solution found on github](https://github.com/SHWotever/SimHub/wiki/Arduino---Counterfeit-Fake-CH340G-chips-driver-issues):

> Rollback to an older driver manually :
>
> Unfortunately since the incompatible driver is delivered through
> windows update it is harder to keep an older driver installed :
>
>    Recommended : Block windows drivers update so the newest driver won't get installed automatically:
> https://www.makeuseof.com/windows-stop-automatic-driver-updates (note:
> while this is required to be able to install and keep the older ch340g
> driver but this will affect any of your future devices)
>
>    Reinstall an older driver here : [01/30/2019, 3.5.2019.1 CH341SER driver](https://github.com/SHWotever/SimHub/files/11564977/CH341SER.zip)


body:
I am hoping there is a simple fix to this problem.

I am playing around with a 16x2 lcd with a I2C connector attached. I wired it up to an elegoo uno R3.

I started with some code I've used before and ended up with one row of the LCD fully lit and the other dark.

After a ton of trouble shooting, I can not get the LCD to show anything but one lit and one dark row.

[![arduino with lcd attached][1]][1]

In this image:

Power: 5V, 1.5A

| Pin | LCD | Uno |
|--|--|--|
| SCL | SCL | SCL |
| SCA | SDA | SDA |
| + | VCC | 5V |
| gnd | gnd | gnd |

I've also tried:
* putting the SDA to A4 and the SCL to A5
* Using different power supplies
* Powering from the USB connector

And I've tried several of the libraries available

They are all variations of the following from the [Adafruit_LiquidCrystal](https://github.com/adafruit/Adafruit_LiquidCrystal) library:

```
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

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

void setup()
{
 // initialize the LCD
 lcd.begin();

 // Turn on the blacklight and print a message.
 lcd.backlight();
 lcd.print("Hello, world!");
}

void loop()
{
 // Do nothing here...
}

```

No matter what I do the display does not change.

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

title: LCD I2C connection problems

Answers: 1

body:
Some common problems with LCD displays which incorporate an I2C backpack include:

1. Not using the correct I2C address for the I2C backpack. Use an I2C scanner to discover the correct address.
2. Mixing voltages without proper level shifting, say using a 5v display with a 3.3v MCU
3. Failing to adjust the contrast potentiometer
4. Some I2C backpacks may use a non-standard pin allocation which may be corrected by specifying a pin mapping in the constructor to the display library. Fortunately, this is rare.
5. Using code samples intended for a different variant of the library supporting the display. Always use a basic test sketch which is packaged with the chosen library to verify the performance of the display.


body:
[![enter image description here][1]][1]I'm new with arduino (nano). I am having problems with Servo MG90S, I cant make it move. Im doing the easiest test, Servo cables connected:

Brown -> gnd
Red -> 5v
Orange -> pin 9

my arduino code is:
```
#include <Servo.h>
Servo servo;

const int servoPin = 9;

void setup()
{
  servo.attach(servoPin);
  Serial.begin(9600);
}

void loop()
{
  servo.write(40);
  delay(2000);
  servo.write(0);
  delay(2000);
}
```
As you see its a super simple example, but the result is the servo vibrating slightly.

Extra data: the servo start vibrating with the `servo.attach(servoPin);` it doesnt matters if I set the `servo.write(40);`

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

title: Arduino Servo MG90S not moving

Answers: 2

body:
Okay, so here is the deal: I have looked up the datasheet for the Arduino Nano and the MG90S. The problem is: you may have killed your Arduino Nano. As the datasheet for the Arduino Nano says, "Max DC Current per I/O Pin... 40 mA." ([The Datasheet for Arduino Nano][1]). I am not sure if that's 100% of the issue, so, then I looked up the MG90S and it says "Current (typical during movement)... 120-250mA" ([Also, another datasheet][2]). Basically, all that means is that you *MAY* have to buy another Arduino because you may have used a servo that requires to much (for lack of a better term) "power." Using some math we see that you went approximately: 210 milli-amps over. Sorry.

  [1]: https://diyi0t.com/arduino-nano-tutorial/
  [2]: https://protosupplies.com/product/servo-motor-micro-mg90s-continuous-rotation/

body:
Okay, so my first answer is WRONG. The reason being is because the MG90S and the SG90 (which are very similar servos, except the gearing and some others) **CAN** run off that Arduino. As this article shows: [How to control the MG90S with the Nano][1]. However, it *IS* best to run that servo off a separate power supply (5V). The issue lies within your wiring. Somehow, there is some miscommunication between us, you, and the Arduino.

  [1]: https://www.hibit.dev/posts/101/how-to-control-servo-motor-with-arduino


body:
Recently I have purchased male and female USB-C breakout boards. I intend to connect the male breakout to a keyboard and the female end to my computer using a USB-C cable and wire the breakouts together using a breadboard. I was wondering if it is possible to read the keystrokes being sent across the D- and D+ lines with a micro-controller.

Here is an image of how I currently have the breakout boards setup

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

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

title: Intercepting Keyboard Data on a Micro Controller

Answers: 1

body:
It would be far far easier to [interface an Arduino to an old PS2 keyboard][1].

USB is complex.  You would have to understand [USB protocol][2], then understand the [HID (Human Interface Device) protocol][3] inside of the USB protocol.  As HID can interface a number of devices like mice and keyboards, you might have to then understand the keyboard portion of the HID protocol.

As a point of reference, commercial USB analyzers cost hundreds of dollars.  [This USB analyzer cost about $500][4].

As an alternative, have you considered an all software USB monitor? These normally reside on the same computer as the USB Device is attached to. [Wireshark][5] should be able to do this.

Also, assuming that is a [Pro Micro][6] used on the keyboard, consider adding code to its Atmel processor to send out keyboard activity on an unused pin. This approach might proved much easier then monitoring the keyboard after its data has been incorporated into the USB protocol.

  [1]: https://github.com/techpaul/PS2KeyAdvanced
  [2]: https://en.wikipedia.org/wiki/USB_communications#Protocol_layer
  [3]: https://en.wikipedia.org/wiki/USB_human_interface_device_class
  [4]: https://www.adafruit.com/product/708
  [5]: https://www.wireshark.org/
  [6]: https://www.sparkfun.com/products/12640


body:
Ok, I'm fairly new to Arduino and I'm trying to read bytes from a file in an SD card and convert to integer values (0-255).

I have a file, with 1 byte on it (128 int value, created in Python, can provide the code if necessary) and the hex dump (binary mode) is:

    xxd -b single_byte.dat
    00000000: 10000000

So far so good, right? So I was expecting to read this byte from the file (SD card) and then convert back to 128 value. This is my Arduino code:

    #include <SPI.h>
    #include <SD.h>

    // set up variables using the SD utility library functions:
    Sd2Card card;
    SdVolume volume;
    SdFile root;
    const int chipSelect = 4;

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

      delay(100);
      Serial.print("\nInitializing SD card...");

      if (!card.init(SPI_HALF_SPEED, chipSelect)) {
        Serial.println("initialization failed. Things to check:");
        Serial.println("* is a card inserted?");
        Serial.println("* is your wiring correct?");
        Serial.println("* did you change the chipSelect pin to match your shield or module?");
        while (1);
      } else {
        Serial.println("Wiring is correct and a card is present.");
      }

      // print the type of card
      Serial.println();
      Serial.print("Card type:         ");
      switch (card.type()) {
        case SD_CARD_TYPE_SD1:
          Serial.println("SD1");
          break;
        case SD_CARD_TYPE_SD2:
          Serial.println("SD2");
          break;
        case SD_CARD_TYPE_SDHC:
          Serial.println("SDHC");
          break;
        default:
          Serial.println("Unknown");
      }

      // Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
      if (!volume.init(card)) {
        while (1);
      }

      File file;
      byte one_byte;
      int dec_value;

      file = SD.open("single_byte.dat", FILE_READ);
      one_byte = file.read();
      file.close();

      dec_value = int(one_byte);

      Serial.println(dec_value, DEC);

    }

    void loop(void) {
    }

I was expecting the output to be 128.

However I get:

[![Actual output][1]][1]

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

What am I missing? (yes, I tried generating the .dat file with big-endian encoding, same result)

title: Read one byte from file and convert to decimal

Answers: 2

body:
Consider adding a call to SD.begin() as is done [in the example found on this arduino.cc web page][1].

Here's the section of the example code where SD.begin() is used:

      Serial.print("Initializing SD card...");

      if (!SD.begin(4)) {
        Serial.println("initialization failed!");
        while (1);
      }

  [1]: https://docs.arduino.cc/learn/programming/sd-guide

body:
Ok, I got it working now, here's what was happening:

Turns out the file wasn't being opened. Why? seems like there's a limitation on the filename length, I noticed this after adding the lines:

    root.openRoot(volume);
    // list all files in the card with date and size
    root.ls(LS_R | LS_DATE | LS_SIZE)

And sure enough my file was not detected as **single_byte.dat** but it was something like: **single_~.dat** so I renamed the file to **test.dat** and tada! code now works like a charm.

I guess I overlooked this restriction on the documentation, so keep this in mind when you use an SD card.

Also, make sure to check if you are really opening your file because no exception will be thrown if you reference an uninitialized file pointer I guess.

Just make sure to have:

    file = SD.open(filename, FILE_READ);
    if(file){
        // Do things here.
    }
    else{
        Serial.println("You're out of luck: Can't open file");
    }

Ok, there goes my Sunday. Thanks all for reading!!!


body:
I'm writing a library that will interface with a control unit on a refrigerator compressor pump ([QDZH35G][1]). One of the features of the control unit is that it can detect what problems it's encountering and report them via a flashing LED. Operational errors will cause the LED to flash a number of times. The number of flashes depends on what kind of operational error was recorded. Each flash will last 1/4 of a second. After the actual number of flashes, there will be a delay with no flashes, so that the sequence for each error recording is repeated every 4 seconds.

My goal (as it relates to this post) is to monitor the signal from the diagnostic lead and report what error the control unit has detected. I used my oscilloscope to monitor the diagnostic port, here are some pictures of that (fault codes 1 and 4):

[![Fault code #1][2]][3]
[![Fault code #4][4]][5]

(more photos [here][6])

So the signal looked simple and clean enough. But just to be sure, I wanted to make sure Arduino was seeing it as my Oscilloscope was. I hooked the diagnostic port up to my Arduino digital port 8 and analog pin A0 (I wanted to monitor both to decide what would be the best to use for this) and uploaded the following sketch:
```c++
#define DIGITAL_DIAGNOSTIC_PIN 8
#define ANALOG_DIAGNOSTIC_PIN A0

void setup() {
  Serial.begin(9600);
  pinMode(DIGITAL_DIAGNOSTIC_PIN, INPUT);

  Serial.println("millis,analogRead,digitalRead");
}

void loop() {
  Serial.print(millis());
  Serial.print(",");
  int currentAnalogValue = analogRead(ANALOG_DIAGNOSTIC_PIN);
  int currentDigitalValue = digitalRead(DIGITAL_DIAGNOSTIC_PIN);

  Serial.print(currentAnalogValue);
  Serial.print(",");
  // Bump binary 1 to int 1023, to make it easier to see in the logs
  Serial.print(currentDigitalValue == 0 ? 0 : 1023);

  Serial.println();
}
```
And oddly enough, the signal Arduino was giving back seemed to be all over the place for both the digital and analog pins. While there was some pattern visible it's a pretty big mess.

Then I used `CoolTerm` to monitor and export the serial data into a CSV file which I then imported into a Google Docs spreadsheet ([here][7]) to create some graphs. I captured 10+ seconds in each of the following scenarios:

 1. No fault/control (zero blinks)
 2. Fault #1 (1 blink then 4-second pause)
 3. Fault #3 (3x 0.25 second blinks separated by 0.25 seconds, then 4-second pause)

Here are the screenshots of the graphs (also in the Google spreadsheet doc and imgur gallery):

[![Graph of control scenario - no fault (zero blinks)][8]][8]
[![Graph of fault code 1][9]][9]
[![enter image description here][10]][10]

***Finally* - The question..**
Why is the data seen by Arduino seem considerably less stable than that seen by my oscilloscope? I know that when reading a signal from some sensors (pressure transducer, thermocouple, etc) you get much more accurate and consistent results by averaging the last *n* readings, but the diagnostic voltage port isn't really a "sensor", it's just a voltage reading.

Additionally, it's reading from a pump powered by a DC desktop power unit, which has very stable voltages (I only say this because I know the voltage affects the level of the peaks from the diagnostic port).

  [1]: http://www.frigochem.com/pdf/HTB1t59FHVXXXXcyXpXX.PRXFXXXU.pdf#page=6
  [2]: https://i.stack.imgur.com/TUFJGm.jpg
  [3]: https://i.stack.imgur.com/TUFJG.jpg
  [4]: https://i.stack.imgur.com/jdqR3m.jpg
  [5]: https://i.stack.imgur.com/jdqR3.jpg
  [6]: https://imgur.com/a/ZAmFXGi
  [7]: https://docs.google.com/spreadsheets/d/1IeaqH9RQtn5xjXG500wL4Sm3EI2CuzoQiU8Qc_ooYFg/edit?usp=sharing
  [8]: https://i.stack.imgur.com/4IlzS.png
  [9]: https://i.stack.imgur.com/As7Ja.png
  [10]: https://i.stack.imgur.com/0Sdyx.png

title: Inconsistent results when reading input looking for spike patterns

Answers: 1

body:
Where to start?  Your O'scope photo shows about 3 vertical divisions when the fault line is 'high'. The labelling at the bottom shows '5.00V', which I'm going to assume means '5V per vertical division'.  This would mean your 'high' voltage is about 15V, **much** too high for the 5V max input either analog or digital input on the Mega.

So, you need something like a 3:1 voltage divider just to start with.  The 'bottom' resistor on the divider will set the output impedance driving your analog (and digital) inputs, so this needs to be reasonably low (10K or so).

Before connecting the voltage divider to the Mega, look at the voltage divider output with your O'scope to verify the 'high' voltages are <= 5V. Then, and only then, connect the voltage divider output to the Mega **with the O'scope still connected**.  If you see a big drop in the 'high' voltage, it means the Mega input impedance is loading down the voltage divider output, which means the voltage divider resistor values are too high - choose lower values (same ratio of course).

The specs for the Arduino Mega show a top speed of about 10,000 readings per sec, so your loop speed should be OK as long as adjacent millisec printouts are different.

I suspect you will find that the Mega analog input is loading down the signal.


body:
I'm trying to build a pressure data logger using an Arduino and Mindman MP47P-03-F1 (https://www.mindman.com.tw/proimages/pdf/E_MP47_S.pdf) pressure sensor, the sensor is connected to an outer 12-24 VDC power source.
I've connected the analog wire to the the Arduino's A0 and added another wire from the GND to the sensor. I get a stable voltage (~1V) reading but the pressure is wrong and it doesn't respond to pressure changes.
Can someone tell me what I'm doing wrong?
this is the sample code:

    const int analogPin = A0;
    const float slope = -0.1;
    const float intercept = 0.6;
    const unsigned long startTime = millis();

    void setup() {
      Serial.begin(9600);
      Serial.println("Time (s)\t\tPressure (MPa)");
    }

    void loop() {
      unsigned long elapsedTime = millis() - startTime;
      int sensorValue = analogRead(analogPin);
      float voltage = sensorValue * (5.0 / 1023.0);
      float pressure = slope * (voltage - intercept);

      Serial.println(sensorValue);
      Serial.print(elapsedTime / 1000.0);
      Serial.print("\t\t");
      Serial.println(pressure);

      delay(1000);
    }

edit: i've changed the code to as suggested by some on the arduino forum:

    const int sensorPin = A0;
    const int offset = 201; // zero pressure adjust
    const int fullScale = 1023; // max pressure adjust
    float sensorType = 1000.0; // kPa
    float pressure; // final pressure
    const unsigned long startTime = millis();

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

    void loop() {
      unsigned long elapsedTime = millis() - startTime;
      pressure = (analogRead(sensorPin) - offset) * sensorType / (fullScale - offset);

      Serial.print(analogRead(sensorPin));
      Serial.print("\t\t");
      Serial.print(elapsedTime / 1000.0);
      Serial.print("\t\t");
      Serial.println(pressure, 4);
      delay(1000);
    }
the pressure is 0 but i keep getting jumps in the readings of the pressure when no pressure is applied. here is the picture of the wiring. [![enter image description here][1]][1]

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

title: Connecting pressure sensor to Arduino to collect pressure and time data

Answers: 1

body:
As jsotola mentions in the comments, you should definitely verify that the pressure sensor works with a multimeter first, preferably on a bench that has a variable power supply from which you can power your sensor. Make sure that you can measure the pressure you are putting into the sensor by some other means; a simple pressure gauge could work.

Then, you'll have to correct your equation - it is flipped, since the graphs show the pressure as an input and an output as a voltage, but when you're converting a voltage to a pressure, the process is flipped, so we calculate the slope as follows: take the pressure range (output) and divide it by the voltage range (input) -> 1.1 MPA / 4.4 V = 0.25 V_in. Now, we know that at 0.6V, the pressure output is -0.1 MPA, so we set up a linear equation of the form that you did -> y = mx + b and plug in the values: -0.1 MPA = 0.25 MPA/V * (0.6V) + b. If you solve for b, you'll get -0.25.

Therefore, pressure = 0.25X - 0.25 should be the equation that you check the pressure you're putting into the sensor against the voltage that you are measuring.

If you discover that with this equation you're measuring the right pressure, but once you re-implement your Arduino program you still have no luck, I'd check that the grounds are wired together correctly - it's crucial to have all of the involved grounds at the same 'level'. As a bonus, depending on the Arduino, you could utilize the chip's differential ADC channels, but as far I know, you'd have to write directly to registers to do that.


body:
I'm using a Maduino Zero 4G SIM7600 device to upload data from 28 sensors to a ThingSpeak IoT server. It works well for a few hours, then stops uploading the data. Sometimes it starts again after an inconsistent amount of time (an hour or two), sometimes it doesn't.

I can confirm that it's only the SIM7600 and/or Thingspeak functions that are failing, as the serial monitor demonstrates the other I2C related operations on the Arduino board are still working fine even when the server uploads fail.

Here's the relevant part of the code:

```
void setup(){
    SerialUSB.begin(115200);
    SerialUSB.println("Serial initialized");
    Serial1.begin(115200);
    Wire.begin();

    pinMode(LTE_PWRKEY_PIN, OUTPUT);
    digitalWrite(LTE_RESET_PIN, LOW);
    delay(100);
    digitalWrite(LTE_PWRKEY_PIN, HIGH);
    delay(2000);
    digitalWrite(LTE_PWRKEY_PIN, LOW);

    pinMode(LTE_FLIGHT_PIN, OUTPUT);
    digitalWrite(LTE_FLIGHT_PIN, LOW);//Normal Mode

    delay(5000);

    sendData("AT+CCID", 3000, DEBUG);
    sendData("AT+CREG?", 3000, DEBUG);
    sendData("AT+CGATT=1", 1000, DEBUG);
    sendData("AT+CGACT=1,1", 1000, DEBUG);
    sendData("AT+CGDCONT=1,\"IP\",\"sp.mb.com\"", 1000, DEBUG);

    delay(5000);
}

void loop(){
  getData();

  //Sensors 0-6
  http_str = "AT+HTTPPARA=\"URL\",\"https://api.thingspeak.com/update?api_key=" + Apikey1 + "&field1=" + (String)hallData[0] + "&field2=" + (String)hallData[1] + "&field3=" + (String)hallData[2] + "&field4=" + (String)hallData[3] + "&field5=" + (String)hallData[4] + "&field6=" + (String)hallData[5] + "&field7=" + (String)hallData[6] + "\"\r\n";
  SerialUSB.print("Sent to Channel 1: ");
  SerialUSB.println(http_str);
  sendData("AT+HTTPINIT\r\n", 2000, DEBUG);
  sendData(http_str, 2000, DEBUG);
  sendData("AT+HTTPACTION=1\r\n", 3000, DEBUG);
  sendData("AT+HTTPTERM\r\n", 3000, DEBUG);

  //Sensors 7-13
  http_str = "AT+HTTPPARA=\"URL\",\"https://api.thingspeak.com/update?api_key=" + Apikey2 + "&field1=" + (String)hallData[7] + "&field2=" + (String)hallData[8] + "&field3=" + (String)hallData[9] + "&field4=" + (String)hallData[10] + "&field5=" + (String)hallData[11] + "&field6=" + (String)hallData[12] + "&field7=" + (String)hallData[13] + "\"\r\n";
  SerialUSB.print("Sent to Channel 2: ");
  SerialUSB.println(http_str);
  sendData("AT+HTTPINIT\r\n", 2000, DEBUG);
  sendData(http_str, 2000, DEBUG);
  sendData("AT+HTTPACTION=1\r\n", 3000, DEBUG);
  sendData("AT+HTTPTERM\r\n", 3000, DEBUG);

  //Sensors 14-20
  http_str = "AT+HTTPPARA=\"URL\",\"https://api.thingspeak.com/update?api_key=" + Apikey3 + "&field1=" + (String)hallData[14] + "&field2=" + (String)hallData[15] + "&field3=" + (String)hallData[16] + "&field4=" + (String)hallData[17] + "&field5=" + (String)hallData[18] + "&field6=" + (String)hallData[19] + "&field7=" + (String)hallData[20] + "\"\r\n";
  SerialUSB.print("Sent to Channel 3: ");
  SerialUSB.println(http_str);
  sendData("AT+HTTPINIT\r\n", 2000, DEBUG);
  sendData(http_str, 2000, DEBUG);
  sendData("AT+HTTPACTION=1\r\n", 3000, DEBUG);
  sendData("AT+HTTPTERM\r\n", 3000, DEBUG);

  //Sensors 21-27
  http_str = "AT+HTTPPARA=\"URL\",\"https://api.thingspeak.com/update?api_key=" + Apikey4 + "&field1=" + (String)hallData[21] + "&field2=" + (String)hallData[22] + "&field3=" + (String)hallData[23] + "&field4=" + (String)hallData[24] + "&field5=" + (String)hallData[25] + "&field6=" + (String)hallData[26] + "&field7=" + (String)hallData[27] + "\"\r\n";
  SerialUSB.print("Sent to Channel 4: ");
  SerialUSB.println(http_str);
  sendData("AT+HTTPINIT\r\n", 2000, DEBUG);
  sendData(http_str, 2000, DEBUG);
  sendData("AT+HTTPACTION=1\r\n", 3000, DEBUG);
  sendData("AT+HTTPTERM\r\n", 3000, DEBUG);
}

String sendData(String command, const int timeout, boolean debug){
  String response = "";
  Serial1.println(command);

  long int time = millis();
  while ( (time + timeout) > millis()){
    while (Serial1.available()){
      char c = Serial1.read();
      response += c;
    }
  }
  if (debug){
    SerialUSB.print(response);
  }
  return response;
}
```

All SIM7600 related operations are taken directly from the Makerfabs examples, found on [this page][1]. One thing of note is that in their example, they use the command `AT+HTTPACTION=0`, which, according to [this page][2], means READ. This does work but it sometimes returns ERROR instead of OK. I've changed it to `AT+HTTPACTION=1`, which means POST, which seems to work a bit better - at least there are no ERROR messages. But the same problem still persists.

UPDATE #1: The ERROR messages sometimes return even with the `AT+HTTPACTION=1` adjustment. Something I've noticed is that generating new API keys for each of the Thingspeak pages (there are 4 in total, 7 sensors per page) causes it to work for a while when it didn't before. No explanation for why that is.

Any advice would be greatly appreciated.

Hardware wise, I'm powering this from an AC adapter through a DC-DC 5V converter. I'm also using a 3.7 battery for backup power.

  [1]: https://github.com/Makerfabs/Maduino-Zero-4G-LTE/blob/main/example/4G_HTTP_DHT11_V1.0/4G_HTTP_DHT11_V1.0.ino
  [2]: https://m2msupport.net/m2msupport/athttpaction-perform-getposthead-http-action/

title: Why does my Arduino stop uploading to the Thingspeak server after several hours?

Answers: 1

body:
From the [ThingSpeak License Options page][1]:

> ThingSpeak is available as a free service for non-commercial small projects (<3 million messages/year or ~8,200 messages/day).

Could you be hitting that limit?

  [1]: https://thingspeak.com/prices


body:
I need two Serial ports. One port is some sort of modified Software Serial, where I have to be listening constantly and send responses immediately if the port requires it. There is no XY problem hidden here, promise.

On the other hand I have a device on the hardware serial.

If I'm listening on the Software Serial, sometimes I lose data on the hardware serial. How can this be? Isn't the Hardware Serial "hardware", meaning independent of the CPU?

title: SoftwareSerial and HardwareSerial lost data

Answers: 1

body:
Software Serial turns off interrupts. Depending on the baud rate, they may be off for so long that the interrupt generated by the hardware serial is not serviced in time. Depending on the chip, the hardware serial may only have a buffer of a couple of bytes. Turn off interrupts long enough and one will be lost.

The external interrupts are higher priority than the UART interrupts, which won't help. I am referring to the Uno here.

**It would help** in future if you provide code to reproduce the situation, and also state what Arduino you are using. The lack of information about that in the question would be why you were downvoted.


body:
The HardwareSerial requires to run an interrupt to store received bytes in the buffer. Look at [this][1] file from the Arduino Core.
If I am now constantly receiving and writing on the Software Serial, the data from the HardwareSerial cannot be buffered, since external interrupts are higher priority.

In my application, I need to constantly listen to the SoftwareSerial and respond immediately to incoming data (actually inside the receive interrupt of the SoftwareSerial, so its modified), so the SoftwareSerial has higher priority. But when I do this, I lose data on the HardwareSerial.

Is there any way to circumvent this limitation, without disabling any interrupts or getting a chip with more UART ports?

EDIT: the actual interrupt vector is [here][2]

EDIT2: This is question is not answered by the answers in my previous question. It is clearly a fact that HardwareSerial needs its receive interrupt to store data in a buffer. My question now is how I can still use the SoftwareSerial while it is constantly receiving.

  [1]: https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/HardwareSerial_private.h
  [2]: https://github.com/arduino/ArduinoCore-avr/blob/eabd762a1edcf076877b7bec28b7f99099141473/cores/arduino/HardwareSerial0.cpp

title: HardwareSerial and SoftwareSerial not compatible

Answers: 1

body:
If you are sending something in SoftwareSerial ISR handler that means ISRs are disabled and you are blocking other ISRs being called (if needed).

If you're using some crazy slow baudrate like 9600 then it means over 1 millisecond per character sent and during that time you might be missing other interrupts calls (millis, HW serials). If there is only one character, it's not problem, it'll be handled after interrupts are enabled again, but if there will be second or more character, previous are lost, as the've never been readed out from the UDR register (that should set flag for buffer overrun or how it's called).

If your Hw serial has some nice speed like 115200, you can lose up to 12 characters during sending single characted on software serial with speed 9600

The cli() in [software serial library](https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/SoftwareSerial/src/SoftwareSerial.cpp#L436C22-L436C22) but as you wrote it's called from ISR handler and the ISRs are disabled anyway already during whole ISR handler


body:
When i was testing out a program I found a strange behavior of esp8266

It seems to get out of a while loop even when there's no option of getting out on code

I don't know if these are related but here's the code
(the program is just two different visual patterns of leds toggled by a button)
```
#define led1 D0
#define led2 D1
#define led3 D2
#define led4 D3
#define button D7

unsigned long pressedButton;
bool change = 0;
unsigned long previousTime;
unsigned int difference;

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(button, INPUT_PULLUP);
}

void loop(){
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);
  digitalWrite(led3, LOW);         //when the while loop change, this should delete interference
  digitalWrite(led4, LOW);
  previousTime = millis();

  while (!change){                                      //default visual pattern of leds
    difference = millis()-previousTime;

    if (!digitalRead(led1) && difference>=200){
      digitalWrite(led1, HIGH);
    }
    if (!digitalRead(led2) && difference>=400){
      digitalWrite(led2, HIGH);
    }
    if (!digitalRead(led3) && difference>=600){
      digitalWrite(led3, HIGH);
    }
    if (!digitalRead(led4) && difference>=800){         //after here, all the leds should be HIGH
      digitalWrite(led4, HIGH);
    }
    if (digitalRead(led4) && difference>=1000){
      digitalWrite(led4, LOW);
    }
    if (digitalRead(led3) && difference>=1200){
      digitalWrite(led3, LOW);
    }
    if (digitalRead(led2) && difference>=1400){
      digitalWrite(led2, LOW);
    }
    if (digitalRead(led1) && difference>=1600){        //after here, all the leds should be LOW
      digitalWrite(led1, LOW);
      previousTime = millis();
    }

    if (!digitalRead(button) && millis()-pressedButton>200){       //check if button was pressed to break while loop
      pressedButton = millis();
      break;
    }
  }

  while (change){                                         //alternative of visual pattern of leds
    difference = millis()-previousTime;

    if (!digitalRead(led1) && difference>=200){
      digitalWrite(led1, HIGH);
      digitalWrite(led4, HIGH);
      digitalWrite(led2, LOW);
      digitalWrite(led3, LOW);
    }
    if (digitalRead(led1) && difference>=400){
      digitalWrite(led1, LOW);
      digitalWrite(led4, LOW);
      digitalWrite(led2, HIGH);
      digitalWrite(led3, HIGH);
      previousTime = millis();
    }

    //if (!digitalRead(button) && millis()-pressedButton>=200){     //check if button was pressed to break while loop
    //  pressedButton = millis();
    //  break;
    //}
  }

  change = !change;         //after a break in one of the while loops, this will make the program go to the other while loop
 }

```
Is there something wrong with the code?
Here is a link of a video of the behavior for more details
https://drive.google.com/file/d/1822MHNGQn-A2-HGHhRXz_8xydz-wM4Ha/view?usp=sharing

title: ESP8266 seems to be killing a while loop

Answers: 1

body:
You can't trap an ESP in a while loop like that. There are things it needs to get back to main and do between loops. Instead, let the loop function be your loop. Make the while statements if statements and where you have break, that's where you change the change variable. Put the code at the top in an if statement that checks to see if change has changed.

    #define led1 D0
    #define led2 D1
    #define led3 D2
    #define led4 D3
    #define button D7

    unsigned long pressedButton;
    bool change = 0;
    bool oldChange = 1;
    unsigned long previousTime;
    unsigned int difference;

    void setup() {
      pinMode(led1, OUTPUT);
      pinMode(led2, OUTPUT);
      pinMode(led3, OUTPUT);
      pinMode(led4, OUTPUT);
      pinMode(button, INPUT_PULLUP);
    }

    void loop() {
      if (change != oldChange) {
        digitalWrite(led1, LOW);
        digitalWrite(led2, LOW);
        digitalWrite(led3, LOW);  //when the while loop change, this should delete interference
        digitalWrite(led4, LOW);
        previousTime = millis();
        oldChange = change;
      }

      if (!change) {  //default visual pattern of leds
        difference = millis() - previousTime;

        if (!digitalRead(led1) && difference >= 200) {
          digitalWrite(led1, HIGH);
        }
        if (!digitalRead(led2) && difference >= 400) {
          digitalWrite(led2, HIGH);
        }
        if (!digitalRead(led3) && difference >= 600) {
          digitalWrite(led3, HIGH);
        }
        if (!digitalRead(led4) && difference >= 800) {  //after here, all the leds should be HIGH
          digitalWrite(led4, HIGH);
        }
        if (digitalRead(led4) && difference >= 1000) {
          digitalWrite(led4, LOW);
        }
        if (digitalRead(led3) && difference >= 1200) {
          digitalWrite(led3, LOW);
        }
        if (digitalRead(led2) && difference >= 1400) {
          digitalWrite(led2, LOW);
        }
        if (digitalRead(led1) && difference >= 1600) {  //after here, all the leds should be LOW
          digitalWrite(led1, LOW);
          previousTime = millis();
        }

        if (!digitalRead(button) && millis() - pressedButton > 200) {  //check if button was pressed to break while loop
          pressedButton = millis();
          change = true;
        }
      }

      if (change) {  //alternative of visual pattern of leds
        difference = millis() - previousTime;

        if (!digitalRead(led1) && difference >= 200) {
          digitalWrite(led1, HIGH);
          digitalWrite(led4, HIGH);
          digitalWrite(led2, LOW);
          digitalWrite(led3, LOW);
        }
        if (digitalRead(led1) && difference >= 400) {
          digitalWrite(led1, LOW);
          digitalWrite(led4, LOW);
          digitalWrite(led2, HIGH);
          digitalWrite(led3, HIGH);
          previousTime = millis();
        }
      }

      change = false
    }


body:
This is puzzling me: if I power my Arduino IoT 33 Board from USB, everything runs smoothly. Now, if I power it with 5V on Vin, the board resets as soon as I call WiFiNINA's `WiFi.begin(ssid, pass)`.

Of course, power is my first suspect as I'd imagine that wifi connections draw lots of current. But what's intriguing is that the main power source is a 5V (10A) DC source that is powered by a 24V (20A) AC/DC converter. The Arduino connects to 3 I2C components (an  128x128 monochrome OLED, an INA219, and an Adafruit PWM multiplexer). There are 2 servos connected to the multiplexer. Here's the wiring diagram:

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

With this setup, INA219 reads 4.8V and about 100mA when both servos are moving (85mA in rest).

An important remark: the PCA9685 multiplexer has a separate V+ just to drive the servos. I was assuming that my power source is enough to drive all of this, so I didn't bother supplying a separate power source for it (btw, there's an additional 680uF capacitor on soldered the board). Just for debugging purposes I did try a separate power source for it, but the problem persists.

Here some data sheets: [24V power source][2], [DC-DC Converter (D24-S5)][3], [OLED][4], [PWM Multiplexer][5], [INA219][6].

Finally, here's the setup code:

    void setup() {
      delay(250);
      Wire.begin();

      // Check for the screen module
      if (!display.begin(SCREEN_ADDRESS, true)) {
        // don't continue
        while (true)
          ;
      }

      // Check for the PWM module
      pwm.begin();
      pwm.setOscillatorFrequency(27000000);
      pwm.setPWMFreq(50);
      // Setting servos to midpoint
      pwm.setPWM(0, 0, SERVO_START);
      pwm.setPWM(1, 0, SERVO_START);
      display_line_2 = (String) "PWM... Ok";
      printDisplay(1);
      delay(10);

      // Check for the INA219 module
      if (!ina219.begin()) {
        display_line_3 = (String) "INA219... Fail";
        printDisplay(1);
        // don't continue
        while (true)
          ;
      }

      // Check for the internal LM module
      if (!IMU.begin()) {
        display_line_4 = (String) "IMU... Failed";
        printDisplay(1);
        // don't continue
        while (true)
          ;
      }

      // check for the WiFi module:
      if (WiFi.status() == WL_NO_MODULE) {
        display_line_5 = (String) "Wifi... Failed";
        printDisplay(1);
        // don't continue
        while (true)
          ;
      } else {
          while (status != WL_CONNECTED) {
          // Connect to WPA/WPA2 network:
          status = WiFi.begin(ssid, pass);
          // wait 10 seconds for connection:
          delay(5000);
        }
      }
    }

As I said, if I comment the line `status = WiFi.begin(ssid, pass)`, everything works just fine. So my question is: where the problem likely is? What would be the next step to troubleshoot it?

  [1]: https://i.stack.imgur.com/eNVcR.png
  [2]: https://support.industry.siemens.com/cs/pd/648665?pdti=td&dl=en&lc=en-GB
  [3]: https://www.mouser.co.uk/datasheet/2/670/pqae50_din-2474595.pdf
  [4]: https://cdn-shop.adafruit.com/product-files/5297/ZJY-2828TSWIG01.pdf
  [5]: https://learn.adafruit.com/16-channel-pwm-servo-driver/downloads
  [6]: https://learn.adafruit.com/adafruit-ina219-current-sensor-breakout/downloads

title: WiFiNINA Reseting Arduino Nano IoT 33 When Powered Externally

Answers: 0


body:
I need to support 18 push buttons and 66 IR sensors on my Arduino Mega (model railway). I have a Mega Sensor Shield, but won't have enough pins for all the sensors. Can I get a second sensor shield and nest it some way?

https://www.aliexpress.com/item/1005004554959620.html?spm=a2g0o.order_list.order_list_main.31.1cda18022wJnOM

title: Stack Mega Shield

Answers: 2

body:
I may be interpreting your question wrong, but it seems that you're asking if you can somehow get more input pins for your sensor (general-purpose input/output), with which your sensor shield will not help with that. If you want to get more inputs for your sensors, you'll need to use shift registers.

[Link to understanding how to add more digital GPIO pins][1]

  [1]: https://www.digikey.com/en/maker/blogs/2022/how-to-add-more-digital-gpio-pins-to-arduino-projects-using-shift-registers#:~:text=Using Shift Registers to Add,inputs of the register IC.

body:
For a model railway, this may not work as well as you are expecting. Sending 66 sensors values and 18 push-buttons along long cable lengths, as may be expected for a model railway, could introduce noise which would give bogus readings. The noise in long, adjacent, cables could be from one cable inducing a voltage in its neighbour, or simply from the railway operations themselves.

It may be better to use something like [RS485](https://en.wikipedia.org/wiki/RS-485) which is a balanced protocol. That is, of the two data wires connecting nodes, one is positive and one is negative simultaneously, for a signal to be considered genuine. Noise would tend to influence the cables in the same direction (eg. both positive) and would thus be discarded.

As described in the [Wikipedia article](https://en.wikipedia.org/wiki/RS-485), RS485 is used in aircraft for reliability. The wiring is minimal: two wires for data, plus an earth wire. You would also need 5V power available at the nodes.

What I would suggest here is a series of nodes, spread around your railway layout. Each node could be an inexpensive Atmeg328P processor (around $3 on eBay) with a couple of supporting resistors and capacitors. You would use 3 pins for the RS485 (transmit, receive and enable) which would leave 17 inputs for your sensors and switches per node. Thus, around 5 nodes.

You would keep the cabling for the sensors running to each node as short as possible, to reduce noise. Maybe use shielded cable.

I wrote an [RS485 non-blocking library](https://github.com/nickgammon/RS485_non_blocking) - available on Github.

There are some explanations about using it [on my website](https://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=11428) most of which is also on the Github page.

Basically what you would do is give each node an address (stored in EEPROM) and then have a master query each node in turn for the values on its sensors or switches. The node would reply, and then the master could move onto the next one.

---

I realise this isn't directly answering the question about the Mega shield, but I am trying to answer the underlying problem of how to connect 84 sensors and switches to one Arduino reliably.


body:
I am using the `sim800l gsm module` with `nodemcu esp8266` and comunicating with it using AT+ commands. The module is working correctly but I am trying to use the command `AT+CLCC` to get all the current calls' state but it responds with only the first call information and a part of the second call.

This is the response while there are two active calls
```
15:37:19.156 -> AT+CLCC
15:37:19.156 -> +CLCC: 1,0,1,0,0,"+0123456789",145,"name"
15:37:19.156 ->
15:37:19.156 -> +CLCC: 2,
```
I think it is the Serial buffer's problem because the size of the serial buffer is 64 bytes and the response is more than that but I don't know how to handle that

I hope someone can help.

EDIT: this is the code i am using

```
#include <SoftwareSerial.h>
#include <cstring>

#include <Arduino.h>

#define simTX D3
#define simRX D4

SoftwareSerial sim800l(simRX, simTX);  //RX, TX

void setup() {

  Serial.begin(115200);  //Begin serial communication with Arduino and Arduino IDE (Serial Monitor)

  sim800l.begin(115200);  //Begin serial communication with Arduino and SIM800L

}

void loop() {

  updateSerial();

}

//Start
// this method takes input from the serial monitor the pass it to sim800l via serial communication
void updateSerial() {
  delay(500);
  while (Serial.available()) {
    sim800l.write(Serial.read());  //Forward what Serial received to Software Serial Port
  }
  while (sim800l.available()) {
    Serial.write(sim800l.read());  //Forward what Software Serial received to Serial Port
  }
}
//End
```

title: sim800l gsm module response isn't completed

Answers: 1

body:
Just for someone in the future who is having the same issue.

the problem was because of the boadrate 115200 is pretty fast for a software serial implementation so i just changed it to 9600

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

good luck from the past :)


body:
**I understand that** the Arduino is generally not fast or powerful enough to generate a suitable VGA/HDMI signal with higher resolution.

However, I've noticed that there are **inexpensive PC graphics cards** available that can easily maintain a stable screen on a monitor.

----

Back in the DOS era, it was relatively straightforward to write a short program that could output text to CGA/EGA/VGA cards using BIOS calls and a few assembly instructions. The BIOS itself surely was not overly complex or large.

---

So my idea is to take an Arduino, use shift registers like the 74HC595 to create a sufficiently long bus, and connect it to a cheap, obsolete GPU (e.g., an NVIDIA card from a discarded PC) along with a regular monitor. I would then write Arduino code to emulate a BIOS call, such as 10h, which would shift out the "bus status" to the 74HC595s, send the signal to the GPU, and continue this process until the characters are transferred to the GPU.

The GPU can easily generate VGA/HDMI signals and work with any modern monitor. It also has enough memory to support screen resolutions like 80x25, 80x50, or even 132x60 for text-based displays. In fact, it might even be possible to run at full graphical resolutions such as 640x480 or even 2560x1440, with the Arduino slowly sending graphic primitives to display.

While the GPU's performance would be severely degraded, it would still be a better alternative than throwing it away.

-----

**My question** is whether it is possible or even feasible to connect a GPU to such a slow source. If it is, I would like to know if there are any readily available and understandable documentation or even someone who has already attempted this approach.

(Or should I post it somwere else? Where?)

title: Connecting Arduino to a cheap Graphics Card for VGA Output

Answers: 1

body: This doesn't answer your question about the cheap graphics card, but see https://forum.arduino.cc/t/toorums-quest-ii-atmega328p-based-retro-video-game-with-256-color-graphics/192920 for where Petri Häkkinen did an arcade-style game with an Atmega328 and the AD725 chip for generating the VGA signal.


body:
This is my first project working with stepper motors, so I may have a bit of a shaky understanding of the electronic side of the project. I'm trying to create a simple device with 4 buttons connected to a stepper motor driver/NEMA 17 motor, with the ability to increase/decrease RPM, switch motor spin direction, and run the motor with the button being held down. (LCD screen included for output as well)

I'm noticing that when changing the RPM on my motor, i.e. from 3.2 to 3.1 to 3.0, the speed of the motor is really slow, then when set to 3.0, suddenly increases a lot, but goes down when setting the RPM back down to 2.8 or so. This occurs multiple times along different intervals of RPMs that I have tested as well.

I think that there may be an issue with the method with which I am calculating the pulse delay given the RPM in my function `setRPM()` at the end of my code or with the way that I am micro-stepping, which I am doing because I need extremely precise movement.

Included below is the code that I used to run with my TMC2208 driver. (Sorry if it is rather long, but I included comments to document my thought process when programming the Arduino.)

Included list of RPMs and pulse delays

| rpm | pulse_delay (us)   |
|:---:|:------------------:|
| 1   | 37500 (too fast)   |
| 2   | 18750 (too fast)   |
| 2.25| 16666.6667 (works) |
| 2.5 | 15000  (works)     |
| 3   | 12500  (works)     |
| 5   | 7500   (works)     |
| 10  | 3759   (works)     |

```c
// Stepper motor run code with TMC2208 driver and LCD code
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Stepper.h>
// Define Pins for Step Motor Driver
#define stepPin 7  // define pin for step
#define dirPin 8   // define pin for direction
#define enPin 9    // define pin for enable ^^ Do I need this?

// Define Buttons for Speed and Direction
#define buttGo 10      // define pin for button input
#define buttSwitch 11  // define pin for button input
#define incSpeed 12    // define button for increasing speed
#define decSpeed 13    // define button for decreeasing speed

// Define LCD pinout
const int en = 2, rw = 1, rs = 0, d4 = 4, d5 = 5, d6 = 6, d7 = 7, bl = 3;  // Adapter Pinout
const int i2c_addr = 0x27;                                                 // Adapter pinout
LiquidCrystal_I2C lcd(i2c_addr, en, rw, rs, d4, d5, d6, d7, bl, POSITIVE);

/* Formulas for determining RPM
Assuming one step per pulse, delay is: wait = (μs/min)*(1/rpm)*(1/pulses per revolution) - overhead
Overhead = extra time it takes to run digitalWrite twice and loop
RPM = (steps per second)/(steps per revolution) * (60 seconds/minute)
step angle = 1.8 degrees ; 200 steps per revolution ; .005 revolutions per step
Solving for Steps Per Second: SPS = (RPM)/((REV_P_STEP)*(60 sec/min))

According to Notes:
  C0 = 15 * M_PI ; Motor X Circumference
  XSPR = 1 * (200 * 11) ; Motor X Steps per Rotation
  dVx = dS * (XSPR/C0) ; Desired X-Axis time from mm/s to x-axis steps/sec (dS represents desired x-axis speed)
  Assuming we use a button/knob, each increment/decrement would change the mm/s by 0.1
  So, to get the necessary pulse delay, increment/decrement by:
    dVx = 0.1 * (1 * (200 * 11))/(15*M_PI)

  Example: If we have an initial target rpm of 10, that gives us a dS of 10
  As such, dVx which is our speed in steps will be 10 * (1 * (200 * 11)) / (15 * M_PI)
  All of these variables are set globally
  wait = (microsecondsPminute)*(1/RPM)*(1/pulsesPrevolution) - overhead
  rpm / 60 = rps
  60 / rpm = spr
  (60 / rpm)/360 = spd
  ((60 / rpm)/360) * 1.8 = sps
***
Frequency = (RPM)/((Resolution/360)*60)
Resolution =  360/(Steps/Revolution)
For us, Resolution = 360/(200); so Resolution = 1.8**
Frequency = (RPM)/(0.005 * 60) = RPM/(0.3)
*
T_inc = incremental torque produced with each microstep
T_hfs = holding torque (full-step operation)
SDR = step division ratio (number of microsteps per full step)

T_inc = T_hfs * sin(90/SDR)
T_inc = 0.14 * sin(90/256)
T_inc = 0.00085902385
*/
float resolution = 1.8;
float rpm = 10;
float pulse_delay;  // Temporary starting value that will change after void setup
bool buttonState = false;
bool onState = false;

// Set up output types
void setup() {
  Serial.begin(9600);  // Change this baud rate to whatever rate the LCD screen runs on - should generally be 9600
  // Set up LCD screen
  pulse_delay = setRPM(rpm, resolution);
  lcd.begin(16, 2);  // set up the LCD's number of columns and rows:
  lcd.setCursor(0, 0);
  lcd.print("Current RPM: ");
  lcd.setCursor(12, 0);
  lcd.print(rpm);
  lcd.setCursor(0, 1);
  lcd.print("MOVE RIGHT");

  // Sets up buttons
  pinMode(buttSwitch, INPUT);
  pinMode(buttGo, INPUT);
  pinMode(incSpeed, INPUT);
  pinMode(decSpeed, INPUT);

  // Establish initials
  pinMode(enPin, OUTPUT);
  digitalWrite(enPin, HIGH);  // deactivate driver
  pinMode(dirPin, OUTPUT);
  digitalWrite(dirPin, HIGH);
  pinMode(stepPin, OUTPUT);
  digitalWrite(enPin, LOW);  // activates driver
}

// Revolutions per second should be able specified to the tenths
// Run code to continual
void loop() {
  // Read Buttons Being Pressed
  int pressSwitch = digitalRead(buttSwitch);
  int pressGo = digitalRead(buttGo);
  int pressInc = digitalRead(incSpeed);
  int pressDec = digitalRead(decSpeed);
  pulse_delay = setRPM(rpm, resolution);  //pulse_delay = (rpm * 200)/60;

  if (pressSwitch == HIGH)  // Moves motor Right (Counter-Clockwise)
  {
    if (buttonState == 0) {
      digitalWrite(dirPin, LOW);  // sets direction of the motor turning
      buttonState = 1;
      lcd.setCursor(0, 1);
      lcd.print("MOVE  LEFT");
      delay(500);
    }
    else {
      if (buttonState == 1) {
        digitalWrite(dirPin, HIGH);  // sets direction of the motor turning
        buttonState = 0;
        lcd.setCursor(0, 1);
        lcd.print("MOVE RIGHT");
        delay(500);
      }
    }
  }

  if (pressGo == HIGH)  // Moves motor
  {
    digitalWrite(stepPin, HIGH);  // This LOW to HIGH change is what creates the "Rising Edge" so the easydriver knows when to step.
    delayMicroseconds(pulse_delay);
    digitalWrite(stepPin, LOW);
  }

  if (pressInc == HIGH)  // Increases RPM
  {
    rpm = rpm + 0.1;
    delay(150);
    lcd.setCursor(12, 0);
    lcd.print(rpm);
  }

  if (pressDec == HIGH)  // Decreases RPM
  {
    rpm = rpm - 0.1;
    delay(150);
    lcd.setCursor(12, 0);
    lcd.print(rpm);
  }
}

// Function to get pulse delay time based off of inputted RPM value
float setRPM(float rpm, float resolution) {
  /*
  float temper = ((60 / rpm) / 360);
  float pulsetime = ((temper * resolution) * 1000000);
  1 rpm = 37500 us delay (too fast)
  2 rpm = 18750 us delay (too fast)
  2.25 rpm = 16666.6667 us delay
  2.5 rpm = 15000 us delay
  3 rpm = 12500 us delay
  5 rpm = 7500 us delay
  10 rpm = 3750 us delay
  */
  unsigned int pulsetime = (60000000 / (1600 * rpm));
  return pulsetime;  // Converts to microseconds
}
```

title: TMC2208 Stepper Motor does not change its RPM linearly

Answers: 2

body:
[The documentation][1] says:

> Currently, the largest value that will produce an accurate delay is 16383; larger values can produce an extremely short delay.

The value given to `delayMicroseconds()` seems to be processed by a modulo 16384 operation. That means that the value is divided by 16384, and the remainder of this division is the effective delay in microseconds.

If we apply this to the delays in your table, we get:

|desired rpm|calculated delay (µs)|effective delay (µs)|effective rpm|
|-|-|-|-|
|1|37500|4732|7.9|
|2|18750|2366|15.8|
|2.25|16666|16666|2.25|
|2.5|15000|15000|2.5|
|3|12500|12500|3|
|5|7500|7500|5|
|10|3750|3750|10|

One possible solution is presented in the same documentation:

> For delays longer than a few thousand microseconds, you should use `delay()` instead.

You might want to consider to use both functions, depending on the necessary delay.

---

And then there is the other issue with the time when the output is low. Currently, it is determined by the time the code takes to quit `loop()`, do its internal looping, call `loop()` and your statements until the pin goes high again.

You might want to divide the pulse period in two halves and take control of this low phase, too.

  [1]: https://www.arduino.cc/reference/en/language/functions/time/delaymicroseconds/

body:
For reference for any future readers who have had similar problems using a TMC2208 Stepper Motor - I have attached my annotated code to this answer for your use. In the annotation, I also include equations that can be used to determine spacings for a coiling setup.

```
// Stepper motor run code with A4988 driver and LCD code
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <Stepper.h>
// Define Pins for Step Motor Driver
#define stepPin 7  // define pin for step
#define dirPin 8   // define pin for direction
#define enPin 9    // define pin for enable ^^ Do I need this?

// Define Buttons for Speed and Direction
#define buttGo 10      // define pin for button input
#define buttSwitch 11  // define pin for button input
#define incSpeed 12    // define button for increasing speed
#define decSpeed 13    // define button for decreeasing speed

// Define LCD pinout
const int en = 2, rw = 1, rs = 0, d4 = 4, d5 = 5, d6 = 6, d7 = 7, bl = 3;  // Adapter Pinout
const int i2c_addr = 0x27;                                                 // Adapter Pinout
LiquidCrystal_I2C lcd(i2c_addr, en, rw, rs, d4, d5, d6, d7, bl, POSITIVE);

/* Formulas for determining RPM
Assuming one step per pulse, delay is: wait = (μs/min)*(1/rpm)*(1/pulses per revolution) - overhead
Overhead = extra time it takes to run digitalWrite twice and loop
RPM = (steps per second)/(steps per revolution) * (60 seconds/minute)
step angle = 1.8 degrees ; 200 steps per revolution ; .005 revolutions per step
Solving for Steps Per Second: SPS = (RPM)/((REV_P_STEP)*(60 sec/min))

According to John Craig:
  C0 = 15 * M_PI ; Motor X Circumference
  XSPR = 1 * (200 * 11) ; Motor X Steps per Rotation
  dVx = dS * (XSPR/C0) ; Desired X-Axis time from mm/s to x-axis steps/sec (dS represents desired x-axis speed)
  Assuming we use a button/knob, each increment/decrement would change the mm/s by 0.1
  So, to get the necessary pulse delay, increment/decrement by:
    dVx = 0.1 * (1 * (200 * 11))/(15*M_PI)

  Example: If we have an initial target rpm of 10, that gives us a dS of 10
  As such, dVx which is our speed in steps will be 10 * (1 * (200 * 11)) / (15 * M_PI)
  All of these variables are set globally
  wait = (microsecondsPminute)*(1/RPM)*(1/pulsesPrevolution) - overhead
  rpm / 60 = rps
  60 / rpm = spr
  (60 / rpm)/360 = spd
  ((60 / rpm)/360) * 1.8 = sps
***
*Assume from measured diameter with calipers that it is 12 mm (Check 11.85 as well)
To get Spacings: V_extruder / RPM_rod
V_extruder = M_PI * Diam_extruder * RPM_extruder (in (mm*rev)/min)
RPM_rod = 13 rpm (set from original bought parts)
V_extruder = M_PI * 12 mm * X
Spacing = (M_PI * 12 * X) / 9.64507699 RPM
Spacing = 3.90863773 * X
For Spacings of 3 mm... 0.76753084 rev/min ~= 0.77 rev/min
For Spacings of 5 mm... 1.27921807 rev/min ~= 1.28 rev/min
For Spacings of 7 mm... 1.79090529 rev/min ~= 1.79 rev/min
*
y = 1.0715x + 2.6653
y = Voltage Setting
x = RPM
For Voltage Setting of 13, RPM = 9.64507699

T_inc = incremental torque produced with each microstep
T_hfs = holding torque (full-step operation)
SDR = step division ratio (number of microsteps per full step)

T_inc = T_hfs * sin(90/SDR)
T_inc = 0.14 * sin(90/256)
T_inc = 0.00085902385
*/
float resolution = 1.8;
float rpm = 3;
unsigned int pulse_delay;  // Temporary starting value that will change after void setup
bool buttonState = false;
bool onState = false;

// Set up output types
void setup() {
  Serial.begin(9600);  // Change this baud rate to whatever rate the LCD screen runs on - should generally be 9600
  // Set up LCD screen
  pulse_delay = setRPM(rpm);
  lcd.begin(16, 2);  // set up the LCD's number of columns and rows:
  lcd.setCursor(0, 0);
  lcd.print("Current RPM: ");
  lcd.setCursor(12, 0);
  lcd.print(rpm);
  lcd.setCursor(0, 1);
  lcd.print("MOVE RIGHT");

  // Sets up buttons
  pinMode(buttSwitch, INPUT);
  pinMode(buttGo, INPUT);
  pinMode(incSpeed, INPUT);
  pinMode(decSpeed, INPUT);

  // Establish initials
  pinMode(enPin, OUTPUT);
  digitalWrite(enPin, HIGH);  // deactivate driver
  pinMode(dirPin, OUTPUT);
  digitalWrite(dirPin, HIGH);
  pinMode(stepPin, OUTPUT);
  digitalWrite(enPin, LOW);  // activates driver
}

// Revolutions per second should be able specified to the tenths
// Run code to continual
void loop() {
  // Read Buttons Being Pressed
  int pressSwitch = digitalRead(buttSwitch);
  int pressGo = digitalRead(buttGo);
  int pressInc = digitalRead(incSpeed);
  int pressDec = digitalRead(decSpeed);
  pulse_delay = setRPM(rpm);  //pulse_delay = (rpm * 200)/60;

  if (pressSwitch == HIGH)  // Moves motor Right (Counter-Clockwise)
  {
    if (buttonState == 0) {
      digitalWrite(dirPin, LOW);  // sets direction of the motor turning
      buttonState = 1;
      lcd.setCursor(0, 1);
      lcd.print("MOVING  LEFT");
      delay(500);
    } else {
      if (buttonState == 1) {
        digitalWrite(dirPin, HIGH);  // sets direction of the motor turning
        buttonState = 0;
        lcd.setCursor(0, 1);
        lcd.print("MOVING RIGHT");
        delay(500);
      }
    }
  }
// Both of the next functions move the motor, but switches between Microseconds and Milliseconds in delay time to fit.
  if (pressGo == HIGH && pulse_delay >= 16383)  // Moves motor
  {
      digitalWrite(stepPin, HIGH);  // This LOW to HIGH change is what creates the "Rising Edge" so the easydriver knows when to step.
      delay(pulse_delay/1000);
      digitalWrite(stepPin, LOW);
  }

  if (pressGo == HIGH && pulse_delay < 16383)
  {
      digitalWrite(stepPin, HIGH);  // This LOW to HIGH change is what creates the "Rising Edge" so the easydriver knows when to step.
      delayMicroseconds(pulse_delay);
      digitalWrite(stepPin, LOW);
  }

  if (pressInc == HIGH)  // Increases RPM
  {
    rpm = rpm + 0.01;
    delay(150);
    lcd.setCursor(12, 0);
    lcd.print(rpm);
  }

  if (pressDec == HIGH)  // Decreases RPM
  {
    rpm = rpm - 0.01;
    delay(150);
    lcd.setCursor(12, 0);
    lcd.print(rpm);
  }
}

// Function to get pulse delay time based off of inputted RPM value
float setRPM(float rpm) {
  /*
  float temper = ((60 / rpm) / 360);
  float pulsetime = ((temper * resolution) * 1000000);
  1 rpm = 37500 us delay (too fast)
  2 rpm = 18750 us delay (too fast)
  2.25 rpm = 16666.6667 us delay
  2.5 rpm = 15000 us delay
  3 rpm = 12500 us delay
  5 rpm = 7500 us delay
  10 rpm = 3750 us delay
  */
  unsigned int pulsetime = (60000000 / (1600 * rpm));
  return pulsetime;  // Converts to microseconds
}

```


body: I'm planning to use Arduino UNO to do some measurements and record it in a SD card module. The measurements is going to last for a year or 20 month. I need some advice on how to estimate how long can the SD card storage last without overflow. Right now I'm doing measurements every second, each second contains 13 lines of data, each line is roughly 30 characters. How big is the txt file gonna be if I left the Arduino unit recording for a year?

title: How to estimate the storage room for txt file when writing data to SD card module?

Answers: 2

body:
This is just a multiplication problem.

13 lines times 30 characters is 390 bytes per measurement.

There are 86400 seconds in one day.

86400 * 390 = 33,696,000

So that's around 34 megabytes per day.

After 1 year it would be:

365 * 33.696 = 12299 MB or a little more than 12 GB.

body: What type of SD card are you using? Based on the capacity, you can calculate SD card storage time to overflow with data/second. Since a character has a size of one byte, the amount of data used per day should be 30 * 13 * 86400 (sec/day) = 33696000 bytes or 0.033696 gb per day.


body:
I am trying to set up a weather station, and I should just have the anemometer left. This code works fine (as far as I know).

    // Pin definitions
    const int reedSwitchPin = 2;

    // Variables
    volatile unsigned long lastRotationTime = 0;
    volatile float windSpeed = 0.0;
    const float windSpeedFactor = 2.4; // Factor to convert rotation time to wind speed

    void setup() {
      pinMode(reedSwitchPin, INPUT_PULLUP);
      // attachInterrupt(digitalPinToInterrupt(reedSwitchPin), handleRotation, FALLING);
      Serial.begin(9600);
      Serial.println("hello world!");
    }

    void loop() {
      // Test reed switch functionality
      int reedState = digitalRead(reedSwitchPin);
      if (reedState == HIGH) {
        Serial.println("Reed switch triggered!");
      }

      // Calculate wind speed based on the time between rotations
      unsigned long elapsedTime = micros() - lastRotationTime;
      if (elapsedTime > 0) {
       windSpeed = windSpeedFactor / (float)elapsedTime;
      }

      Serial.print("Wind Speed: ");
      Serial.print(windSpeed);
      Serial.println(" m/s");

      delay(1000); // Delay for 1 second before measuring again
    }

    void handleRotation() {
      // Record the time of the last rotation
      lastRotationTime = micros();

    }

But when I uncomment the following line:  `attachInterrupt(digitalPinToInterrupt(reedSwitchPin), handleRotation, FALLING);`

it prints garbage characters on the serial monitor. Here is the full code:

        // Pin definitions
    const int reedSwitchPin = 2;

    // Variables
    volatile unsigned long lastRotationTime = 0;
    volatile float windSpeed = 0.0;
    const float windSpeedFactor = 2.4; // Factor to convert rotation time to wind speed

    void setup() {
      pinMode(reedSwitchPin, INPUT_PULLUP);
      attachInterrupt(digitalPinToInterrupt(reedSwitchPin), handleRotation, FALLING);
      Serial.begin(9600);
      Serial.println("hello world!");
    }

    void loop() {
      // Test reed switch functionality
      int reedState = digitalRead(reedSwitchPin);
      if (reedState == HIGH) {
        Serial.println("Reed switch triggered!");
      }

      // Calculate wind speed based on the time between rotations
      unsigned long elapsedTime = micros() - lastRotationTime;
      if (elapsedTime > 0) {
       windSpeed = windSpeedFactor / (float)elapsedTime;
      }

      Serial.print("Wind Speed: ");
      Serial.print(windSpeed);
      Serial.println(" m/s");

      delay(1000); // Delay for 1 second before measuring again
    }

    void handleRotation() {
      // Record the time of the last rotation
      lastRotationTime = micros();
    }

title: ESP8266 serial monitor spitting out garbage

Answers: 1

body:
Pin 2 that is  gpio2 (D4) is not suitable for this esp8266 application because this pin must be high at boot time and your anemometer could be in either state. Try say pin 4 that is gpio4 (D2) instead or search for "best pins to use - esp8266"

A crash during boot time can result in characters being written to the serial monitor at a baud rate of 115200 or 74880.