message:
default parameter class method

I have this function (which works fine):

    String Esper::rtcTimeString() {
      DateTime now = rtc.now();
      char buf[] = "MM/DD/YY hh:mm:ss";
      return now.toString(buf);
    }

I'd like to have a default value of "MM/DD/YY hh:mm:ss" but also pass an argument to a parameter such as "MM/DD/YYYY" if I want to override this default behavior.

Typically, in the definitions .h file I would do something like:

    String rtcTimeString(char ts[] = "MM/DD/YY hh:mm:ss");

and subsequently in the .cpp:

    String Esper::rtcTimeString(char ts[]) {
      DateTime now = rtc.now();
      return now.toString(ts);
    }

However that results in the same returned time string every time.

e.g.

    1/6/2020 12:01:12
    1/6/2020 12:01:12
    1/6/2020 12:01:12

How can I implement a parameter such that the functionality is the same as in the first code block?

body:
This basic C++ (and GIYF).

What about

    String Esper::rtcTimeString(std::string dateTimeForamt = "MM/DD/YY hh:mm:ss")
    {
      DateTime now = rtc.now();

      return now.toString(dateTimeForamt );
    }

See, for instance, [this question](https://stackoverflow.com/questions/2749471/default-string-arguments). Hope this helps :-)


sender: user

sender: assistant

body:
You cannot pass an array of characters as an argument (implicit or not)
to a function. When you write

```c++
String rtcTimeString(char ts[] = "MM/DD/YY hh:mm:ss");
```

The array notation is implicitly converted to a pointer. The line above
is then equivalent to:

```c++
String rtcTimeString(char *ts = "MM/DD/YY hh:mm:ss");
```

And this is incorrect: you are initializing a pointer to _modifiable_
characters using the address of an array of _constant_ characters. The
compiler should have warned you about this... if you enabled compiler
warnings. The correct prototype should be

```c++
string rtcTimeString(const char* ts = "MM/DD/YY hh:mm:ss");
```

But then you cannot pass this pointer to `DateTime::toString()`, as this
method expects the template string to live in a buffer it can overwrite:
that's where it will write the formatted string.

I suggest this solution:

```c++
string rtcTimeString(const char* ts = "MM/DD/YY hh:mm:ss") {
    DateTime now = rtc.now();
    char buf[strlen(ts)+1];  // allocate a fresh buffer
    strcpy(buf, ts);         // copy the template there
    return now.toString(buf);
}
```


message:
cast double to long leads to unexpected results

I wrote a little program to show my problem:

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

      double K=39.85;
      double a=K*100;
      Serial.print("a= ");
      Serial.println(a);

      long val_long = 0;
      val_long = a;
      Serial.print("val_long= ");
      Serial.println(val_long);
    }

    void loop() {
    }

I get this back from my Arduino uno:

    a= 3985.00
    val_long=3984

I've been pondering for a long time and can't find the mistake! Why is the long value decremented by one? Can anybody help me please?

body:
The problem is that float numbers are seldom an exact representation. So the float is stored as the closest number that is exactly representable as a float, namely
10446438 × 2−18 = 39.84999847412109375.

When you multiply this by 100, you get 16322559 × 2−12 = 3984.999755859375.

And than casting to an int or long results in 3984, not 3985.

so whenever you cast a value from a float or double to an int or long, you always should add 0.5 (so all values from [x - 0.5, x + 0.5) are rounded to x assuming x >= 0, thus:

    val_long = int(a + 0.5);

Beware of negative values, see therefore https://www.cs.cmu.edu/~rbd/papers/cmj-float-to-int.html

Better is to use the `round` function, see comment of Edgar Bonet below.

**UPDATE**

See comment of Lightness Races with Monica

In case it's not wanted to round up, but you still want 39.84999847412109375 to be 39.85, than you have to add a value that has the value of the least significant bit (actually slightly less but that is impossible to define). In most cases, it's best to add half the significance you want. So if you need two decimal accuracy, add 0.005.


message:
HX711 - Inconsistent Readings

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

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

<!-- End schematic -->

Wiring is based on the scheme presented below -
[![enter image description here][1]][1]

(Reference: https://electronics.stackexchange.com/a/174580)

I am using Arduino Mega 2560, HX711 and four load cells to build a weighing scale but having a hard time calibrate the unit. I have tried different libraries and calibration schemes but none of them seem to help. I have found that the raw values corresponding to any given weight (including zero load) are not consistent. Firstly, the readings do not settle even after 10 minutes, and even if I take an average, the next time I put the same weight, I get an entirely different reading making the last average useless. I am seeing errors of the order of +/- 30 lbs when I put a known weight.

I first thought that maybe my load cells are the root cause but when hooked them up directly to Arduino and read the voltage across the bridge, I read stable constant values. Verified the voltage readings with a Voltmeter. (Yes, their resolution is not as good as HX711 but at least they are stable and consistent). I get the voltage reading close to my hand calculations.

Next, I tried testing the HX711 in different ways. In one test, I created a full-bridge using resistors other than load cells, forced the bridge out of balance but cannot read anything other than 16777215. Next, I wanted to see if the board is reacting to any voltage at all, so, I removed the bridge and did not connect anything to E+ and E- pins but supplied known voltages from a DC power supply (from 0 to 4.5V) to the A+ and A- (GND) pins. Now, it is reading only 8388607, no matter what voltage I supply. If I supply +5V or +3.3V from Arduino to the A+ and A- (GND) pins instead of DC Power supply, it then only reads 16777215.

I don't know how to interpret this behavior. How can I resolve the issue and bring the error down? Thanks for your help.

I have included the schematic below. All four Load Cells (LCs) are 3-wired (White, Black & Red). Resistance between W & B wires is around 1980 ohms while that between R & W or R & B is around 990 ohms. SO I connected the four LCs in the manner shown in the schematic. Wire colors have been labelled.

Code:

Code is pretty straightforward as I am simply reading raw values from the HX711 using the following HX711 library - github.com/queuetue/Q2-HX711-Arduino-Library.git

```
#include <Q2HX711.h>

const byte hx711_data_pin = 4;
const byte hx711_clock_pin = 8;

Q2HX711 hx711(hx711_data_pin, hx711_clock_pin);

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

void loop()
{
  Serial.println(hx711.read());
  delay(500);
}
```

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

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

 Here is is a picture of how I have seen the sensors connected.  Is this how your is?

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


message:
Arduino Uno Rev3 Internal Quartz

I'm using an Arduino Uno Rev3 Board and need to send a trigger signal at a certain frequency (20-50Hz).
This trigger signal should be as accurate as possible (+/- 0.01 ms).
The Arduino site states that the arduino uno has a 16MHz Quartz Crystal, but I'm measuring a frequency accuracy of about 0.35% (which would be typical for a ceramic resonator) instead of what i could expect from a quartz (0.001%).
I'm using the micros() function to measure time.
Am I doing something wrong? How is my frequency so inaccurate?

Thanks for your help! :)

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

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

Edit: Indeed when I have a look at the schematics, I see the ceramic resonator (Blue circle). However, there seems to be another 16 MHz part (red circle). could that be a quartz oscillator?

body:
The ATMega328P chip is, indeed, clocked by a ceramic resonator. The website is misleading in stating that it has a crystal (I have emailed the webmaster to try and get this corrected, though I don't hold out much hope).

The 16MHz crystal in the schematics is part of the USB interface circuitry and has nothing to do with the timing of your running code. It is purely used to clock the ATMega16U2 chip which provides USB connectivity (USB requires a higher accuracy for stable communication).

There are other boards available with better crystals - most often boards that have native USB connections, such as the Arduino Due or Leonardo, or any of the myriad of boards by other manufacturers, like Teensy or chipKIT.


message:
How many UNO pins have internal pull up resistors?

As the title implies.
thank you in advance.

body: All of them. It's a standard feature on all IO pins in the AVR range.


message:
"Serial" does not name a type -> How to solve this problem?

I'm trying my best to solve this problem but it didn't changed

The red line was drawn on the last Serial.println */

    int cds = A0;
    int led = 12;
    int trig1 = 2;      // Left Trig
    int trig2 = 3;      // Right Trig
    int trig3 = 4;      // Front Trig
    int trig4 = 5;      // Upside Trig
    int echo1 = 6;      // Left Echo
    int echo2 = 7;      // Right Echo
    int echo3 = 8;      // Front Echo
    int echo4 = 9;      // Upside Echo
    int vib1 = 10;      // Left vib
    int vib2 = 11;      // Right vib

    void setup() {
            pinMode(led, OUTPUT);

            pinMode(trig1, OUTPUT);
            pinMode(trig2, OUTPUT);
            pinMode(trig3, OUTPUT);
            pinMode(trig4, OUTPUT);
            pinMode(echo1, INPUT);
            pinMode(echo2, INPUT);
            pinMode(echo3, INPUT);
            pinMode(echo4, INPUT);
            pinMode(vib1, OUTPUT);
            pinMode(vib2, OUTPUT);

            Serial.begin(9600);
    }

    void loop(){
      long duration1, value1;
      long duration2, value2;
      long duration3, value3;
      long duration4, value4;

      // Ultra Sonic Sensor Part1
      digitalWrite(trig1,LOW);                           // Trigger Output
      delayMicroseconds(2);
      digitalWrite(trig1,HIGH);
      delayMicroseconds(5);
      digitalWrite(trig1,LOW);
      duration1 = pulseIn(echo1,HIGH);                   // Read Pulse Duration
      value1 = microsecondsToCentimeters(duration1);     // Count Distance
      delay(10);

      // Ultra Sonic Sensor Part2
      digitalWrite(trig2,LOW);
      delayMicroseconds(2);
      digitalWrite(trig2,HIGH);
      delayMicroseconds(5);
      digitalWrite(trig2,LOW);
      duration2 = pulseIn(echo2,HIGH);
      value2 = microsecondsToCentimeters(duration2);
      delay(10);

      // Ultra Sonic Sensor Part3
      digitalWrite(trig3,LOW);
      delayMicroseconds(2);
      digitalWrite(trig3,HIGH);
      delayMicroseconds(5);
      digitalWrite(trig3,LOW);
      duration3 = pulseIn(echo3,HIGH);
      value3 = microsecondsToCentimeters(duration3);
      delay(10);

      // Ultra Sonic Sensor Part4
      digitalWrite(trig4,LOW);
      delayMicroseconds(2);
      digitalWrite(trig4,HIGH);
      delayMicroseconds(5);
      digitalWrite(trig4,LOW);
      duration4 = pulseIn(echo4,HIGH);
      value4 =  microsecondsToCentimeters(duration4);
      delay(10);

      //Commend Part (Vibration motor)

      // Print Out Value
      Serial.print(" dist1 =");
      Serial.print(value1);
      Serial.print("(cm)");
      Serial.print(" dist2 =");
      Serial.print(value2);
      Serial.print("(cm)");
      Serial.print(" dist3 =");
      Serial.print(value3);
      Serial.print("(cm)");
      Serial.print(" dist4 =");
      Serial.print(value4);
      Serial.print("(cm)");
      delay(10);
      //

      // Initialize PIN Mode
      digitalWrite(vib1,HIGH);
      digitalWrite(vib2,HIGH);

      // 진동모터1,2,3
      if (  value4<60  or  value3<60)
      digitalWrite(vib1,LOW);
      digitalWrite(vib2,LOW);

      delay(100);

      digitalWrite(vib1,HIGH);
      digitalWrite(vib2,HIGH);

      if (0< value1 && value1<60)
      digitalWrite(vib1,LOW);

      delay(100);

      digitalWrite(vib1,HIGH);

      if (0< value2 && value2<60)
      digitalWrite(vib1,LOW);

      delay(100);

      digitalWrite(vib1,HIGH);
    }

    // Function of Count Distance

    long microsecondsToCentimeters(long microseconds)
    {
      return microseconds/29/2;
    }

            int cdsValue = analogRead(cds);

            Serial.print("cds =  ");
            Serial.println(cdsValue);

            if (cdsValue < 38 ) {
                    digitalWrite(led, HIGH);
            } else {
                    digitalWrite(led, LOW);
            }

body:
Your code would be a lot easier to read and find mistakes in if you formatted it. I see that you did that in the IDE, but in your question, you need to highlight all of the code, then click the "{}" button to make it look like code in your question.

When I pasted your code into my IDE and auto-formatted it, the answer was immediately clear: after the function `microsecondsToCentimeters()` you have written some code that is not inside any function. C and C++ don't allow that. The error message wasn't very helpful - the compilers easily get confused by our mistakes - but in this case, looking at the formatted code made it clear.

*All of the executable code in a C or C++ program (Arduino IDE uses C++) must be inside a typed and named function.* Since that is what the compiler was looking for, it seems to have interpreted the word "Serial" as a function type, but no type was defined with that name.

I'm not sure where you intended the lines from the end of `long microsecondsToCentimeters()` to go, but they need to be inside of a function, somewhere.


message:
Function to control servos

I'm trying to control 6 servos while writing a lean code. I think the function call isn't correctly yet and I think that the variables (pos_n, open_n, servo_1) in the for loop do not get inserted, but instead the string just gets inserted.

I think I have come a long way to not make this a bulky code.

What changes makes this function working, so that the call openValve(1) and openValve(2); work for both servos?

    #include <Servo.h>
    const int buttonPin = 2;
    int buttonState = 0;

    Servo servo_1;
    const int pos_1 = 0;
    const int open_1 = 105;
    const int clos_1 = 10;
    //Servo servo_2;
    //const int pos_2 = 0;
    //const int open_2 = 104;
    //const int clos_2 = 9;

    String servo_n, pos, pos_n, servo, openServo, open_n;

    void setup() {
      Serial.begin(9600);
      pinMode(buttonPin, INPUT);
      servo_1.attach(11);
    }

    void loop() {
      openValve(1); // call the function
      while (true);
    }

    void openValve(n) {
      int n = 3;
      pos = "pos_";
      pos_n = (pos + n);
      Serial.println(pos_n);

      servo = "servo_";
      servo_n = servo + n;
      Serial.println(servo_n);

      openServo = "open_";
      open_n = openServo + n;
      Serial.println(open_n);

      // DONT USE STRING BUT THE VARIABLE CONTENTS ??
      for (pos_n = pos_n; pos_n <= open_n; pos_n += 1) {
        servo_n.write(open_n);
        delay(10);
      }
    }

body:
I think you are totally misunderstanding, about variables and types and how using multiple servos with 1 function can work, and that this is your real question and not the thing with inserting variables (whatever you mean by that).

You are trying to put together a string and use it as variable name. That does not work. A string is only a variable/instance of type/class `String`. It cannot have methods of the `Servo` class. Also function parameters each have their own type. You cannot provide a value of a different type to this parameter. `Servo.write()` takes an integer value. It cannot use a String value. Thus the code inside the for loop is nonsense and won't compile. I would suggest doing some C++ tutorials from the web, that explain, how variables work in C++.

Instead you have to use multiple variables of the type `Servo`, one for each servo motor, that you are using. These variables are instances of the `Servo` class, which implements all the servo related functions (like write) Each motor gets it's own pin on the Arduino. You can put these `Servo` objects into an array, so that they can be indexed by an integer number. For example you can define the following variable in the global scope:

    #define N_SERVOS 6
    Servo servos[N_SERVOS];

This creates an array of type `Servo` with 6 elements. Each element is one independent servo object. (Note, that I used a define to easily change the number of attached servos when changing the code). You can reach an individual servo object by indexing it:

    servos[3].write(pos);

This would write a new position to servo 4 (4 because array indices are starting from 0). Now we need to attach each Servo object to one pin of the Arduino. I would create an extra array, which contains the corresponding pin numbers - also at global scope:

    int servo_pin[N_SERVOS] = {6, 7, 8, 9, 10, 11};

Here I used pins 6 to 11, but you can change them, as you like. Then in the `setup()` function we loop over our servo elements and corresponding pin numbers and attach the servo objects to the pins:

    for(int i=0;i<N_SERVOS;i++){
        servo[i].attach(servo_pin[i]);
    }

And now you can rewrite your `openValve()` function corresponding to that. I don't understand, what you wanted the servo to do in the for loop, so I will leave this to you. First you need to correct the syntax at the function declaration. You didn't specify the type of the parameter `n`. It has to look like:

    void openValve(int n){

And then you shouldn't declare a new variable with the same name, so delete the line `int n=3;`. Then you can delete all the weird string concatiation. Then you need to fix the for loop (as I wrote I will leave that to you, since you didn't explain, what the servo should actually do there). And finally you need to rewrite the servo write line like described above:

    servo[n].write(new_pos);

Note, that `new_pos` is just a placeholder here, for whatever values you need to write to the servo (as already said, I don't understand, what exactly you want the servo to do).

---

>  what I then should use instead of the String object?

The `String` class from the Arduino framework can get you into memory trouble (to be exactly memory fragmentation). You can read [Majenko's blog post about Arduino Strings][1] for further explanations.

Instead you should use `char` arrays aka C-Strings. You create a buffer with a fixed length, that is big enough to hold the biggest chunk of data, that you need to process. Let's say you need at max 30 characters. Every C-String is terminated by a zero ('\0'). This zero also needs space in the buffer. So the actual buffer size is 31.

    char string_buffer[31];

You can even directly initialize it with a string value:

    char string_buffer[31]="Teststring";

You can use `sprintf()` to put a formatted string into the buffer. For example a string with a number:

    sprintf(string_buffer, "Number: %d", 50);

will put the string "Number: 50" to the buffer and will terminate it with a zero.

  [1]: https://hackingmajenkoblog.wordpress.com/2016/02/04/the-evils-of-arduino-strings/


message:
How can I interrupt a delay() when a button is pressed?

I have created a device that allows my son to track time spent on activities and exchanges that time into a time he can use with his electronics (eTime).

[Full code in GITHUB][1]

I am having trouble coding the part of the code that handles the countdown from his earned eTime. As it is right now it can count down and give him a warning when his eTime has run out, but the process can't be interrupted.

I would like to have him be able to stop his eTime and use the remainder later. I tried putting the function in a while loop.

```
while(digitalRead(button_9)==LOW){
    delay(60000);
    avail_time -= 1;
    if(avail_time<0){
      playAlarm();
      return;
}
```
This one registers the keypress but ignores the delay.

I have also tried using a for loop to count down and another to check every second for a keypress.

```
void useTime() {
  for(int i=avail_time+1; i>0; i--){
    displayTime(i);
    for(int minute=60; minute>0; minute--){
      if(digitalRead(button_9)==HIGH){
        avail_time = i;
        return;
      }
      delay(1000);
    }
  }
  while(digitalRead(button_9)==LOW){
    tone(buzzer, 2000);
    }
  noTone(buzzer);
  avail_time=0;
  displayOptions();
  return;
 }
```
That one does not register the keypress.

  [1]: https://github.com/islandwonderer/eTimeBank

body:
You can use the [millis][1] function to check the current 'time'. If you store this, and later call this function again, by subtracting you can see how much time has been passed. so instead of `delay(500)` you use `if (millis() - timeStamp >= 500) { ...` to continue your code.

As others said in comments,  you also need to debounce to prevent multiple button triggers.

**Edit: Debouncing**

There is not a library for debouncing (at least not one on the Arduino site), but you can easily copy the needed code from the following sketch:

[Arduino Debounce][2]

  [1]: https://www.arduino.cc/reference/en/language/functions/time/millis/
  [2]: https://www.arduino.cc/en/Tutorial/Debounce


message:
Arduino GPS Simulator: SoftwareSerial Issues

For my project, i need my Arduino Uno to simulate a GPS. To do this, I need to:

 - Generate a 5V Pulse once a second (no problem)
 - Send a $GPRMC NMEA sentence with the current time over RS-232 (i've got an RS-232 shield)

The GPRMC message i need to send is the following:

$GPRMC,075832.293,A,4042.695,N,07400.796,W,,,080120,000.0,W*63

Where the first part is the time, and needs to change.
I basically implemented it as:

    // Setup
    String prefix = "$GPRMC,";
    String gprmc  = "075832.293";
    String suffix = ",A,4042.695,N,07400.796,W,,,080120,000.0,W*63";
    String all = prefix + gprmc + suffix;
    char* buff = (char*) malloc(sizeof(char)*all.length()+1);

Then, in the loop-code i update the time and want to send the message:

    //...inside the condition that gets executed once a second
    gprmc = String(gprmc.toFloat()+1);
    all = prefix+gprmc+suffix;
    all.toCharArray(buff, all.length()+1);
    mySerial.write(buff);

I'm using an RS-232 shield, which shows me when a message is being sent by blinking an LED.
However, is only seems to work, if i shorten the all string, i.e.:
Works:

    all = prefix+gprmc;
Does not work:

    all = prefix+gprmc+suffix;

Is it possible that the message is just too long to send? Is there a way I can fix this? Because it's crucial to send the whole message.

Note: I'm currently working on an Arduino Uno, but I'm switching to an arduino Leonardo today. I currently have low memory available (77% used). could this add to the problem?

Thank you so much for your help!! :)

body:
First off, some comments about your code:

* Never use `String` unless it is absolutely unavoidable
* Unless you have a `free()` to balance your `malloc()` you will run out of memory almost immediately
* There is never any need to concatenate strings to send through serial like that.

Instead of what you are currently doing, just scrap the `String` usage and your `buf` variable completely.  There is no need to concatenate things together - serial sends data one character at a time, so you're gaining nothing by concatenating and only causing yourself more problems.

How you *should* be doing it:

```c++
// The changing value as a float
float gprmc=75832.293;
// Print the prefix
mySerial.print(F("$GPRMC,"));
// Pad the value with zeroes
if (gprmc < 10) mySerial.print(F("0"));
if (gprmc < 100) mySerial.print(F("0"));
if (gprmc < 1000) mySerial.print(F("0"));
if (gprmc < 10000) mySerial.print(F("0"));
if (gprmc < 100000) mySerial.print(F("0"));
// Print the value with 3 decimal places
mySerial.print(gprmc, 3);
// Finally print the suffix
mySerial.println(F(",A,4042.695,N,07400.796,W,,,080120,000.0,W*63"));
```

Note the use of the `F()` macro to further reduce RAM usage by keeping the string constants in flash memory.


message:
Is it possible to use the Arduino Due's specials pins for digital writing and reading?

Hello the arduino [documentation][1] on the due specifies the pin mapping of the pins.I am making a custom board using the dues schematics and i am running still a bit low on pins. Also some of the special pins offer a better position for traces.

So is it possible digitalWrite()/digitalRead() the specials pins such as:

 - RX (0-3)
 - TX (0-3)
 - SDA (0-1)
 - SCL (0-1)
 - CANRX
 - CANTX
 - LED RX
 - LED TX
 - MISO
 - MOSI
 - SCLK

As for the SPI and i2c lines i will be using them for the original purpose,but i would like to take the opportunity to know anyway.

I do not own a due so unfortunately i can not test it

  [1]: https://www.arduino.cc/en/Hacking/PinMappingSAM3X

body:
As far as I know you can use them as GPIO too (I know for sure for Arduino Uno/Mega etc., I know for STM32, I would be very surprised if it's not possible for Arduino Due.

Other solutions are using shift registers like:

- 74HC595: For adding upto 32 outputs using SPI
- 74HC565: For adding upto 32 inputs using SPI

Or you can use GPIO extenders using either SPI or I2C.


body:
Yes, although you may need to modify the variant files to allow access to them.

Every function on the SAM3X8E is a "multiplexed" function. That is, it shares pins with other functions.  For example CANTX0 is an alternative function on pin PA0.

You can find all the alternative function mappings on page 40 of [the datasheet](https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-11057-32-bit-Cortex-M3-Microcontroller-SAM3X-SAM3A_Datasheet.pdf).

You may find that many of these pins already have an Arduino pin number assigned to them in the [variant file](https://github.com/arduino/ArduinoCore-sam/blob/master/variants/arduino_due_x/variant.cpp). If that is the case then you can just use it as you would any digital IO pin.

I have included the comments from the variant files here for quick reference:

```
/*
 * DUE Board pin   |  PORT  | Label
 * ----------------+--------+-------
 *   0             |  PA8   | "RX0"
 *   1             |  PA9   | "TX0"
 *   2       TIOA0 |  PB25  |
 *   3       TIOA7 |  PC28  |
 *   4       NPCS1 |  PA29  |
 *           TIOB6 |  PC26  |
 *   5       TIOA6 |  PC25  |
 *   6       PWML7 |  PC24  |
 *   7       PWML6 |  PC23  |
 *   8       PWML5 |  PC22  |
 *   9       PWML4 |  PC21  |
 *  10       NPCS0 |  PA28  |
 *           TIOB7 |  PC29  |
 *  11       TIOA8 |  PD7   |
 *  12       TIOB8 |  PD8   |
 *  13       TIOB0 |  PB27  | LED AMBER "L"
 *  14       TXD3  |  PD4   | "TX3"
 *  15       RXD3  |  PD5   | "RX3"
 *  16       TXD1  |  PA13  | "TX2"
 *  17       RXD1  |  PA12  | "RX2"
 *  18       TXD0  |  PA11  | "TX1"
 *  19       RXD0  |  PA10  | "RX1"
 *  20             |  PB12  | "SDA"
 *  21             |  PB13  | "SCL"
 *  22             |  PB26  |
 *  23             |  PA14  |
 *  24             |  PA15  |
 *  25             |  PD0   |
 *  26             |  PD1   |
 *  27             |  PD2   |
 *  28             |  PD3   |
 *  29             |  PD6   |
 *  30             |  PD9   |
 *  31             |  PA7   |
 *  32             |  PD10  |
 *  33             |  PC1   |
 *  34             |  PC2   |
 *  35             |  PC3   |
 *  36             |  PC4   |
 *  37             |  PC5   |
 *  38             |  PC6   |
 *  39             |  PC7   |
 *  40             |  PC8   |
 *  41             |  PC9   |
 *  42             |  PA19  |
 *  43             |  PA20  |
 *  44             |  PC19  |
 *  45             |  PC18  |
 *  46             |  PC17  |
 *  47             |  PC16  |
 *  48             |  PC15  |
 *  49             |  PC14  |
 *  50             |  PC13  |
 *  51             |  PC12  |
 *  52       NPCS2 |  PB21  |
 *  53             |  PB14  |
 *  54             |  PA16  | "A0"
 *  55             |  PA24  | "A1"
 *  56             |  PA23  | "A2"
 *  57             |  PA22  | "A3"
 *  58       TIOB2 |  PA6   | "A4"
 *  69             |  PA4   | "A5"
 *  60       TIOB1 |  PA3   | "A6"
 *  61       TIOA1 |  PA2   | "A7"
 *  62             |  PB17  | "A8"
 *  63             |  PB18  | "A9"
 *  64             |  PB19  | "A10"
 *  65             |  PB20  | "A11"
 *  66             |  PB15  | "DAC0"
 *  67             |  PB16  | "DAC1"
 *  68             |  PA1   | "CANRX"
 *  69             |  PA0   | "CANTX"
 *  70             |  PA17  | "SDA1"
 *  71             |  PA18  | "SCL1"
 *  72             |  PC30  | LED AMBER "RX"
 *  73             |  PA21  | LED AMBER "TX"
 *  74       MISO  |  PA25  |
 *  75       MOSI  |  PA26  |
 *  76       SCLK  |  PA27  |
 *  77       NPCS0 |  PA28  |
 *  78       NPCS3 |  PB23  | unconnected!
```


message:
USING HX711 ( WITH LOADCELL) WITH PCF8574 IN NODEMCU

I have used hx711 and loadcell with nodemcu (esp8266) in its D1 and D2 pins ( here I have used Logic level shifter and a 5v supply to power hx711).It worked perfectly fine.

 Due to the lack of enough pins to accommodate other sensors  in Nodemcu, I'm using PCF8574. I have connected hx711 to pins P0 and P1 of PCF8574.I'm not able to get any output in serial monitor while running like this.

The PCF8574 was connected using resource -

https://www.instructables.com/id/PCF8574-GPIO-Extender-With-Arduino-and-NodeMCU/

The Hx711 was connected using this  code.It is compiling but not getting any output in serial monitor.

    #include "Arduino.h"
    #include "PCF8574.h"

    // Set i2c HEX address
    PCF8574 pcf8574(0x20); // A0,A1,A2 all connected to GND
    unsigned long timeElapsed;

    include <HX711.h>
    HX711 scale;

    void setup() {
      Serial.begin(9600);
      Serial.println("initializing");
      pcf8574.pinMode(P0,INPUT);
      pcf8574.pinMode(P1,OUTPUT);
      pcf8574.begin();

      Serial.println("initializing");

      scale.begin(P0,P1); //dt , sck
      scale.get_value(5);  // print the avg of 5 readings from ADC minus tare weight
      scale.set_scale(-450.f); // callibration value
      scale.tare();// reset scale to zero
    }

    void loop() {

      int weight = scale.get_units(3);
      Serial.println(weight);
      delay(1000)

    }

Or how about this code without a library? Can I do some changes to it and use pcf8574 ?

```

#define DT D1
#define SCK D2

long sample=0;
float val=0;
long count=0;

unsigned long readCount(void)
{
  unsigned long Count;
  unsigned char i;
  pinMode(DT, OUTPUT);
  digitalWrite(DT,HIGH);
  digitalWrite(SCK,LOW);
  Count=0;
  pinMode(DT, INPUT);
  while(digitalRead(DT));
  for (i=0;i<24;i++)
  {
    digitalWrite(SCK,HIGH);
    Count=Count<<1;
    digitalWrite(SCK,LOW);
    if(digitalRead(DT))
    Count++;
  }
  digitalWrite(SCK,HIGH);
  Count=Count^0x800000;
  digitalWrite(SCK,LOW);
  return(Count);
}

void setup()
{
  Serial.begin(9600);
  pinMode(SCK, OUTPUT);
  Serial.println("Weight");
  Serial.println(" Measurement ");
  delay(1000);
  calibrate();
}

void loop()
{
  count= readCount();
  int w=(((count-sample)/val)-2*((count-sample)/val));
  Serial.print("weight:");
  Serial.print(w);
  Serial.println("g");

 delay(100);
   // val=0;
   // sample=0;
    w=0;
    count=0;
   // calibrate();

}

void calibrate()
{

  //Serial.println("Calibrating...");
  //Serial.println("Please Wait...");
  for(int i=0;i<100;i++)
  {
    yield();
    count=readCount();
    sample+=count;
   // Serial.println(count);
  }
  sample/=100;
  //Serial.print("Avg:");
  //Serial.println(sample);
  count=0;
  while(count<1000)
  {
    yield();
    count=readCount();
    count=sample-count;
    //Serial.println(count);
  }

  //Serial.println("Please Wait....");
  delay(100);
  for(int i=0;i<100;i++)
  {
    yield();
    count=readCount();
    val+=sample-count;
   //Serial.println(sample-count);
  }
  val=val/100.0;
  val=val/100.0;
  //Serial.println(val);
}

```

body: According to library, hx711 sending pulses to mcu and we are scaling with take this pulses. I think you must connect DOUT and SCK pins directly to the MCU or you must counting pulses via I2C after all create a scaling value according the library code and send it to mcu.


body:
I didnt try this method but; when i check the data sheet, i found this code on last page:

        sbit ADDO = P1^5;
        sbit ADSK = P0^0;
        unsigned long ReadCount(void){
         unsigned long Count;
         unsigned char i;
         ADDO=1;
         ADSK=0;
         Count=0;
         while(ADDO);
         for (i=0;i<24;i++){
         ADSK=1;
         Count=Count<<1;
         ADSK=0;
         if(ADDO) Count++;
         }
         ADSK=1;
         Count=Count^0x800000;
         ADSK=0;
         return(Count);
    }
Here is the pulse counting method i think. So if we are using I2C IC,  we must get pulse datas over it to our MCU and count them. But before this scaling method; we must calibrate loadcells and tare them absolutely.
And i found a link that pointing i2c with hx711. They used sparkfuns IO expander(communicating via I2C) to fix low io problem and connect loadcells to this expander and how read scalings completely.
Here is the link: if you can check, maybe find a solution for your problem.
[Sparkfun's I2c Expander with Hx711][1]

  [1]: https://www.robotshop.com/community/forum/t/reading-form-several-load-cells-hx711-using-i-o-expander-s/29268


body: PCF8574 takes around 256us to update pins (at standard 100khz i2c). This too high compared to hx711 sck timing constraint which is 50us max. So, it's not possible to communicate with hx711 using PCF8574. wasted two days in finding out this.


message:
Connect Arduino to LiDAR via RS-232

**Edit: We're so close! Update at bottom!**
I'm not sure if this is the right place to ask, but since you helped my so much in the past, I thought it's worth a try.

So as I stated in my [last question](https://arduino.stackexchange.com/questions/71584/arduino-gps-simulator-softwareserial-issues), I'm using my Arduino Leonardo to simulate a GPS Receiver.

The Arduino is now connected to a [Velodyne VLP-16 LiDAR](https://levelfivesupplies.com/product/velodyne-puck-vlp-16/)

Here's what the Lidar needs:
[![Requirements of the LiDAR][1]][1]

I wired it like this:
[![Schematic][2]][2]

And wrote the following code:

    #include <SoftwareSerial.h>
    SoftwareSerial mySerial(7, 6); //232_TX,232_

    int triggerFreq = 1;
    unsigned long timestamp;
    unsigned long triggerStartTime;
    const unsigned long dt = 1000000/triggerFreq; //micros

    unsigned long i;

    float gprmc = 181721.000;

    void setup() {
      pinMode(11, OUTPUT); // PPS
      pinMode(12, OUTPUT); // Indicator of msg_sent
      Serial.begin(9600);
      mySerial.begin(9600);
      triggerStartTime = micros();
    }

    void loop() {
      timestamp = micros()-triggerStartTime;
      if (timestamp>= dt*i+200000)
      {
        digitalWrite(12,HIGH);

        i +=1;
        gprmc += 1;
        mySerial.print("$GPRMC,");
        if (gprmc < 100000) mySerial.print(F("0"));
        mySerial.print(gprmc,3);
        mySerial.println(F(",A,4042.695,N,07400.796,W,,,080120,000.0,W*63"));
        Serial.print("$GPRMC,");
        if (gprmc < 100000) Serial.print(F("0"));
        Serial.print(gprmc,3);
        Serial.println(F(",A,4042.695,N,07400.796,W,,,080120,000.0,W*63"));
        digitalWrite(12,LOW);
      }
      else if (timestamp>=dt*i+100000)
      {
        digitalWrite(11,LOW);
      }
      else if (timestamp>=dt*i)
      {
        digitalWrite(11,HIGH);

      }

    }
Here's the situation now:

 - I'm seeing on the board that the messages are being sent (TX LED flashing)
 - I'm also seeing that the pulse is sent correctly (flashing LED)
 - I don't measure any voltage on the TX output pin (RS232 pin3) (I'm just using my multimeter, but normally it reacts to such short voltage pulses by blinking an LED)
 - I do measure such a pulse on RS232 pin4
 - The LiDAR doesn't react to my sent messages

Now my question: Do you see an error in my implementation? Is the message sent correctly?

Thank you sooo much for your help! I'm really appreciating it!

Edit: The LiDAR manual says:

> The supported NMEA sentence and syntax are exactly the same as on the wired (serial) GPS interface. Supported sentence delimiter sequences include <CR><LF> (HEX 0D0A, the standard), <CR> by itself, and <LF> by itself.

To be honest I'm not very familiar with these kind of problems so I'm not sure if these delimiters are already being sent?

Edit Nr2: Ok the following situation:

 - I'm actually not sure what changed. The code is still the same as above
 - The LiDAR now recognizes SOME of the messages (I can only see the position, so I edited the code to change the position a bit every second, and the Lidar updates its position irregularly but approx. all 10 seconds)
 - If anyone knows an explanation, I would be very happy to know. Otherwise, I just keep on trying an will keep you updated!

  [1]: https://i.stack.imgur.com/QDpzP.png
  [2]: https://i.stack.imgur.com/DWvLe.png
  [3]: https://i.stack.imgur.com/d5XWS.png

---

So the following code partially works. That means: the LiDAR recognizes **certain** messages... it seems like those are always the same messages (i incremented the position every second, these are the positions):

 - 3015.2746
 - 3015.2766
 - 3015.2971
 - 3015.3107
 - 3015.3117

I displayed all the times when something was sent, and i could not find any differences between the messages that worked and those that didn't work.

**One more followup:**
If I try to increment `pos+=0.0001`, it does not work... it seems like i can only change up to 3 decimals. I don't understand why, since the float uses 4 bytes, so this should be no problem to store?! helpppp

Ok so here is the code for now:

    #include <SoftwareSerial.h>
    SoftwareSerial mySerial(7, 6); //232_TX,232_

    int triggerFreq = 1;
    unsigned long timestamp;
    unsigned long triggerStartTime;
    const unsigned long dt = 1000000/triggerFreq; //micros
    unsigned long ts_pps_high;
    unsigned long ts_pps_low;
    unsigned long ts_msg_high;
    unsigned long ts_msg_low;

    unsigned long i;

    int hh = 04;
    int mm = 51;
    int ss = 00;
    float pos = 3015.2307;
    bool msg;

    void setup() {
      // put your setup code here, to run once:
      pinMode(11, OUTPUT); // PPS
      pinMode(12, OUTPUT); // Indicator of msg_sent
      Serial.begin(9600);
      mySerial.begin(9600);
      triggerStartTime = micros();
    }

    void loop() {
      timestamp = micros()-triggerStartTime;
      if (timestamp>= dt*i+350000)
      {
        pos +=0.001;
        digitalWrite(12,HIGH);
        i +=1;
        if (ss == 59)
        {
          ss=0;
          if (mm==59)
          {
            mm=0;
            hh+=1;
          }
          else mm+=1;
        }
        else ss+=1;

        ts_msg_high = micros();
        mySerial.print("$GPRMC,");
        if (hh<10) mySerial.print(F("0"));
        mySerial.print(hh);
        if (mm<10) mySerial.print(F("0"));
        mySerial.print(mm);
        if (ss<10) mySerial.print(F("0"));
        mySerial.print(ss);
        mySerial.print(".000,A,");
        mySerial.print(pos,4);
        mySerial.println(",N,09749.2872,W,0.67,161.46,030913,,,A*7C");

        // Print Debug Messages
        digitalWrite(12,LOW);
        ts_msg_low=micros();
        Serial.print("PPS at: ");
        Serial.print(ts_pps_high);
        Serial.print("\t PPS low after: ");
        Serial.print(ts_pps_low-ts_pps_high);
        Serial.print("\t MSG high after: ");
        Serial.print(ts_msg_high-ts_pps_high);
        Serial.print("\t MSG low after: ");
        Serial.print(ts_msg_low-ts_pps_high);
        Serial.print("$GPRMC,");
        if (hh<10) Serial.print(F("0"));
        Serial.print(hh);
        if (mm<10) Serial.print(F("0"));
        Serial.print(mm);
        if (ss<10) Serial.print(F("0"));
        Serial.print(ss);
        Serial.print(".000,A,");
        Serial.print(pos,4);
        Serial.println(",N,09749.2872,W,0.67,161.46,030913,,,A*7C");
      }
      else if (timestamp>=dt*i+100000)
      {
        digitalWrite(11,LOW);
        if (msg==true)
        {
          msg = false;
          ts_pps_low = micros();
        }

      }
      else if (timestamp>=dt*i)
      {
        digitalWrite(11,HIGH);
        if (msg==false)
        {
          msg = true;
          ts_pps_high = micros();
        }
      }

    }

You can see my output as well:

    PPS at: 2001060  PPS low after: 100000  MSG high after: 350016  MSG low after: 427132$GPRMC,045103.000,A,3015.2336,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 3001060  PPS low after: 100004  MSG high after: 350004  MSG low after: 427112$GPRMC,045104.000,A,3015.2346,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 4001056  PPS low after: 100000  MSG high after: 350004  MSG low after: 427116$GPRMC,045105.000,A,3015.2355,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 5001060  PPS low after: 100004  MSG high after: 350004  MSG low after: 427112$GPRMC,045106.000,A,3015.2365,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 6001056  PPS low after: 100004  MSG high after: 350004  MSG low after: 427116$GPRMC,045107.000,A,3015.2375,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 7001060  PPS low after: 100004  MSG high after: 350004  MSG low after: 427120$GPRMC,045108.000,A,3015.2385,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 8001056  PPS low after: 100004  MSG high after: 350020  MSG low after: 427132$GPRMC,045109.000,A,3015.2395,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 9001060  PPS low after: 100000  MSG high after: 350016  MSG low after: 427160$GPRMC,045110.000,A,3015.2404,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 10001052  PPS low after: 100008  MSG high after: 350020  MSG low after: 427164$GPRMC,045111.000,A,3015.2414,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 11001064  PPS low after: 100000  MSG high after: 350020  MSG low after: 427164$GPRMC,045112.000,A,3015.2424,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 12001056  PPS low after: 100008  MSG high after: 350004  MSG low after: 427152$GPRMC,045113.000,A,3015.2434,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 13001056  PPS low after: 99996  MSG high after: 350020  MSG low after: 427164$GPRMC,045114.000,A,3015.2443,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 14001056  PPS low after: 100008  MSG high after: 350008  MSG low after: 427156$GPRMC,045115.000,A,3015.2453,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 15001052  PPS low after: 100004  MSG high after: 350020  MSG low after: 427164$GPRMC,045116.000,A,3015.2463,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 16001052  PPS low after: 100000  MSG high after: 350016  MSG low after: 427164$GPRMC,045117.000,A,3015.2473,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 17001056  PPS low after: 100004  MSG high after: 350020  MSG low after: 427164$GPRMC,045118.000,A,3015.2482,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 18001052  PPS low after: 100000  MSG high after: 350016  MSG low after: 427164$GPRMC,045119.000,A,3015.2492,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 19001056  PPS low after: 100004  MSG high after: 350020  MSG low after: 427160$GPRMC,045120.000,A,3015.2502,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 20001060  PPS low after: 100000  MSG high after: 350004  MSG low after: 427148$GPRMC,045121.000,A,3015.2512,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 21001052  PPS low after: 100004  MSG high after: 350020  MSG low after: 427168$GPRMC,045122.000,A,3015.2521,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 22001064  PPS low after: 100004  MSG high after: 350004  MSG low after: 427148$GPRMC,045123.000,A,3015.2531,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 23001052  PPS low after: 100008  MSG high after: 350020  MSG low after: 427172$GPRMC,045124.000,A,3015.2541,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 24001052  PPS low after: 100008  MSG high after: 350024  MSG low after: 427168$GPRMC,045125.000,A,3015.2551,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 25001056  PPS low after: 100000  MSG high after: 350016  MSG low after: 427168$GPRMC,045126.000,A,3015.2561,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 26001052  PPS low after: 100008  MSG high after: 350024  MSG low after: 427160$GPRMC,045127.000,A,3015.2570,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 27001056  PPS low after: 100000  MSG high after: 350020  MSG low after: 427156$GPRMC,045128.000,A,3015.2580,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 28001060  PPS low after: 100008  MSG high after: 350004  MSG low after: 427144$GPRMC,045129.000,A,3015.2590,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 29001056  PPS low after: 100000  MSG high after: 350020  MSG low after: 427156$GPRMC,045130.000,A,3015.2600,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 30001056  PPS low after: 100004  MSG high after: 350020  MSG low after: 427164$GPRMC,045131.000,A,3015.2609,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 31001056  PPS low after: 100008  MSG high after: 350004  MSG low after: 427148$GPRMC,045132.000,A,3015.2619,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 32001056  PPS low after: 99996  MSG high after: 350012  MSG low after: 427164$GPRMC,045133.000,A,3015.2629,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 33001056  PPS low after: 100008  MSG high after: 350020  MSG low after: 427164$GPRMC,045134.000,A,3015.2639,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 34001056  PPS low after: 100000  MSG high after: 350016  MSG low after: 427164$GPRMC,045135.000,A,3015.2648,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 35001060  PPS low after: 100004  MSG high after: 350000  MSG low after: 427144$GPRMC,045136.000,A,3015.2658,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 36001060  PPS low after: 100000  MSG high after: 350004  MSG low after: 427148$GPRMC,045137.000,A,3015.2668,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 37001060  PPS low after: 100004  MSG high after: 350004  MSG low after: 427144$GPRMC,045138.000,A,3015.2678,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 38001064  PPS low after: 100004  MSG high after: 350004  MSG low after: 427144$GPRMC,045139.000,A,3015.2687,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 39001060  PPS low after: 100008  MSG high after: 350004  MSG low after: 427152$GPRMC,045140.000,A,3015.2697,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 40001052  PPS low after: 100008  MSG high after: 350024  MSG low after: 427160$GPRMC,045141.000,A,3015.2707,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 41001052  PPS low after: 100000  MSG high after: 350016  MSG low after: 427168$GPRMC,045142.000,A,3015.2717,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 42001060  PPS low after: 100004  MSG high after: 350004  MSG low after: 427148$GPRMC,045143.000,A,3015.2727,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 43001056  PPS low after: 100000  MSG high after: 350020  MSG low after: 427164$GPRMC,045144.000,A,3015.2736,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 44001052  PPS low after: 100004  MSG high after: 350020  MSG low after: 427164$GPRMC,045145.000,A,3015.2746,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 45001064  PPS low after: 100004  MSG high after: 350004  MSG low after: 427144$GPRMC,045146.000,A,3015.2756,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 46001052  PPS low after: 100004  MSG high after: 350020  MSG low after: 427172$GPRMC,045147.000,A,3015.2766,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 47001056  PPS low after: 100004  MSG high after: 350020  MSG low after: 427164$GPRMC,045148.000,A,3015.2775,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 48001056  PPS low after: 100000  MSG high after: 350016  MSG low after: 427164$GPRMC,045149.000,A,3015.2785,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 49001060  PPS low after: 100004  MSG high after: 350004  MSG low after: 427144$GPRMC,045150.000,A,3015.2795,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 50001052  PPS low after: 100000  MSG high after: 350016  MSG low after: 427160$GPRMC,045151.000,A,3015.2805,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 51001060  PPS low after: 100004  MSG high after: 350004  MSG low after: 427148$GPRMC,045152.000,A,3015.2814,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 52001056  PPS low after: 100000  MSG high after: 350020  MSG low after: 427164$GPRMC,045153.000,A,3015.2824,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 53001064  PPS low after: 100004  MSG high after: 350000  MSG low after: 427144$GPRMC,045154.000,A,3015.2834,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 54001056  PPS low after: 100004  MSG high after: 350020  MSG low after: 427164$GPRMC,045155.000,A,3015.2844,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 55001060  PPS low after: 100004  MSG high after: 350020  MSG low after: 427172$GPRMC,045156.000,A,3015.2854,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 56001068  PPS low after: 100004  MSG high after: 350000  MSG low after: 427144$GPRMC,045157.000,A,3015.2863,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 57001060  PPS low after: 99996  MSG high after: 350012  MSG low after: 427160$GPRMC,045158.000,A,3015.2873,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 58001064  PPS low after: 100004  MSG high after: 350004  MSG low after: 427148$GPRMC,045159.000,A,3015.2883,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 59001056  PPS low after: 100000  MSG high after: 350024  MSG low after: 427132$GPRMC,045200.000,A,3015.2893,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 60001060  PPS low after: 100004  MSG high after: 350020  MSG low after: 427124$GPRMC,045201.000,A,3015.2902,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 61001064  PPS low after: 100008  MSG high after: 350004  MSG low after: 427116$GPRMC,045202.000,A,3015.2912,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 62001060  PPS low after: 100008  MSG high after: 350008  MSG low after: 427124$GPRMC,045203.000,A,3015.2922,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 63001060  PPS low after: 100012  MSG high after: 350008  MSG low after: 427120$GPRMC,045204.000,A,3015.2932,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 64001052  PPS low after: 100000  MSG high after: 350020  MSG low after: 427136$GPRMC,045205.000,A,3015.2941,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 65001060  PPS low after: 100008  MSG high after: 350004  MSG low after: 427120$GPRMC,045206.000,A,3015.2951,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 66001064  PPS low after: 100000  MSG high after: 349996  MSG low after: 427116$GPRMC,045207.000,A,3015.2961,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 67001060  PPS low after: 100004  MSG high after: 350004  MSG low after: 427120$GPRMC,045208.000,A,3015.2971,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 68001060  PPS low after: 100000  MSG high after: 350004  MSG low after: 427112$GPRMC,045209.000,A,3015.2980,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 69001052  PPS low after: 100004  MSG high after: 350020  MSG low after: 427164$GPRMC,045210.000,A,3015.2990,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 70001064  PPS low after: 100004  MSG high after: 350004  MSG low after: 427136$GPRMC,045211.000,A,3015.3000,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 71001060  PPS low after: 100004  MSG high after: 350004  MSG low after: 427148$GPRMC,045212.000,A,3015.3010,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 72001064  PPS low after: 100004  MSG high after: 350004  MSG low after: 427144$GPRMC,045213.000,A,3015.3020,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 73001056  PPS low after: 100000  MSG high after: 350016  MSG low after: 427164$GPRMC,045214.000,A,3015.3029,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 74001064  PPS low after: 99988  MSG high after: 350004  MSG low after: 427148$GPRMC,045215.000,A,3015.3039,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 75001052  PPS low after: 100000  MSG high after: 350020  MSG low after: 427164$GPRMC,045216.000,A,3015.3049,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 76001060  PPS low after: 100004  MSG high after: 350000  MSG low after: 427144$GPRMC,045217.000,A,3015.3059,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 77001056  PPS low after: 100008  MSG high after: 350004  MSG low after: 427148$GPRMC,045218.000,A,3015.3068,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 78001060  PPS low after: 100008  MSG high after: 350004  MSG low after: 427152$GPRMC,045219.000,A,3015.3078,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 79001052  PPS low after: 100008  MSG high after: 350020  MSG low after: 427164$GPRMC,045220.000,A,3015.3088,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 80001052  PPS low after: 100000  MSG high after: 350016  MSG low after: 427164$GPRMC,045221.000,A,3015.3098,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 81001056  PPS low after: 100008  MSG high after: 350020  MSG low after: 427164$GPRMC,045222.000,A,3015.3107,N,09749.2872,W,0.67,161.46,030913,,,A*7C
    PPS at: 82001060  PPS low after: 100000  MSG high after: 350016  MSG low after: 427172$GPRMC,045223.000,A,3015.3117,N,09749.2872,W,0.67,161.46,030913,,,A*7C

body:
A number of hints to check, though I can only throw vague observations on the error (EDIT: some hints only make sense with an older version of the question):

 - You set the SoftwareSerial to pin 7 for RX and pin 6 for TX, but the TX LED of the board is connected to the _hardware_ UART, which is used by `Serial`. So the TX LED reacts to your debug messages sent via `Serial.print()` to the PC. The TX and RX pins on your Arduino board are always connected to the hardware UART, which always is managed by `Serial` and cannot be claimed by `SoftwareSerial`.
 - The "SoftwareSerial TX pin" of your Arduino (note: the TX pin _you_ set via `SoftwareSerial mySerial(7, 6);`) needs to be connected to RX of the GPS module. Remember: If you transmit something via the transmit line of one device, it needs to be received by the receive line of the other device (T stands for transmit, R for receive, and X for that you must cross the lines). (This hint ignores that you've got a RS232 shield, I realized that only later.)
 - The docs state that your gprmc record is accepted in either `hhmmss` or `hhmmss.s` format. Yet you send a string with three places after the dot. I'm not sure whether I misinterpret something here.
 - If you just add 1 to gprmc every second, you'll end up sending the equivalent of "18 hours, 17 minutes, 61 seconds" after 40 seconds runtime (because the format is expected to be `hhmmss`), which might or might not confuse the GPS chip.
 - Is 9600 baud the correct speed for the GPS receiver? Somewhere in the docs should be a hint about that (I'd expect at least 115200 on devices that are less than 20 years old...).
 - The pulse line might follow negative logic, i.e. it normally is HIGH and need to be pulled LOW for the pulse. Check the data sheet whether a LOW pulse is needed, in which case you need to swap HIGH and LOW on the pulse line.
 - What is pin 12 (msg_sent) and why do you need it? Its not mentioned in the schematics. I can only glean that it might signal your RS232 shield that the message has been sent to the RS232 shield and the RS232 UART now may empty its buffer, i.e. actually send the message over the wire to the GPS chip. If this is indeed the case, you signal the RS232 shield that the message has been sent before you actually send the message.
 - Try it without the RS232 shield? RS232 is just a specification of "serial protocol" that allows for voltage levels of up to 25V plus a few extra signal lines. By the schematic and wiring, I see that the GPS chip does not use any extra lines and expects a signal level of 5V. With SoftwareSerial, you already output "serial protocol" at 5V signal level from your GPIO pins. From afar, it looks like the RS232 shield inserts more potential points of failure into the communication. Have you got a Serial-to-USB converter to actually check the output of your RS232 shield?
 - Your delimiters are not sent. Hex 0D0A is simply CRLF, or "carriage return, line feed" or "the standard line break characters in plain text files on DOS and Windows". Which means: The last `mySerial.print()` would need to be changed to `mySerial.println()`, which is just like `mySerial.print()`, only that it adds a line break at the end.
 - Maybe it works if you connect the pin labeled `GPS_RXD_CNT` in the schematics with pin 6 of your Arduino while removing any own wiring from TX and RX of your Arduino.
 - [Floats][1] do not "store 3 decimal places after the decimal point", they store the significant binary places plus the position of the point. This means: if the number of significant places is big, you lose precision at the end. Converted to decimal, a 32-bit float only has a precision of 6-7 decimal places. A number like (decimal) 100000.01 would lose its last 1, yielding 100000.0; this also is true for 1000000.1 (=1000000.0), 10000001000.0 (=10000000000.0) and 0.000010000001 (=0.00001). So if you add 0.1 to 1234567.0, you'll end up with 1234567.0 -- or in the extreme: 1234567000000.0 + 11111.0 = 1234567000000.0. (Numbers off the top of my head, reality might introduce some rounding between decimal and binary representation, this is just to get the point across -- also, your decimal output will not show this exactly, because a binary representation only is precise for fractions of powers of two after the point).

Also, you might want to add some `Serial.println()` calls for each of your `digitalWrite()` calls, outputting something like "pin 11 (PPS) is now HIGH". Then use the Serial Monitor of Arduino IDE (don't forget to set its baud rate to 9600) to check whether the protocol looks right.

  [1]: https://www.arduino.cc/reference/en/language/variables/data-types/float/


message:
Information about 'Arduino Nano 33 IoT'

blox w-102 is based on esp32** which (Esp32) can be used as a standalone chip for projects.
Here I want to know **how w-102 and samd21g18a are communicating with each other**.
If they are communicating then what is the need of doing so?

body: The two chips are connected together by both UART and SPI channels.  I am unsure, but I think the main communication is performed over SPI and the UART is only used for programming and debugging of the NINA.


body:
The Arduino boards with the NINA module: MKR 1010 WiFi, MKR 4000 vidor, Uno WiFi and Nano 33 IoT use the NINA module for WiFi networking with the WiFiNINA library and for BLE with the ArdunioBLE library. Additionally the flash memory of the NINA module will be available as storage.

The NINA module runs a firmware made by Arduino with ESP32 IDF framework.

I wired MKR ZERO with an ESP32 dev board for the WiFiNINA firmware and library according to MKR 1010 WiFi schematics, which is very similar to Nano 33 IoT. The MCUs are connected on SPI pins and UART for communication. The firmware uses one additional pin to signal to SPI master as 'ready' pin. Also io 0 and enable pin of NINA module are wired to put the ESP32 into flashing mode for firmware upgrade over UART.

On MKR 1010 and Nano33 IoT I2C is connected too. Boot MCU have access to on-board I2C sensors and could in theory communicate over I2C. This is currently not used.

The WiFiNINA library uses SPI communication. SAMD is master, NINA is slave.

The ArduinoBLE library communicates over UART. 'Ready' pin is used to switch to BLE mode in firmware at NINA reset.

The firmware uses io 0 as 'heartbeat' signal for the library.

My wiring:

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

* the orange wire from MKR pin 5 is connected as reset to EN (with a wire under the ESP32 board)
* io 0 of ESP32 is the yellow wire to MKR pin 4
* VSPI pins 5, 18, 19, 23 (I changed 12 to 19 in firmware). white wire on MKR pin 7 and ESP32 pin 19 is CS
* I used 22 as readyPin (originally 33). white wire on MKR pin 6
* I didn't wire I2C and Serial here

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


message:
Generate number

I wanna make some sketch to generate number to represent sensor value, with range from high (900) to low (670), that number decrease with range between 1-10 and with some delay of switching number with range from 5-15 seconds:

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

        void number(){
          int sensor = 0;                  //sensor variable
          int a = random(0, 10);           //range subtraction sensor value
          int delay = random(5000, 15000); //range delay switching value
          for(sensor = 900; sensor >= 670; sensor -=a){ //iteration sensor value with range 670-900
            Serial.println(sensor);
            delay(delay);}
        }

        void loop() {
        number();
        }

with output:

 - 900 (delay 7 sec)
 - 894 (delay 3 sec)
 - 988 (delay 5 sec)
 - 979 (delay 9 sec)

The sketch above was work as well, **but i still can't using variable "sensor" result after iteration "for" in void loop**.
I hope you can help me, thanks.

body:
    int sensor = 900;                 //variabel sensor

    void setup() {
      Serial.begin(9600);
      while (!Serial);
      randomSeed(analogRead(A0));
    }

    int number() {
      int a = random(0, 10);          //range pengurang nilai sensor
      int d = random(500, 1500); //range delay perubahan nilai
      if (sensor < 670) {
        sensor = 900;
      }
      sensor -= a;
      delay(d);
      return sensor;
    }

    void loop() {
      int val = number();
      Serial.println(val);
    }

I modified the delay for test.

[randomSeed][1] ensures different random values at every run

EDIT: a not blocking version which returns the same values for random interval:

    int sensor = 900;                 //variabel sensor
    unsigned long nextChangeMillis = 0;

    void setup() {
      Serial.begin(9600);
      while (!Serial);
      randomSeed(analogRead(A0));
    }

    int number() {

      if (millis() < nextChangeMillis)
        return sensor;

      int a = random(0, 10);          //range pengurang nilai sensor
      int d = random(500, 1500); //range delay perubahan nilai
      if (sensor < 670) {
        sensor = 900;
      }
      sensor -= a;
      nextChangeMillis += d;
      return sensor;
    }

    void loop() {
      int val = number();
      Serial.println(val);
    }

  [1]: https://www.arduino.cc/reference/en/language/functions/random-numbers/randomseed/


message:
Spiffs vs Eeprom on esp8266

In my project, i have some data to save permanently. After some research i got many examples and informations to do that with eeprom. I used it effectively.
After all i decide to deep dive to esp8266 and i got some information about spiffs.
Now i know what spiffs is and what its purpose. But i am wondering what is difference between eeprom vs spiffs?
I know both of them using flash memory as same and we can write and store data with them but why spiffs? Why eeprom ? What are their pros and cons or etc.?

body:
I don't think it makes any difference from a hardware point of view. The benefits of using the eeprom library is that it avoids rewriting unchanged data (if you use spiffs you might want to implement that as well) and that the esp is compatible with the arduino environment, where there is a real eeprom.

On the other hand, SPIFFS has its advantages (e.g. easy upload, space). It's up to you...


body:
On the ESP8266 there's very little to choose from between the two. It all really boils down to what you want to store and how you best want to access it.

EEPROM emulation is ideal for small bits of data - configuration values and that sort of thing. Where you just want to store a few of values that would seldom change.

SPIFFS though is better at dealing with large amounts of data. Since it's a filesystem it can store actual files, and that makes it ideal for serving images and static data for web pages, for example.

A SPIFFS filesystem can be built on your PC from files of your choice and then uploaded over serial using `mkspiffs` and `esptool.py` or the SPIFFS tool that can be installed into the Arduino IDE. That means the files are very easy to update.

SPIFFS is not so great when it comes to writing data though - experiments have shown that it gets quite slow when writing often.  EEPROM doesn't suffer from such a problem, but then you can't write as much data to EEPROM as you can to SPIFFS.

So that's really all there is to it. Neither is "better" than the other, but each is better suited to different ways of working or to different styles of data.


body:
I will also add a few more things:

SPIFFS acts like a String or Serial object -- so you can do a println() or whatever else you want, and read/parse it back out. There's also a digital-level access that lets you read or write memory structures directly, too. It is wear-leveled and is wonderful for anything where you need multiple independent configs or lots of (searchable!) data.

You can also upload files (or download them) from a web server, and most things that support Strings to write to can use a File as well (YMMV).

EEPROM is not (unless you specifically downloaded a 3rd-party library to do so) wear-leveled on this system and uses one sector of flash. Writing to it too often will cause the sector to fail (~10,000-100,000 times, so it's a lot though). You are also limited by the size of the sector, so the maximum size of the data you can store is 4096 bytes.

Furthermore, EEPROM is written like an array. All your data ends up in this array, and you have to keep track of where each piece is and how large it was (potentially across multiple libraries, files, or functions). Worse, you can't tell if you changed the format since it was last saved (reuploaded your code or something), so you really _should_ have a checksum or something.

----------

TL;DR:
SPIFFS is larger (storable capacity and in terms of code to access) and wear-leveled. It has a lot of convenience features, and lets you write or compose complex data.

EEPROM is tiny and has a limitation on how many times it can be committed before it fails (bad for datalogging and stuff). At best you can write memory blocks to it.

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

Edit: SPIFFS has now been deprecated due to lack of support by the devs, which is somewhat sad. It has been replaced by LittleFS, which (annoyingly to me) has more overhead AND does not do static wear-leveling (it only wear-levels to free space when a file is edited/moved, and does not reuse memory consumed by files that don't change (even if those have by far the least wear)). The interface (aside from changing all instances to "LittleFS" instead of SPIFFS, and some other minor things) is largely the same to the user otherwise, however, so this post still applies.


message:
Arduino randomly freezes during runtime?

I'm currently trying to create a traffic simulation project on Arduino, where it can change lights, open a gate, and turn on street lamps based on light. If anybody could help me diagnose why my arduino is behaving this way, that'd be extremely appreciated. Here is my code, if it helps you understand.
```
//Libraries Used
#include<Servo.h>

//Variable Declaration
int red1 = 10;
int yellow1 = 9;
int green1 = 8;
int red2 = 13;
int yellow2 = 12;
int green2 = 11;
int debug = 3;
int PIR = 5;

int button1 = 2;
int buttonState = 0;

int light = 0;

unsigned long previousTime = 0;
unsigned long currentTime = 0;
int currentState = 0;

int currentPIR = 0;
int pirState = LOW;

Servo servo;

void setup()
{
  pinMode(red1, OUTPUT);
  pinMode(yellow1, OUTPUT);
  pinMode(green1, OUTPUT);
  pinMode(red2, OUTPUT);
  pinMode(yellow2, OUTPUT);
  pinMode(green2, OUTPUT);
  pinMode(debug, OUTPUT);

  pinMode(PIR, INPUT);

  pinMode(button1, INPUT);

  servo.attach(4);
  servo.write(90);
}

void loop()
{

  currentPIR = digitalRead(PIR);
  if(currentPIR == 1){
    servo.write(180);
  }else{
    servo.write(90);
  }

  buttonState = digitalRead(2);
  light = analogRead(A0);

  if(light > 100){
    digitalWrite(debug, HIGH);
  }else{
    digitalWrite(debug, LOW);
  }

  if(buttonState == HIGH){
    if(currentState == 3){
      digitalWrite(debug, HIGH);
      currentState++;
    }
  }
  //Using millis() instead of delay(), so program doesn't pause completely.
  currentTime = millis();
  changeLights();
}

void changeLights(){
  if(currentState == 0){
    //Red, Green
    digitalWrite(red2, LOW);
    digitalWrite(red1, HIGH);
    digitalWrite(green2, HIGH);
    asyncDelay(4000);
  }
  else if(currentState == 1){
    //Red, Yellow
    digitalWrite(green2, LOW);
    digitalWrite(yellow2, HIGH);
    asyncDelay(2000);
  }
  else if(currentState == 2){
    //Red, Red
    digitalWrite(yellow2, LOW);
    digitalWrite(red2, HIGH);
    asyncDelay(750);
  }
  else if(currentState == 3){
    //Green, Red
    digitalWrite(red1, LOW);
    digitalWrite(green1, HIGH);
    asyncDelay(4000);
  }
  else if(currentState == 4){
    //Yellow, Red
    digitalWrite(green1, LOW);
    digitalWrite(yellow1, HIGH);
    asyncDelay(2000);
  }
  else if(currentState == 5){
    //Red, Red
    digitalWrite(yellow1, LOW);
    digitalWrite(red2, HIGH);
    asyncDelay(750);
  }
}

void asyncDelay(int delayTime){
  if(currentTime - previousTime == delayTime){
    currentState++;
    previousTime = currentTime;
    if(currentState == 6){
      currentState = 0;
    }
  }
}
```

body:
You should replace:

    if(currentTime - previousTime == delayTime){

with

    if(currentTime - previousTime >= delayTime){

There is always a chance that, since you are using a servo which is quite intensive with interrupts, that `millis()` may skip a beat and that statement can never be true.


message:
Cancelling state of code before going to interrupt

Currently, I have two loops in my Arduino code.

Certain cases take me from loop 1 to loop 2

I also have an ISR

When my ISR condition is met the code is executed and part of the ISR code is supposed to go to loop 1. Which it does but...

Then I close the ISR accordingly, but the service routine goes back to loop 2.

Any ideas why?

I've been surfing the web for the past couple hours and haven't caught a wave..

Thanks all.

    //Physical variables
    int eStop = 3;         // the number of the input pin
    int eStopLED = 9;       // the number of the output pin

    int dispenseButton = 6;         // the number of the input pin
    int dispenseLED = 8;       // the number of the output pin

    // have 789 for colors and 3456 for input only 3 ND 6 NEEDS TO BE USED

    int eStopZone = HIGH;      // the current eStopZone of the output pin
    int eStopScan;           // the current eStopScan from the input pin
    int eStopPrior = LOW;    // the eStopPrior eStopScan from the input pin

    int dispenseZone = HIGH;      // the current eStopZone of the output pin
    int dispenseScan;           // the current eStopScan from the input pin
    int dispensePrior = LOW;    // the eStopPrior eStopScan from the input pin

    //Other Variables
    volatile int vControl = 0;
    int eVar;
    int i; //Normal counting integer

    // will quickly become a bigger number than can be stored in an int.
    long time = 0;         // the last time the output pin was toggled
    long debounce = 200;   // the debounce time, increase if the output flickers

    void control(void);
    void emergency(void);
    //another coid for char ring

    void setup()
    {
      pinMode(eStop, INPUT);
      pinMode(eStopLED, OUTPUT);

      pinMode(dispenseButton, INPUT);
      pinMode(dispenseLED, OUTPUT);
      eVar = 0;
      Serial.begin(9600);  //Start Serial
      attachInterrupt(digitalPinToInterrupt(eStop), emergency, CHANGE);
    }

    void loop()
    {
      eStopScan = digitalRead(eStop);
      dispenseScan = digitalRead(dispenseButton);
      //Serial.println(eStopScan);
      /*if (eStopScan == HIGH && eStopPrior == LOW && millis() - time > debounce) { //eStop control conditions
        switch (eVar) {
          case 0:
            vControl = 0;
            control();
            break;

          case 1:
            vControl = 1;
            control();
            break;
        }
        time = millis();
        }
      */

      if (dispenseScan == HIGH && dispensePrior == LOW && millis() - time > debounce) { //dispense control conditions
        Serial.println("in this loop");
        switch (eVar) {
          case 0:
            vControl = 2;
            control();
            break;

          case 1:
            vControl = 3;
            control();
            break;
        }
        time = millis();
      }

      eStopPrior = eStopScan;
      dispensePrior = dispenseScan;
    }

    void control () {

      switch (vControl) {
        case 0: //estop case put in another variable for showing last estop state
          eStopZone = HIGH;
          dispenseZone = LOW;
          digitalWrite(dispenseLED, dispenseZone);
          digitalWrite(eStopLED, eStopZone);
          eStopScan = LOW;
          dispenseScan = LOW;
          Serial.println("Case 0");
          //eVar = 1;
          break;

        case 1:
          for (int i = 0; i <= 2; i++) {
            eStopZone = LOW;
            digitalWrite(eStopLED, eStopZone);
            delay(345);
            eStopZone = HIGH;
            digitalWrite(eStopLED, eStopZone);
            delay(345);
            Serial.println("Case 1");
            //Serial.println(i);
          }
          break;

        case 2:
          dispenseZone = HIGH;
          eStopZone = HIGH;
          digitalWrite(eStopLED, eStopZone);
          digitalWrite(dispenseLED, dispenseZone);
          Serial.println("here 1");
          delay(1000);
          Serial.println("here?");
          eStopZone = LOW;
          digitalWrite(eStopLED, eStopZone);
          Serial.println("Case 2");
          break;

        case 3:
          dispenseZone = HIGH;
          eStopZone = LOW;
          digitalWrite(eStopLED, eStopZone);
          digitalWrite(dispenseLED, dispenseZone);
          eVar = 0;
          Serial.println("Case 3");
          // make led go green
          break;
      }
      time = millis();
      loop();
    }

    void emergency () {
      Serial.println("interrupt");
      vControl = 0;
      control();
    }

Com window from debugging

    in this loop
    here 1
    here?
    Case 2
    in this loop
    here 1
    here?
    Case 2
    in this loop
    here 1
    interrupt
    interrupt
    interrupt
    here?
    Case 2

body:
Your explanation of what you expect to happen is not very clear but I'll take a stab at your question.

First thing - Interrupt Service Routines (ISR) need to be *short* (execution time, not necessarily code length). Do the minimum necessary to save whatever status or data caused the interrupt and exit. Let the background (your main sketch) handle any further processing resulting from the interrupt.

That means the ISR has to leave some indication - a boolean flag, f/ex - that it did something, and your background has to check that frequently, act on it when it changes, and reset it for the next interrupt.

It looks like your ISR is calling into your background code, which effectively becomes part of the ISR, runs at interrupt level, prevents further interrupts while it is doing so, and (possibly) returns to your background code at a place or in a state that is no longer relevant by then.

Think about organizing your code so that the background does whatever ongoing, routine tasks you need it to be doing, but checking frequently for whether an interrupt has occurred yet. When one has, do whatever needs to done to handle it, reset the "interrupt has occurred" flag, and return to your background task(s).


body:
I cannot see what actually goes wrong, but you're calling way too much stuff in your ISR. You're changing non-volatile variables with the `control()` call in your ISR, leading to undefined behaviour: You don't know _when_ the ISR is being called, especially not whether it is called before or after the non-volatile variables have been transferred from memory to the registers or back in the routine started from `loop()`. Also: Never output anything from an ISR nor from code you call from that ISR. Serial communication is slooow (compared to what the processor could be doing in that time frame).

I'd say: The only thing your ISR should do is to add 1 to a volatile variable, then end. In your `loop()`, check whether that volatile variable is greater than 0, then reset the volatile variable back to 0 and run what you've got in your current ISR. To react to the interrupt in a timely manner, this also means that you should not use `delay()` anywhere in your code. This would put your code back into defined behaviour, at least.


message:
Is it possible to get values only during vibration/movement from an Accelerometer(ADXL335/MPU6050)?

I'm trying to make a wearable motion sensor using ESP32 board and ADXL335 Accelerometer.

Presently when I'm serial printing the output I'm getting the tilt value as well, which have different values at different orientation (I'm printing average of the X,Y & Z). So when I try to light up an led by setting a threshold the average value is different in different orientation.

Is there way to get values only during vibration and be zero when there is no vibration/body movement.

Thanks in advance guys for the help.

body:
Acceleration is a vector quantity. Therefore, instead of looking at the average values of X,Y, and Z, you should probably look at the magnitude of the acceleration vector, that is (X^2+Y^2+Z^2)^0.5. Then, you can set an acceleration threshold below which you would send no data.

The benefit of using the magnitude of the acceleration vector is that it is independent of the orientation of the device. For example, if you placed the device on a table along the X-axis, the accelerometer would read something like X = -g, Y=0, Z=0, where g is the gravitational acceleration. Similarly, if you placed the device on a table at 45 degrees between X and Y axes, the accelerometer would read something like X = -g sqrt(2)/2, Y=-g sqrt(2)/2, Z=0. In both cases, the magnitude of the acceleration vector is just g. On the other hand, the average values would be -g/3 and -g sqrt(2)/3, respectively, as you observed in "...the average value is different in different orientation."


body:
Yes.

**Linear Acceleration at given axis = Actual Acceleration - Gravitational Acceleration**

Gravitational Acceleration across any Axis = Magnitude of Gravity Vector x Cosine of axis angle with the Gravity Vector


message:
Bootloader difference between Atmel328p(through hole) and Atmel328p au(smd)

It’s been bugging me lot that Can’t we burn the same bootloader for both 328p and 328p au?

I got confused when I see this link[smd 328p au bootloader burn][1].

Will there be any impact on performance or any other impact if I use same bootloader for both?

  [1]: http://www.electronoobs.com/eng_arduino_tut6.php

body:
The bootloader doesn't care about how many pins the device has. All it cares about is the UART pins, and they are the same.

Internally the two chips are the same, it's just the packaging that is different. They take the same silicon chip and mount it on a different lead frame and encapsulate it in epoxy. Which is why the only pin differences are a couple of extra power and ground pins, and two dedicated ADC pins that they don't connect in the DIP package.  Even the pins are in the same order around the chip if you examine the pinouts in the datasheet.

Whether you use the DIP (Uno) or the SMD (Nano) bootloader it makes no difference (the two bootloaders are the same anyway). There can be no "perform better" anyway, since that isn't a valid concept. Either it is compatible, in which case it will work, or it's not, in which case it won't.

The only real thing of concern is to ensure that your fuses are set correctly for your chosen clock source, and that the bootloader you install is compiled to run at the speed of your chosen clock source. That has nothing at all to do with which chip it is you are using, but how you have designed your circuit.


body:
Two different bootloaders are used for ATmega328p. One is used in Uno, it is based on Optiboot 4. Second is used in Arduio Nano and is based on Atmel bootloader. Arduino replaced the old Nano bootloader with the Uno Optiboot bootloader in 2018, but Nano clones and old Nanos still in use have the old bootloader. In current AVR boards package version there is a bootloader selection in Tools menu.

With the burn of bootloader fuses are written to set the bootloader area size.

The old Nano bootloader is 2 kB large. The Optiboot bootloader is 0.5 kB large (small). But Arduino didn't change for Nano the size of the flash memory reserved for bootloader so 1.5 kB of flash memory is lost because of inaccurate fuse setting.

The old Nano bootloader didn't reset the watchdog flag. If your sketch setup the watchdog for some short time, after the reset the watchdog did reset the MCU while still in bootloader ending in endless reset loop.

The tutorial in your question would flash the Nano bootloader, because the author of the tutorial has Nano as target board while burning the bootloader. In 2017 it would be the Old bootloader.

So the Uno bootloader is recommended for ATmega328p with Uno fuse settings for bootloader size. After uploading the "Arduino as ISP" sketch and before activating "Burn bootloader" change the board selection to Uno.

Notes:

* For ATmege328p with different frequency then 16 MHz the bootloader must by build with the required frequency.
* there are newer versions of Optiboot (7 is current) with additional options. Some of the options result in larger bootloader.


message:
Multiple Time-Sensitive Tasks

I'm using an Arduino Leonardo and need to perform two time-sensitive tasks like this:

    // Task 1 - Gets executed once a second (1Hz)
    // Execution of task needs approx 70ms
       task1(); //Sending a message via Serial

    // Task 2 - Gets executed 50 times a second (50Hz)
    // Execution of task need a few micros
       task2(); //digitalWrite

As you can see, the problem is, that task one needs very long for execution and therefore task2 is executed too late to send a 50Hz signal. I'm not sure how, but I think there must be a way to give task 1 higher priority to interrupt task 2?

Thanks in advance! :)

**Just for completion**, here is my (not so clean) code:

    #include <SoftwareSerial.h>
    SoftwareSerial mySerial(7, 6); //232_TX,232_

    int triggerFreq = 10;
    unsigned long timestamp_pps;
    unsigned long timestamp;
    unsigned long triggerStartTime;
    const unsigned long dt_pps = 1000000; //micros
    const unsigned long dt_trig = 1000000/triggerFreq; //micros
    unsigned long ts_pps_high;
    unsigned long ts_pps_low;
    unsigned long ts_msg_high;
    unsigned long ts_msg_low;

    unsigned long i_pps = 0;
    unsigned long i_trig = 0;

    int hh = 04;
    int mm = 51;
    int ss = 00;
    unsigned int pos = 2307;
    bool msg;
    bool trigMsgSent;

    void setup() {
      // put your setup code here, to run once:
      pinMode(11, OUTPUT); // PPS
      pinMode(12, OUTPUT); // Indicator of msg_sent
      pinMode(13, OUTPUT); // FPS
      Serial.begin(9600);
      mySerial.begin(9600);
      triggerStartTime = micros();
    }

    void loop() {
      // ================== Part for the GPS Simulation ==================
      timestamp_pps = micros()-triggerStartTime;
      if (timestamp_pps>= dt_pps*i_pps+350000)
      {
        pos += 1;
        digitalWrite(12,HIGH);
        i_pps +=1;
        if (ss == 59)
        {
          ss=0;
          if (mm==59)
          {
            mm=0;
            hh+=1;
          }
          else mm+=1;
        }
        else ss+=1;

        ts_msg_high = micros();
        mySerial.print("$GPRMC,");
        if (hh<10) mySerial.print(F("0"));
        mySerial.print(hh);
        if (mm<10) mySerial.print(F("0"));
        mySerial.print(mm);
        if (ss<10) mySerial.print(F("0"));
        mySerial.print(ss);
        mySerial.print(".000,A,3015.");
        mySerial.print(pos);
        mySerial.println(",N,09749.2872,W,0.67,161.46,030913,,,A*7C");

        // Print Debug Messages
        digitalWrite(12,LOW);
        ts_msg_low=micros();
        Serial.print("PPS at: ");
        Serial.print(ts_pps_high);
        Serial.print("\t PPS low after: ");
        Serial.print(ts_pps_low-ts_pps_high);
        Serial.print("\t MSG high after: ");
        Serial.print(ts_msg_high-ts_pps_high);
        Serial.print("\t MSG low after: ");
        Serial.print(ts_msg_low-ts_pps_high);
        Serial.print("$GPRMC,");
        if (hh<10) Serial.print(F("0"));
        Serial.print(hh);
        if (mm<10) Serial.print(F("0"));
        Serial.print(mm);
        if (ss<10) Serial.print(F("0"));
        Serial.print(ss);
        Serial.print(".000,A,3015.");
        Serial.print(pos);
        Serial.println(",N,09749.2872,W,0.67,161.46,030913,,,A*7C");
      }
      else if (timestamp_pps>=dt_pps*i_pps+100000)
      {
        digitalWrite(11,LOW);
        if (msg==true)
        {
          msg = false;
          ts_pps_low = micros();
        }

      }
      else if (timestamp_pps>=dt_pps*i_pps)
      {
        digitalWrite(11,HIGH);
        if (msg==false)
        {
          msg = true;
          ts_pps_high = micros();
        }
      }
      // ================== Part for the FPS Trigger ==================
      timestamp = micros()-triggerStartTime;
      if (timestamp>= dt_trig*i_trig+2000)
      {
        digitalWrite(13,LOW);
        i_trig +=1;
        trigMsgSent = false;
      }
      else if (timestamp >=dt_trig*i_trig)
      {
        digitalWrite(13,HIGH);
        if (trigMsgSent == false)
        {
          Serial.print("FPS at: ");
          Serial.println(micros());
          trigMsgSent = true;
        }
      }

    }

----------
**Update:** So i implemented it with an interrupt according to [this example](https://www.instructables.com/id/Arduino-Timer-Interrupts/). I just programmed the interrupt for the 50Hz signal, because that one must be accurate. The code is at the end. However, I'm still experiencing the 50Hz signal to be late when the serial is sent. It's now in the dimensions of half a millisecond, but that's not negligible in my project (Sensor fusion computer vision). The output of my post-processing-tool shows:

    Trigger Nr. 25 is 646.912us late!
    Trigger Nr. 28 is 434.176us late!
    Trigger Nr. 75 is 653.056us late!
    Trigger Nr. 78 is 429.056us late!
    Trigger Nr. 125 is 646.912us late!
    Trigger Nr. 128 is 434.944us late!
    Trigger Nr. 175 is 646.912us late!
    Trigger Nr. 178 is 439.04us late!
    Trigger Nr. 225 is 646.912us late!
    Trigger Nr. 228 is 440.064us late!
    Trigger Nr. 275 is 647.168us late!
    Trigger Nr. 278 is 434.944us late!
    Trigger Nr. 325 is 611.84us late!
    Trigger Nr. 328 is 462.08us late!
    Trigger Nr. 375 is 612.864us late!
    Trigger Nr. 378 is 475.136us late!
    Trigger Nr. 425 is 619.008us late!
    Trigger Nr. 428 is 473.856us late!
    Trigger Nr. 475 is 613.888us late!
    Trigger Nr. 478 is 467.968us late!
    Trigger Nr. 525 is 612.864us late!
    Trigger Nr. 528 is 474.88us late!
    Trigger Nr. 575 is 613.12us late!

Does anyone know how I could improve my code?

Code:

    //GPS DEFINITIONS
    #include <SoftwareSerial.h>
    SoftwareSerial mySerial(7, 6); //232_TX,232_

    int triggerFreq = 50;
    unsigned long timestamp_pps;
    //unsigned long timestamp;
    unsigned long triggerStartTime;
    const unsigned long dt_pps = 1000000; //micros
    //const unsigned long dt_trig = 1000000/triggerFreq; //micros
    unsigned long ts_pps_high;
    unsigned long ts_pps_low;
    unsigned long ts_msg_high;
    unsigned long ts_msg_low;

    unsigned long i_pps = 0;
    //unsigned long i_trig = 0;

    int hh = 04;
    int mm = 51;
    int ss = 00;
    unsigned int pos = 2307;
    bool msg;
    bool trigMsgSent;

    void setup() {

      cli();//stop interrupts
      //set timer1 interrupt at 1Hz
      TCCR1A = 0;// set entire TCCR1A register to 0
      TCCR1B = 0;// same for TCCR1B
      TCNT1  = 0;//initialize counter value to 0
      // set compare match register for 1hz increments
      //OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
      OCR1A = 19999; // = (16*10^6) / (100 * 8) -1 (must be <65536)
      // turn on CTC mode
      TCCR1B |= (1 << WGM12);
      // Set CS11 bit for 8 prescaler
      TCCR1B |= (1 << CS11);
      // enable timer compare interrupt
      TIMSK1 |= (1 << OCIE1A);
      sei();//allow interrupts

      // GPS SETUP
      pinMode(11, OUTPUT); // PPS
      pinMode(12, OUTPUT); // Indicator of msg_sent
      pinMode(13, OUTPUT); // FPS
      Serial.begin(9600);
      mySerial.begin(9600);
      triggerStartTime = micros();

    }

    ISR(TIMER1_COMPA_vect){  //change the 0 to 1 for timer1 and 2 for timer2
       //interrupt commands here
       digitalWrite(13,!digitalRead(13));
    }

    void loop() {
      // ================== Part for the GPS Simulation ==================
      timestamp_pps = micros()-triggerStartTime;
      if (timestamp_pps>= dt_pps*i_pps+350000)
      {
        pos += 1;
        digitalWrite(12,HIGH);
        i_pps +=1;
        if (ss == 59)
        {
          ss=0;
          if (mm==59)
          {
            mm=0;
            hh+=1;
          }
          else mm+=1;
        }
        else ss+=1;

        ts_msg_high = micros();
        mySerial.print("$GPRMC,");
        if (hh<10) mySerial.print(F("0"));
        mySerial.print(hh);
        if (mm<10) mySerial.print(F("0"));
        mySerial.print(mm);
        if (ss<10) mySerial.print(F("0"));
        mySerial.print(ss);
        mySerial.print(".000,A,3015.");
        mySerial.print(pos);
        mySerial.println(",N,09749.2872,W,0.67,161.46,030913,,,A*7C");

        // Print Debug Messages
        digitalWrite(12,LOW);
        ts_msg_low=micros();
        Serial.print("PPS at: ");
        Serial.print(ts_pps_high);
        Serial.print("\t PPS low after: ");
        Serial.print(ts_pps_low-ts_pps_high);
        Serial.print("\t MSG high after: ");
        Serial.print(ts_msg_high-ts_pps_high);
        Serial.print("\t MSG low after: ");
        Serial.print(ts_msg_low-ts_pps_high);
        Serial.print("$GPRMC,");
        if (hh<10) Serial.print(F("0"));
        Serial.print(hh);
        if (mm<10) Serial.print(F("0"));
        Serial.print(mm);
        if (ss<10) Serial.print(F("0"));
        Serial.print(ss);
        Serial.print(".000,A,3015.");
        Serial.print(pos);
        Serial.println(",N,09749.2872,W,0.67,161.46,030913,,,A*7C");
      }
      else if (timestamp_pps>=dt_pps*i_pps+100000)
      {
        digitalWrite(11,LOW);
        if (msg==true)
        {
          msg = false;
          ts_pps_low = micros();
        }

      }
      else if (timestamp_pps>=dt_pps*i_pps)
      {
        digitalWrite(11,HIGH);
        if (msg==false)
        {
          msg = true;
          ts_pps_high = micros();
        }
      }

    }

body:
Two possible solutions:

1. Split the serial string in small pieces so it's (comfortably) less than 50 ms and send the string in 'pieces' … you could even send it until e.g. 45 ms has been reached and continue in the next round. Use the Blink Without Delay mechanism to switch between the tasks.
2. More robust solution: Make Task 2 an interrupt... This is probably much easier, since you can keep sending the serial string and the MCU takes care of automatically starting the interrupt each 50 ms. Make sure the interrupt code is very short. When it is finished, it will automatically resume with the normal code (sending serial data). I have not checked this library, but it seems very simple to use: https://playground.arduino.cc/Code/Timer/ .


body:
Here lies your ≈ ½ ms problem:

> `#include <SoftwareSerial.h>`

SoftwareSerial is very time sensitive. It generates the serial stream by
bit-banging, _with interrupts disabled_. For each byte sent, interrupts
are disabled just before sending the start bit, and re-enabled just
after the stop bit has been written. At 9600 bps, interrupts are
thus disabled for a little more than 9 bit times on each byte, i.e.
936 µs.

Do not use SoftwareSerial if you need short interrupt latency. Use a
hardware serial port instead. This can be problematic on the Uno, where
you would loose the ability to send debugging info, but it is fine on
the Leonardo.

Alternatively, if the _only_ thing your ISR has to do is toggle a pin,
you can instead configure the timer to generate that as PWM. This way
the CPU is not involved at all in the pin toggling, and you get
cycle-accurate signal timing irrespective of interrupt latency.

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

**Edit**: Answering your comment.

About the hardware serial ports: on the Uno you just have `Serial`, so
you are out of luck if you want one port for outputting NMEA sentences
and another one for debugging information. However, on the Leonardo,
`Serial` is a virtual serial port emulated over USB. The real hardware
serial port is called `Serial1`, and you should use it in preference to
a `SoftwareSerial` instance.

About “more than just toggle the pin”: You may still be able to use PWM
if whatever other stuff task2 has to perform is less time-critical than
toggling the pin. In this case, you use PWM to toggle the pin on the
`TIMER1_COMPA` event, and `ISR(TIMER1_COMPA_vect)` to do the other
stuff. Then, each time the timer hits `TIMER1_COMPA`, it will
immediately toggle the pin and, _at the same time_, rise an interrupt
request. The CPU may take some time to service the request, but this
delay could be acceptable if only the toggling needs extra-accurate
timing.


message:
Arduino encrypted Radio communication

Is there any way or library to communicate two Arduino devices with encrypted connection using modules NRF24L01 or "433Mhz RF" ? Similar encryption like CCMP in Wi-Fi network.

body:
Communicating and Encryption are to completely separate things. How you communicate (with what device) has no relevance to encryption. True, there are devices that can themselves encrypt data, but they tend to be higher-end or geared towards a specific purpose (such as WiFi).

What you send is just data. What that data consists of is entirely up to you.  If you want your communications encrypted then send encrypted data before sending it and decrypt it after receiving it.

Of course, you have to then consider such things as sharing of keys, etc.

There are numerous ways of encrypting data, but one of the easiest to implement on Arduino is AES, for which there is a library [here](https://spaniakos.github.io/AES/index.html).


message:
How to prevent the garbage data when the serial port is initialised?

I use Arduino Uno. I get garbage in Serial Monitor or HyperTerminal right after I connect to the port. Here is an example code:

    void setup() {
      // initialize serial:
      Serial.begin(57600);

    }

    void loop() {

        Serial.println("Test");
    }

An example screenshot of the output. When port is re-connected the first received data is not Test:

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

So my problem is when the port is initialised the first data received is garbage. Is there a way to prevent this happening? Is that something to do with bootloader baud rate? I tried other baud rates and get same issue and I really want to use 57600 or 115200 baud rate.

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

body:
Your use of the terminology in your edited post and comments is problematic because you are not being clear enough. For example:

"*I mean during Serial.begin(57600); I get garbage values. How can I skip this?* " and "*If I comment out I get nothing*".

"*By "When port is re-connected" means clicking "call" in HyperTerminal or openning Arduino serial monitor. First data is always garbage"*. There are others."

"*An example screenshot of the output. When port is re-connected the first received data is not Test:*" - But, the first received data you are showing is, in fact, the word Test.

There are others.

I will try to help by answering your main question which seems to be "**How to prevent the garbage data**" and note that I have not included "*when the serial port is initialized*".

Firstly, when I use my Uno and V 1.8.13 of the IDE, and I compile and run your sample program, I get the usual output showing progress of the compilation and upload to the board, and that text ends with "avrdude done.  Thank you." At this point, the program is running and println is doing its thing.

When I open the serial monitor (by clicking on the box in the upper right corner of the full IDE screen - baud rate=57600, no line ending), I get corrupt characters at first. This always happens and I believe that is what you are seeing.

This happens because when you open the serial monitor, the UNO is being reset, but it is not the complete reset that is done when you upload code and begin execution. To be a bit simplistic, when you open the serial monitor, your program is running and the reset from opening the serial monitor is not the clean start that is done when you compile, upload and begin to execute the program.

Use either of these programs to test out what I am getting at.

    void setup() {
      // initialize serial:
      Serial.begin(57600);
    }

    void loop() {
        delay(10000);
        while(1){
        Serial.println("Test");
        }
    }

or

    void setup() {
      // initialize serial:
      Serial.begin(57600);
      delay(10000);
    }

    void loop() {
      Serial.println("Test");
    }

Go through your steps with either of these modified versions and open the serial monitor during the 10 second delay (unclick autoscroll to make it easier to see) and you will not get any corruption.

If, however, you compile/load/execute the program and then start opening and closing the serial monitor, you will start to see corruption in subsequent opens of the serial monitor - again because the reset when you open the serial monitor is not the clean reset that is done when you compile/load/execute.

Why doesn't everybody complain like crazy about the problem that you are experiencing? I think because folks learns to work with/around the way the UNO works. Your code just sends out serial data, so it is a prominent illustration of the issue, but it is not an insurmountable issue.

You can go deep into the serial monitor code and learn all about what is going on and come up with an elegant and likely tedious solution - I'm not sure, but I don't doubt that some have done this and it may even involve some hardware manipulation of serial control lines.

Alternatively, you can write the program to allow time to complete the serial monitor opening before you start sending out the data. You can even clean out any residual data (as long as you know what you are doing) if you anticipate multiple opening and closings.

Hope it helps.