# Question
Title: Is it possible to use a slide switch without a resistor?
I understand how pullup and pulldown resistors work with push buttons and I also understand that an analogous idea can be applied to slide switches. Furthermore, I know that some versions of Arduino have an internal pullup resistor that can be used, if you adjust the code properly.

I was wondering, if I can, without using the internal pullup resistor, wire a slide switch without any kind of resistor like so:

As I understand, this should behave exactly the same as using a pull-down resistor. If the switch is on the left side, pin 7 would read `LOW` and if the switch is on the right side, it would read `HIGH`.

Is that a problem with wiring the switch like this? Is there a reason why using a resistor would be better?

In my final project I intend to use a Digispark board and I would not like to rely on its internal resistor and I also would like to avoid using an external resistor if I can.

# Answer
> 2 votes
You *may* be able to do it, or you may not. It depends on the switch.

There are two classes of slide switch:

* Make-before-break
* Break-before-make

In the former the contact you are sliding to is connected *before* the one you are sliding away from is disconnected. This can cause untold problems as you will basically create a short circuit between 5V and GND. Everything will die.

In the latter the contact you are sliding away from is disconnected first, and then the new contact you are sliding towards is connected. That is safer, but it does mean that there is a short period while you're sliding the switch where neither contact is connected. At this time the input pin is floating - just as if you had nothing connected at all (which is in fact the case).

That is of course not a desirable scenario as it's probably the most amount of bounce you will ever see in a switch - bounce you need to eliminate in software to give you a clean signal.

That period of uncertainty is eliminated if you have a pullup or pulldown resistor, since there is never a period where there is no connection, and there's never a period where you risk shorting out power and ground. All you have to content with then is the natural bounce of the contacts as they close.

---
Tags: arduino-uno, electronics, switch
---


title: In Linux how do I start up Atmel Studio

text:
# Question
Title: In Linux how do I start up Atmel Studio
I am using Linux Fedora 20. In order to compile C programs for the Arduino, as described in the book "C Programming with Arduino" by Warwick A Smith, pub by Elektor, I have downloaded and untarred/unzipped "avr8-gnu-toolchain-3.5.1.1671-linux.any.x86.tar.gz". That's as far as I can get. Please how do I proceed from this point? Is there anything else I need or should have done?

# Answer
https://mil.ufl.edu/374/docs/Install\_Atmel\_Studio\_7.0.pdf :

Note for Mac and Linux Computer Users

If you have a Mac (i.e., a Macintosh computer from Apple) or if you use Linux, you will need an alternate Windows installation or you will need to install a Windows virtual machine in order to then install and run Atmel Studio.

We suggest that you install Boot Camp (free and the best); Parallels (not free) or possibly VMware (not free) may also work. UF offers free copies of Windows 10 Software.

We do not recommend Virtual Box. Wine is another alternative, but this has not been verified to work. (Note: My best students use Boot Camp!)
> 1 votes

# Answer
Atmel Studio is a windows only product. The only way to run it on linux is in a virtual machine running windows.
> -1 votes

---
Tags: arduino-uno, linux, atmel-studio
---


# Question
Title: Can Arduino UNO be used to emulate a PS4 joystick?
**I Want to know if there is a library that can be used in order to make a PS4 controller with Arduino.** I have a PS2 steering wheel and I want to use it thorugh Arduino with PS4. I know that PS4 has his own protocol but I think there may be a way to do it.

Cheers!

**EDIT:** I already have the code for reading the PS2 steering wheel, but now I need to "transform" that into PS4 protocol

# Answer
TLDR: Not sure but the PS4 protocol is known and written for other MCUs, and can be found on github.

Not sure if there is a library for it in Arduino, but there are libraries out there (such as Passing Link) that emulate the protocol on other platforms. You can look at that.

BUT...

PS2 and PS4 are completely different beasts. PS2 uses SPI for its protocol. PS4 uses USB with specific USB drivers. Even if you manage to get the PS4 protocol working, the next problem is authenticating you are a legit/licensed controller. For every legit controller, there lies a security chip inside. And that chip also has a proprietary way to be talked to as well. When a legit controller is talking to a PS4, the PS4 will sometimes ask for the contents in the security chip for authentication. If you can't deliver the contents it wants, your controller is locked out until next power up (maybe even next PS4 power up, not sure).

So while it may be possible, the two huge hurdles are:

1. Implementing the USB code properly with custom drivers defined by Sony.
2. Circumventing the security chip by either ripping contents off a legit controller or mining it and placing it in your own circuit. Both of which will require an understanding how how to communicate with said chip.
> 2 votes

---
Tags: usb, joystick
---


# Question
Title: U-Blox Neo M8N GNSS-GPS interface with ESP32-TTGO-T-CALL
I have tried contacting the manufacturers as well as many Google searches. I have tried many different libraries to get this GNSS-GPS working.

**Libraries I've Tried:**

* Arduino\_GPS
* Arduino\_Parser\_Ublox\_Neo\_M8N
* esp32-ublox
* MicroNMEA
* NEO-M8N
* NeoGPS
* UBLOX-NEO-M8N

**The library I am trying now:**

* Parser\_Ublox\_Neo\_M8N *with:*
* ESPSoftwareSerial

(I have a non-AVR board so NeoSWSerial and SoftwareSerial didn't work for me.)

**Link to files on GitHub:** https://github.com/toskyRocker/Arduino\_Parser\_Ublox\_Neo\_M8N

**My questions for someone who has done this before with a U-Blox M8N:**

* Must I use U-Center software to configure the gps before it will output data?
* Does my code look to be functional? I can compile but then when attaching GPS I get the output (as my psuedo error message) that lets me know the serial connection between my TTGO T-Call V1.3 and U-Blox-M8N is not valid. Here is a link to the board I have and the GNSS-GPS:

**Board:** https://www.ebay.com/i/284030711638?chn=ps&norover=1&mkevt=1&mkrid=711-213727-13078-0&mkcid=2&itemid=284030711638&targetid=4580840328168117&device=c&mktype=&googleloc=&poi=&campaignid=403206339&mkgroupid=1235851284533722&rlsatarget=pla-4580840328168117&abcId=9300372&merchantid=51291&msclkid=52c16af1ba571d52ddfe35755ba68854

**GPS:** https://www.bidorbuy.co.za/item/319275677/GYGPSV5\_NEO\_M8N\_NEO\_M8N\_001\_GPS\_Chip\_Module\_for\_APM2\_6\_Flight\_Control.html

(The "\<#include SoftwareSerial.h\>" in the code below is what was added when I used the Arduino IDE's drop down libraries menu when I selected espsoftwareserial to include.)

**Here is the (.ino) code:**

```
#include <SoftwareSerial.h>

#include "Ublox.h"
#define SERIAL_BAUD 115200
#define GPS_BAUD 9600
#define N_INTS 4
//gpsSerial(3,1);
Ublox M8_Gps;
// Altitude - Latitude - Longitude - N Satellites
int gpsArray[N_INTS] = {0, 0, 0, 0};
SoftwareSerial gpsSerial;

/////////////////////////////////////////////////////////////

void setup() {
Serial.begin(SERIAL_BAUD);
gpsSerial.begin(GPS_BAUD,SWSERIAL_8N1,3,1);
//gpsSerial.begin(GPS_BAUD);
pinMode(0,OUTPUT);
}
///////////////////////////////////////////////////////////
void loop() {
digitalWrite(0,LOW);
if(!gpsSerial.available()){
    Serial.print("Problem with GPS ");
}
while(gpsSerial.available()){
    char c = gpsSerial.read();
     if (M8_Gps.encode(c)) {
      gpsArray[0] = M8_Gps.altitude;
      gpsArray[1] = M8_Gps.latitude;
      gpsArray[2] = M8_Gps.longitude;
      gpsArray[3] = M8_Gps.sats_in_use;
    }
 }
 for(byte i = 0; i < N_INTS; i++) {
 Serial.print(gpsArray[i], 10);Serial.print(" ");
 }
 Serial.println("");
 }

```

# Answer
> Must I use U-Center software to configure the gps before it will output data?

No, but it is HIGHLY recommended. It's the only (easy) way to change the baudrate, and the only (easy) way to change what messages are output over serial.

> Does my code look to be functional?

I can't answer 100%, as I have not used that library before, but the problem I did run into with the NEO-M8N and multiple libraries I tried (MicroNMEA, TinyGPS, TinyGPS++, ...) was that as a multi-constellation GNSS receiver that can receive more satellite constellations than just GPS, it by default outputs $GNGGA. These libraries I had tried using only decoded the old standard $GPGGA, and ignored the more universal ones.

Here is how you can use U-Center to verify this is the problem, and if so how to configure your module to output GPGGA messages that these libraries will parse:

1. Connect to your NEO-M8N using U-center. (Usb is pprefered, but serial will work fine too)
2. Confirm that this is the problem by clicking View -\> Messages View.
3. You should see either GPGGA or GNGGA messages being received.

If you are currently getting GNGGA, here is how to switch them to GPGGA:

1. View -\> configuration View
2. Click on "NMEA (NMEA Protocol) config entry
3. Click "Poll" at the bottom to pull the current settings from your device.
4. Change the "Main Talker ID" to "1 - GP (GPS)"
5. Change the "GSV Talker ID" to "1 - Use main talker ID"
6. Click "Send" at the bottom to upload your changes.
7. Click on the "CFG (Configuration)" config entry
8. Choose "Save current configuration" and then "Send" at the bottom.

Now just use the method above to verify what NMEA packets you are receiving!

Now that you're in U-Center, I'd recommend also checking out the GNSS config, to enable the use of more satellites (GPS, Glonass, Galileo) and set the SBAS config depending on your location. (In the US, setting to WAAS may help it lock on quicker as it won't bother searching for other SBAS sources) You can also change the baud rates for different ports under "PORTS", increase or decrease the frequency of sending location updates under "RATE" and enable or disable individual NMEA messages for each port under "MSG"
> 1 votes

---
Tags: esp32, gps
---


# Question
Title: Instances of a class inside another class - is there a way to control the amount?
I have a class with 12 instances of a button, to create a keypad( meaning that this is the only case I use 12 instances). But this class can be just a button array of any other number between 1-12. I'm looking for a way to minimize class overhead of 12 instances, when I most of the time use much less.

'.h' file:

```
class buttonArrayTFT
{
public:
  buttonArrayTFT(XPT2046_Touchscreen &_ts = ts, Adafruit_ILI9341 &_tft = tft);
  void create_array(uint8_t R, uint8_t C, char *but_txt[]);
  uint8_t checkPress(TS_Point &p);

public:

protected:
  ButtonTFT _button0;
  ButtonTFT *_buttons[12] = {&_button0, &_button1, &_button2, &_button3,
                             &_button4, &_button5, &_button6, &_button7,
                             &_button8, &_button9, &_button10, &_button11};
private:
  ButtonTFT _button1;
  ButtonTFT _button2;
  ButtonTFT _button3;
  ButtonTFT _button4;
  ButtonTFT _button5;
  ButtonTFT _button6;
  ButtonTFT _button7;
  ButtonTFT _button8;
  ButtonTFT _button9;
  ButtonTFT _button10;
  ButtonTFT _button11;

private:
  uint8_t _num_items = 0;
};

```

# Answer
> 4 votes
As pointed out in a comment on your original question, a **template** is likely the best solution.

Templates allow you to write highly flexible code. I won't explain why; that's something that goes a little beyond the actual question. However, the following will show that you can create a template that means you can create a `buttonArrayTFT` class with *N* number of `buttonTFT` elements, so long as *N* is known at compile time. The link given as a comment talks describes various aspects of templates but does not necessarily explain how to string it all together.

From the section **Non-type parameters for templates**, you will see that you can specify an integer as a parameter for creating *N* elements of an array member variable.

But what about the *type parameter, T*? You can simply omit it. You don't actually have to create a template for a *type*.

In your *.h* file:

```
template <uint8_t ARRAY_SIZE>
class buttonArrayTFT
{
public:
// One thing to remember about templates: you have to pack the definition
// into the header file with the declaration to avoid all manner of headaches.

    buttonArrayTFT(XPT2046_Touchscreen &_ts = ts, Adafruit_ILI9341 &_tft = tft)
    {
    // Perhaps this is a good opportunity to check that the specified
    // size of the array is sensible, i.e. not zero and no more than 12.
        if ((ARRAY_SIZE == 0) || (ARRAY_SIZE > 12))
        {
            // decide how you want to handle this problem
        }
            // Add the rest of your constructor here
    }

    void create_array(uint8_t R, uint8_t C, char *but_txt[]);
    uint8_t checkPress(TS_Point &p);

    // This little piece of magic allows you to access buttonTFT 'x' of the
    // private _buttonArray as if a buttonArrayTFT class was an array
    buttonTFT &operator[](uint8_t index)
    {
    // Check that 'index' is a valid element in the array
        if (index > _num_items)
        {
            // decide how you want to handle this problem
        }
        return _buttonArray[index];
    }
private:
    buttonTFT _buttonArray [ARRAY_SIZE];
    // I recommend making this constant
    const uint8_t _num_items = ARRAY_SIZE;
};

```

I shall leave it up to you to sort out your privates, publics and protecteds, and I have left out `ButtonTFT _button0;` to keep you on your toes.

You'll also notice that the array is private, as before, but there is now no array-of-pointers-to-buttons. This is because there is no need; the magic `buttonTFT &operator[](int index)` allows you to access array elements directly.

In your *.ino* file, or as appropriate, you use the following code to create and then wield the class:

```
buttonArrayTFT<4> myFourButtonArray(/* constructor arguments as required*/);
buttonArrayTFT<12> myTwelveButtonArray(/* constructor arguments as required*/);

```

This gives you two instances of the class, with the respective number of `buttonTFT` elements! You can now access specific buttons using the following code:

```
myFourButtonArray[0];    // Returns a reference to the first buttonTFT
myTwelveButtonArray[10]; // Returns a reference to the eleventh buttonTFT
myFourButtonArray[n]     // Returns a reference to the 'n+1'th buttonTFT

```

On the assumption that the `buttonTFT` class has some kind of 'read' function that returns a TRUE or FALSE for the status of the button, you can write:

```
if (myFourButtonArray[0].read())
{
    // executed if the button is ON
}
else
{
    // executed if the button is OFF
}

```

**A NOTE ON CONST-NESS:**

The overloading of `operator[]`, while wonderfully magic, is open to abuse. However, this is no different from your original code. The array of `buttonTFT` elements is private but there is public access to all the buttons almost as if the array was not private. In the case of your original code, one could write:

```
myButtonArray._buttons[0] = myButtonArray._buttons[1];

```

Now `_buttons[0]` *points to the same buttonTFT* as `_buttons[1]`.

Ouch. Now `myButtonArray._buttons[0]->read()` is literally the same thing as `myButtonArray._buttons[1]->read()`.

That said, my code does not make it a great deal better; the equivalent code:

```
myFourButtonArray[0] = myFourButtonArray[1];

```

Simply *copies* the right hand side over to the left hand side. You still have two distinct `buttonTFT` instances, with probably no memory leaks, but I am guessing that `buttonTFT` class may contain a reference to an Input pin, so the `_button[0]` pin will now be whatever `_button[1]` pin is because the member variable that stores the pin reference will be overwritten.

To solve this weakness, simply add the `const` qualifier to the beginning of the `operator[]` overload:

```
const buttonTFT &operator[](uint8_t index)
{ // };

```

Now the `buttonTFT` element cannot be altered. This of course brings in a new headache that all functions that rely on `myArray[n]` also need to be constant. It is up to you to determine how constant correctness should be interpreted and whether it is worth the hassle.

# Answer
> 4 votes
You can use a *template* class to provide compile time parameters to your class to tune it. This is most often used in the context of providing a *type* for the class to operate on. However it's not limited to that. It's also often used to provide a storage size or other similar constant to the class.

They kind of work like preprocessor macros. You specify a token in the class and then give that token a value when you instantiate an object. That token can then be used all over the place in your class.

In your case you can provide the number of elements in your array of buttons as a template variable, for example (note: untested):

```
template <int N> class buttonArrayTFT {
    protected:
        ButtonTFT _buttons[N];
    public:
        void doSomething();
};

template <int N> void buttonArrayTFT::doSomething() {
    for (int i = 0; i < N; i++) {
        _buttons[i].doSomethingOnAButton();
    }
}

```

Of course you have to treat your objects a little differently since you can't make an array of pointers to predefined objects any more. Instead just a simple array of objects should be enough.

You then instantiate your class passing the number of elements you want:

```
// Array of 12 buttons
buttonArrayTFT<12> myButtons;
// and do something
myButtons.doSomething();

```

# Answer
> 2 votes
There are more options to solve your question.

---

To use a template as recommended in the other answers is a fancy option, but if you use a template multiple times, it creates a real class for every template value and you will see it on used flash size.

---

The best option in my opinion is to provide the array to the class over a constructor. Create a global array of buttons and hand it over to buttonArrayTFT object over a constructor.

```
const uint8_t BUTTON_COUNT = 12;
ButtonTFT buttons[BUTTON_COUNT];
ButtonArrayTFT buttonArrayTFT(buttons, BUTTON_COUNT);

```

The ButtonArrayTFT class (simplified) would be like:

```
class ButtonArrayTFT {
private:
  ButtonTFT *buttons;
  uint8_t count;
public:
  ButtonArrayTFT(ButtonTFT *_buttons, uint8_t _count) {
    buttons = _buttons;
    count = _count;
  }

```

---

Other option is to use dynamic allocation on heap. If you would create a ButtonArrayTFT object only once at start and never delete it it would not cause heap fragmentation.

```
class ButtonArrayTFT {
private:
  ButtonTFT *buttons;
  uint8_t count;
public:
  ButtonArrayTFT(uint8_t _count) {
    count = _count;
    buttons = new ButtonTFT[count];
  }

```

# Answer
> 0 votes
I want to share my final updated library (thanks to answers by Majenko&Charlie), perhaps it'll help others.

`.h` file

```
template <uint8_t N>
class buttonArray_TFT
{
public:
  int8_t dx = 5;         /* define spacing between buttons */
  int8_t dy = 5;         /* define spacing between buttons */
  uint8_t scale_f = 100; /* change the cale of array. 100% take entire screen */
  uint8_t shift_y = 255; /* Shifts in y director*/
  uint8_t shift_x = 255; /* Shifts in x director*/
  int shrink_shift = 0;  /* shrink array in pixels, and shifts up/ down (+/-) */

  uint8_t &a = butarray[0].a;
  uint8_t &b = butarray[0].b;
  uint8_t &txt_size = butarray[0].txt_size;
  uint16_t &txt_color = butarray[0].txt_color;
  uint16_t &border_color = butarray[0].border_color;
  uint16_t &face_color = butarray[0].face_color;
  bool &roundRect = butarray[0].roundRect;

protected:
  ButtonTFT butarray[N];

public:
  buttonArray_TFT(XPT2046_Touchscreen &_ts = ts, Adafruit_ILI9341 &_tft = tft);
  void create_array(uint8_t R, uint8_t C, char *but_txt[]);
  uint8_t checkPress(TS_Point &p);
};

```

and more in : `.h` file :

```
template <uint8_t N>
buttonArray_TFT<N>::buttonArray_TFT(XPT2046_Touchscreen &_ts, Adafruit_ILI9341 &_tft)
{
  for (int i = 0; i < N; i++)
  {
    butarray[i].TS[0] = &ts;
    butarray[i].TFT[0] = &tft;
  }
}

template <uint8_t N>
void buttonArray_TFT<N>::create_array(uint8_t R, uint8_t C, char *but_txt[])
{
\\ Code
}

template <uint8_t N>
uint8_t buttonArray_TFT<N>::checkPress(TS_Point &p)
{
  for (uint8_t i = 0; i < N; i++)
  {
    if (butarray[i].checkPress(p))
    {
      return i;
    }
  }
  return 99;
}

```

---
Tags: c++, class
---


# Question
Title: Arduino Nano I2C OLED display 0.96 inches 128x64 pixels
I have a strange issue while trying to run the hello world code on an arduino nano connected to an OLED display.

This is the code I used:

```
    #include <Adafruit_SSD1306.h>
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 64, &Wire);

void setup() {

  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Address 0x3C for 128x32

  display.display();
  delay(2000);

  display.clearDisplay();      //this line to clear previous logo
  display.setTextColor(WHITE); //without this no display
  display.print("Hello World!");//your TEXT here
  display.display();            //to shows or update your TEXT
}

void loop() {

 }

```

But I get this on the display.

Any idea what I could be missing?

Thanks !

# Answer
Mystery solved :)

After some more reading it appears that the display driver is actually SH1106, so after using the right library I got the display working.
> 1 votes

---
Tags: arduino-nano, oled
---


# Question
Title: Can't enable face detection on esp32 cam : CORRUPT HEAP: Bad head at 0x3ffe2eb4. Expected 0xabba1234 got 0x00000008 abort()
I was trying to make esp32 face recognition using the esp32 camera web server example in arduino , and everything works fine untill i press on face detection the frame is frozen , module restarted and put this error to serial monitor :

```

CORRUPT HEAP: Bad head at 0x3ffe2eb4. Expected 0xabba1234 got 0x00000008
abort() was called at PC 0x4008a64d on core 1

ELF file SHA256: 0000000000000000

Backtrace: 0x4008df7c:0x3ffe1c30 0x4008e1f5:0x3ffe1c50 0x4008a64d:0x3ffe1c70
0x4008a779:0x3ffe1ca0 0x400f97cb:0x3ffe1cc0 0x400f5a61:0x3ffe1f80 0x400f59f0:0x3ffe1fd0
0x40093545:0x3ffe2000 0x40082976:0x3ffe2020 0x4008a545:0x3ffe2040 0x4000bec7:0x3ffe2060
0x400d1bc9:0x3ffe2080 0x401194f5:0x3ffe2230 0x40119bfd:0x3ffe2260 0x40119cb5:0x3ffe22f0
0x4011a088:0x3ffe2310 0x40118774:0x3ffe2330 0x401187cb:0x3ffe2370 0x4008fe86:0x3ffe2390

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6388
entry 0x400806b4

```

I tried erasing flash bt it made the same error again I am using Arduino IDE 1.8.12 , esp32-cam operating at 5 volts from the programmer (also tried other external power supplies) and these are the pictures of settings : (also used wrover kit in programming settings with huge app \>3mb)

Chip name  ESP32 Cam  FTDI Programmer  AI THINKER  Settings

I want to make a face recognition door lock , if this doesn't work could anyone refer me to how can I get facial recognition on esp32 cam with any other way?

# Answer
I don't have enough reputation to be able to add a comment, but using the answer from Andrew Hart I was able to resolve this. For completeness of this thread in case the linked solution ever disappears:

Locate these sections from the app\_httpd.cpp:

```
if (net_boxes){
    detected = true;
    if(recognition_enabled){
        face_id = run_face_recognition(image_matrix, net_boxes);
    }
    draw_face_boxes(image_matrix, net_boxes, face_id);
    free(net_boxes->score);
    free(net_boxes->box);
    free(net_boxes->landmark);
    free(net_boxes);

```

and

```
fr_recognize = esp_timer_get_time();
draw_face_boxes(image_matrix, net_boxes, face_id);
free(net_boxes->score);
free(net_boxes->box);
free(net_boxes->landmark);
free(net_boxes);

```

replace the 4 `free`'s in each block with `dl_lib_free`.
> 2 votes

# Answer
Rollback your ESP32 board driver to 1.04. works for me ;-)
> 1 votes

# Answer
I ran into this issue with the same setup. This Github issue seems identical to ours, and applying the fix in this comment quickly resolved it for me: https://github.com/espressif/arduino-esp32/issues/5128#issuecomment-851785970. Good luck!
> 0 votes

---
Tags: esp32, espressif, camera, esp
---


# Question
Title: Using millis() and micros() inside an interrupt routine
The documentation for `attachInterrupt()` says:

> ... `millis()` relies on interrupts to count, so it will never increment inside an ISR. Since `delay()` requires interrupts to work, it will not work if called inside an ISR. `micros()` works initially, but will start behaving erratically after 1-2 ms. ...

How does `micros()` differ from `millis()` (except of course for their precision)? Does the above warning mean that using `micros()` inside an interrupt routine is always a bad idea?

Context - I want to measure low pulse occupancy, so I need to trigger my routine when my input signal changes and record the current time.

# Answer
> 20 votes
The other answers are very good, but I want to elaborate on how `micros()` works. It *always* reads the current hardware timer (possibly `TCNT0`) which is constantly being updated by the hardware (in fact, every 4 µs because of the prescaler of 64). It then adds in the Timer 0 overflow count, which is updated by a timer overflow interrupt (multiplied by 256).

Thus, even inside an ISR, you can rely on `micros()` updating. However *if you wait too long* then you miss the overflow update, and then the result returned will go down (i.e you will get 253, 254, 255, 0, 1, 2, 3 etc.)

This is `micros()` \- slightly simplified to remove defines for other processors:

```
unsigned long micros() {
    unsigned long m;
    uint8_t oldSREG = SREG, t;
    cli();
    m = timer0_overflow_count;
    t = TCNT0;
    if ((TIFR0 & _BV(TOV0)) && (t < 255))
        m++;
    SREG = oldSREG;
    return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}

```

The code above allows for the overflow (it checks the TOV0 bit) so it can cope with the overflow while interrupts are off but only **once** \- there is no provision for handling two overflows.

---

**TLDR;**

* Don't do delays inside an ISR
* If you must do them, you can time then with `micros()` but not `millis()`. Also `delayMicroseconds()` is a possibility.
* Don't delay more than 500 µs or so, or you'll miss a timer overflow.
* Even short delays may cause you to you miss incoming serial data (at 115200 baud you will get a new character every 87 µs).

# Answer
> 9 votes
It is not *wrong* to use `millis()` or `micros()` within an interrupt routine.

It *is* wrong to use them incorrectly.

The main thing here is that while you are in an interrupt routine "the clock isn't ticking". `millis()` and `micros()` won't change (well, `micros()` will initially, but once it goes past that magic millisecond point where a millisecond tick is required it all falls apart.)

So you can certainly call on `millis()` or `micros()` to find out the current time within your ISR, but don't expect that time to change.

It is that lack of change in the time that is being warned about in the quote you provide. `delay()` relies on `millis()` changing to know how much time has passed. Since it doesn't change `delay()` can never finish.

So essentially `millis()` and `micros()` will tell you the time *when your ISR was called* no matter when in your ISR you use them.

# Answer
> 6 votes
The quoted phrase is *not* a warning, it is merely a statement about how things work.

There's nothing intrinsically wrong with using `millis()` or `micros()` within a properly-written interrupt routine.

On the other hand, doing anything at all within an improperly-written interrupt routine is by definition wrong.

An interrupt routine that takes more than a few microseconds to do its job is, in all likelihood, improperly written.

In short: A properly-written interrupt routine will not cause or encounter issues with `millis()` or `micros()`.

*Edit:* Regarding “why micros() "starts behaving erratically"”, as explained in an “examination of the Arduino micros function” webpage, `micros()` code on an ordinary Uno is functionally equivalent to

```
unsigned long micros() {
  return((timer0_overflow_count << 8) + TCNT0)*(64/16);
}

```

This returns a four-byte unsigned long comprised of the three lowest bytes from `timer0_overflow_count` and one byte from the timer-0 count register.

The `timer0_overflow_count` is incremented about once per millisecond by the `TIMER0_OVF_vect` interrupt handler, as explained in an examination of the arduino millis function webpage.

Before an interrupt handler begins, AVR hardware disables interrupts. If (for example) an interrupt handler were to run for five milliseconds with interrupts still disabled, at least four timer 0 overflows would be missed. \[Interrupts written in C code in the Arduino system are not reentrant (capable of correctly handling multiple overlapping executions within the same handler) but one could write a reentrant assembly language handler that reenables interrupts before it begins a time-consuming process.\]

In other words, timer overflows don't “stack up”; whenever an overflow occurs before the interrupt from the previous overflow has been handled, the `millis()` counter loses a millisecond, and the discrepancy in `timer0_overflow_count` in turn makes `micros()` wrong by a millisecond too.

Regarding “shorter than 500 μs” as an upper time limit for interrupt processing, “to prevent blocking the timer interrupt for too long”, you could go up to just under 1024 μs (eg 1020 μs) and `millis()` still would work, most of the time. However, I regard an interrupt handler that takes more than 5 μs as a sluggard, more than 10 μs as slothful, more than 20 μs as snail-like.

# Answer
> 0 votes
You should never do anything inside an ISR except set a flag saying you got the interrupt, and return.

---
Tags: interrupt, timers, millis
---


# Question
Title: Is there something that I need to do to make the code from this answer compile?
I tried to compile the following code (using Arduino 1.8.16 with an esp8266-12)

```
extern volatile unsigned long timer0_millis;
unsigned long new_value = 0;

void setup(){
  //Setup stuff
}

void loop(){
  //Do stuff
  //--------

  //Change Millis
  setMillis(new_value);
}

void setMillis(unsigned long new_millis){
  uint8_t oldSREG = SREG;
  cli();
  timer0_millis = new_millis;
  SREG = oldSREG;
}

```

from an answer to this question, but I get the following error

```
 error: 'SREG' was not declared in this scope
   uint8_t oldSREG = SREG;
                 ^
exit status 1
'SREG' was not declared in this scope

```

I wouldn't necessarily want to use this code for any real purpose, other than as an exercise in learning. What am I missing? What is **SREG** ?

# Answer
`SREG` is the processor status register. One of the bits in there is the interrupt flag, which is cleared with the `cli()` command and reset at the end of the function. Why the original poster used the register instead of just using cli/sei is unclear. (Note: Instead of `cli()` and `sei()` the arduino documentation uses the much clearer equivalents `noInterrupts()` and `interrupts()`.)

This SREG register is, in this form, hardware specific and therefore not available if you're using the esp8266 toolchain. The above code builds fine with an Arduino Uno or similar board. To build for the esp8266, change the code to:

```
void setMillis(unsigned long new_millis){
  noInterrupts();
  timer0_millis = new_millis;
  interrupts();
}

```

I don't have such a board, so I can't verify it really works on this board. You might get a linker error about a non-existing `timer0_millis` variable.
> 1 votes

---
Tags: programming, millis
---


title: motor driver only works on one side:

text:
# Question
Title: motor driver only works on one side:
I have 3 motor drivers and all 3 other them only seem to only work on one of the 2 sides. I have used a voltmeter to check the voltages across the each of the 2 sections on each motor driver. For all 3 of the motor drivers, 2 of them had one side which had a voltage of 5V (which should be 7.2 volts as thats the power supply) and the other sides of the 2 motor drivers was 0-0.05V (so effectively no voltage). The other motor driver had no voltage from either of the 2 sides. Are all 3 of the motor drivers faulty or have I broke them? The schematic for the motor drivers was as follows:

(Apart from instead of a 12V source, a 7.2V source is used buts thats the amount of Volts I need for the motors. The arduino I used was an Arduino mega rather than an UNO shown in this diagram as I got this diagram off the internet) Heres a link for the place where I ordered the motor drivers from: https://thepihut.com/products/l298n-motor-stepper-driver

Here is my code:

```
    #include <PS2X_lib.h> //for v1.6
    int enA = 3;
    int in1 = 8;
    int in2 = 7;
    int enB = 9;
    int in3 = 5;
    int in4 = 4;
    int error = 0;
    byte type = 0;
    byte vibrate = 0;
    int light_one_pin = 36;
    int light_two_pin = 38;
    bool lights_on = false;
    PS2X ps2x;
    void setup(){
     Serial.begin(9600);
     pinMode(enA, OUTPUT);
     pinMode(in1, OUTPUT);
     pinMode(in2, OUTPUT);
     pinMode(in3, OUTPUT);
     pinMode(in4, OUTPUT);
     pinMode(light_one_pin, OUTPUT);
     pinMode(light_two_pin, OUTPUT);

     //CHANGES for v1.6 HERE!!! **************PAY ATTENTION*************
     for(int x = 0; x < 100; x++)
     {
      error = ps2x.config_gamepad(13,11,10,12, true, true);   //setup pins and settings:  GamePad(clock, command, attention, data, Pressures?, Rumble?) check for error
     }
     error = 0;

    }

    void loop() {
      ps2x.read_gamepad(false, vibrate);

      if(ps2x.ButtonPressed(PSB_GREEN) && lights_on == false)
      {
         digitalWrite(light_one_pin, HIGH);
         digitalWrite(light_two_pin, HIGH);
         lights_on = true;
         Serial.println("on");
      }
      else if(ps2x.ButtonPressed(PSB_GREEN) && lights_on == true)
      {
          digitalWrite(light_one_pin, LOW);
          digitalWrite(light_two_pin, LOW);
          lights_on = false;
          Serial.println("off");
      }

      if(ps2x.Analog(PSS_LY) < 128)
        {
          digitalWrite(in1, LOW);//all fowards wheel
          digitalWrite(in2, HIGH);
          digitalWrite(in3, HIGH);
          digitalWrite(in4, LOW);
          analogWrite(enA, 255);
          analogWrite(enB, 255);
          Serial.println("forwards");

        }

        else if(ps2x.Analog(PSS_LY) > 128)
        {
          digitalWrite(in1, HIGH);//all backwards wheels
          digitalWrite(in2, LOW);
          digitalWrite(in3, LOW);
          digitalWrite(in4, HIGH);
          analogWrite(enA, 255);
          analogWrite(enB, 255);
          Serial.println("backwards");

        }

        else if(ps2x.Analog(PSS_LY) == 128)
        {
          analogWrite(enA, 0);
          analogWrite(enB, 0);
          Serial.println("stationary");

        }

        else if(ps2x.Analog(PSS_LX) == 128)
        {
            //Serial.println("still");
            //wheel_steering_servo.write(wheel_steering_servo_angle);
        }

        Serial.println(ps2x.Analog(PSS_LX));

    }

```

# Answer
> 2 votes
Just a correction to something Coder9390 wrote:

The ENA and ENB pins on this motor drive are not supposed to be used as digital pins and receive HIGH or LOW, but as analog pins and receive a value in range 0-255 using a PWM pin (PWM pins are marked on the board with a ~). This enables you to control the speed of the motor, by simulating low voltage.

In your code you actually seem to do this correctly, so I don't think this is the problem. Setting the pinMode of ENA and ENB to OUTPUT on the other hand is correct, so it might actually be the problem. I couldn't reproduce your bug this way though, so it might be something else.

In case you don't need to control the speed of the motor and want it to always go full speed, you can use jumpers to short each EN pin with it's orthogonal-adjacent pin (which are marked in your image as 5v) to achieve the same effect of connecting them to 5v "manually" as Coder9390 suggested (basically by placing the jumpers there you are doing exactly that - connecting the EN pins to 5v).

Coder9390, if you implicitly meant to suggest using jumpers like this, then sorry for misrepresenting your answer. I thought it wasn't clear to beginners who might get here, and that it requires an elaboration.

See this motor driver usage explained here: https://create.arduino.cc/projecthub/ryanchan/how-to-use-the-l298n-motor-driver-b124c5

# Answer
> 1 votes
There are a couple of things that you can check-

**Your code**-

Chances are that all of the motor drivers are functional (as manufacturing defects are very rare) and that there is something wrong with the code.

**1-** **The motor driver that you are using has 2 pins that should be labeled "ENA", "ENB" (or some variant of these), in order for the motor driver to work on both sides, both these pins must be high, if any one of these are low, then that side will not work. I highly recommend that you directly connect these 2 pins to 5V, and use the 4 inputs for the control.**

**2-** The 4 input pins labeled "IN1", "IN2", "IN3", "IN4" are the pins that instructs the driver to move each side forward or back, check your code to make sure that these pins are high or low as per your requirement.

Another thing is that both the forward and back inputs of one side must not be high at the same time otherwise it won't work

**Your hardware**-

If you find that something is getting abnormally hot on the boards or worse if something is burnt, then you should check your circuit and make sure there are no problems.

-- A problem in your code, is that "ENB" is not set as an output and hence is not high, you should also modify the setup to set the "ENA", "ENB" to high to make sure that it is on.

So your setup should go something like this-

```
     Serial.begin(9600);
     pinMode(enA, OUTPUT);
     pinMode(enB, OUTPUT);
     digitalWrite(enA, HIGH);
     digitalWrite(enB, HIGH);
     pinMode(in1, OUTPUT);
     pinMode(in2, OUTPUT);
     pinMode(in3, OUTPUT);
     pinMode(in4, OUTPUT);
     pinMode(light_one_pin, OUTPUT);
     pinMode(light_two_pin, OUTPUT);

```

---
Tags: motor, arduino-motor-shield
---


# Question
Title: Can I reuse crystal frequency of Arduino?
If I use some IC which requires clock frequency like 16MHz, can I take one from Arduino?

Or this it too high frequency to travel to neighboring board?

# Answer
> 1 votes
The frequency is important. Make sure they are the same or it will probably not work.

# Answer
> -1 votes
Yes but you need to know what you are doing. You will need a clock driver and possibly a clock receiver depending on the devices you select. Then you need to modify both boards voiding any possible warranty.

The best answer is NO!

---
Tags: oscillator-clock
---


# Question
Title: Serial.write - sedd ascii characters with hex value in the same line
Working on making a controller for a haunted house prop. Trying to get it to interface with a device.

Was able to use a serial analyzer to see what commands and values are being sent.

the hex codes being sent over serial for manual control is " 40 4d 01" which translates to "@M\[?\]"

the third byte 01 is the configuration state you want to have it change to. I'm using a byte to store the value between 0-255.

I'm stumped at how to send 2 ASCII characters but in the same Serial.write() command send a raw value, or at how to send them all as hex. I'm sure this is straight forward and I'm just unaware of some simple function.

# Answer
> 4 votes
First of all, I will challenge your assumption that you have to send the three bytes in the same call to `Serial.write()`. There is no real advantage in doing so. Serial output is handled through a memory buffer that is consumed by the serial port within an interrupt service routine. `Serial.write()` only writes to that memory buffer. Thus, you can simply:

```
Serial.write("@M");
Serial.write(1);

```

and the receiver will not see the difference. There will be no gap between the `'M'` and the `1`. There is no notion of “messages” or “frames” on a serial link, unless an upper layer protocol adds its own framing, which is not the case here.

Next, if you really want to issue a single call (futile as this is), you could

```
Serial.write("@M\1");

```

This, however, will not work if the last byte is zero. The method shown by the busybee is more general ans is able to send a zero-valued byte.

# Answer
> 2 votes
You can use a `byte` array for this:

```
    // at the appropriate place in your code:
    byte message[] = { '@', 'M', 0x01 };
    Serial.write(message, sizeof message);

```

If you need, you can prepare the array and just assign the value:

```
byte message[] = { '@', 'M', 0 };

// ...

    byte value = 0x01; // or any other assignment

    // at the appropriate place in your code:
    message[2] = value;
    Serial.write(message, sizeof message);

```

---
Tags: serial
---


# Question
Title: How to send multiple data over serial in one byte?
I'm currently reading 3 limit switches and sending those data over Serial.write using the following code.

```
#include <SPI.h>
#include <Wire.h>
#include <arduino-timer.h>

//Define limit switch pins
#define LEFT_SWITCH_PIN 5
#define RIGHT_SWITCH_PIN 6
#define REAR_SWITCH_PIN 7

bool left_switch_state;
bool right_switch_state;
bool rear_switch_state;
bool switch_state_array[3] = {left_switch_state,right_switch_state,rear_switch_state};
int switch_pin_array[3] = {LEFT_SWITCH_PIN,RIGHT_SWITCH_PIN,REAR_SWITCH_PIN};

int send_status_state = 0;

void setup() {
    Wire.begin();
    Serial.begin(115200);
    status_timer.every(200, sendStatus);
}

void sendStatus() {
  if (send_status_state == 0) {
    getLimitSwitch();

    unsigned char buf[5];
    buf[0] = 'S';
    buf[1] = switch_state_array[0];
    buf[2] = switch_state_array[1];
    buf[3] = switch_state_array[2];
    buf[4] = '|';
    Serial.write(buf,5);
    send_status_state = 1;

  }
}

void loop() {
    status_timer.tick();
  }

void getLimitSwitch()
{
  for (int i=0; i<3; i++)
  {
    switch_state_array[i] = digitalRead(switch_pin_array[i]);
  }
}
/*********************************************************************************************************
    END FILE
*********************************************************************************************************/

```

as you can see I'm currently using 3 bytes to send the states of each limit switch separately.

```
    buf[1] = switch_state_array[0];
    buf[2] = switch_state_array[1];
    buf[3] = switch_state_array[2];

```

How can I send all limit switch data in one byte?

# Answer
> 5 votes
You should learn how to use bitwise operators. These are needed to do what you want.

We can save the state of each switch in one bit each. For this we first define our global variable that will hold the switch states:

```
byte switch_states = 0;

```

Then in `getLimitSwitch()` we loop through our pins. The result of `digitalRead()` is always one of `0` and `1`. So we can take this value and bit shift it to the left. Then we do bitwise OR operations to put the value into our `switch_states` variable:

```
void getLimitSwitch()
{
  for (int i=0; i<3; i++)
  {
    switch_states |= ( digitalRead(switch_pin_array[i]) << i );
  }
}

```

Then you can send that byte over Serial. It can hold up to 8 states.

```
Serial.write(switch_states);

```

---

The most interesting line here is

```
switch_states |= ( digitalRead(switch_pin_array[i]) << i );

```

Lets follow here with an example: Lets assume we look at the pin with index 2 and it is HIGH. So we have `switch_states |= ( 1 << 2 )`. This equates to the following representation in binary `switch_states |= ( 0b00000001 << 2 )`. `<<` shifts the bit pattern to the left; by 2 digits in this case. So we get `switch_states |= 0b00000100;`. That is equal to `switch_states = switch_states | 0b00000100;`. The bitwise OR operator `|` return a value where each bit is set to 1, if the corresponding bit in at least one of the two operants is 1. Here we use this to put the bits together.

If the pins have the states HIGH,LOW,HIGH the resulting value will be `0b00000101`, aka. `5` in decimal.

---

On the other side you might want to decode this value. How it is done depends on the architecture (using a PC, a microcontroller, ...). But on an Arduino you can test for a pin to be HIGH with this:

```
if(received_states_variable & (1 << pin_index))

```

---

Note: Doing this

```
bool left_switch_state;
bool right_switch_state;
bool rear_switch_state;
bool switch_state_array[3] = {left_switch_state,right_switch_state,rear_switch_state};

```

doesn't make much sense. You initialize the array elements just with the implicitly to `false` initialized variables. You just don't need the normal bool variables. You can just simply define your `bool` array. If you want to initialize it explicitly, just use `true` or `false` directly:

```
bool switch_state_array[3] = {false, false, false};

```

or even

```
bool switch_state_array[3] = {false};

```

---
Tags: serial, communication, serial-data
---


# Question
Title: Why does Arduino Due appear to halt after single call to ADC_Handler?
In the simple example below I just software trigger an ADC acquisition and then set the builtin LED's digital out in the interrupt handler. I don't know why the program appears to halt however.

```

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

  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);

  adc_enable_channel(ADC, ADC_CHANNEL_6);
  adc_enable_interrupt(ADC, ADC_IER_EOC6);
  pmc_enable_periph_clk(ID_ADC);
  NVIC_EnableIRQ(ADC_IRQn);

  Serial.println("GO");
}

void loop()
{
  Serial.println("RUNNING");
  adc_start(ADC);
}

void ADC_Handler(void)
{
  digitalWrite(13,HIGH);
  adc_get_status(ADC);
}

```

I know the handler gets called because the LED lights. The main loops appears to stop running after this as it lo longer prints out anything. If I don't trigger an acquision in the main loop it runs forever. Likewise if I don't enable the interrupt or the NVIC.

I can't explain this behavior.

# Answer
The freeze will occur unless unless `ADC_ISR` bits 0-15 are 0 at the end of the interrupt handler. In this case, ISR returns bit 6 set for the enabled channel (6). For many interrupts, the bit can be reset to 0 by simply reading `ADC_ISR`. However for end-of-conversion interrupts the converted data register for that channel *must* be read for the ISR bit to be set to 0.

Therefore this code will not halt. (I included some extra printouts to make clear the register values at each point in time.)

```
volatile uint32_t LAST = 0;
volatile uint32_t CHAN6 = 0;
volatile uint32_t ISR1 = 0;
volatile uint32_t ISR2 = 0;

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

  adc_enable_channel(ADC, ADC_CHANNEL_6);

  adc_enable_interrupt(ADC, ADC_IER_EOC6);

  pmc_enable_periph_clk(ID_ADC);

  NVIC_ClearPendingIRQ(ADC_IRQn);
  NVIC_EnableIRQ(ADC_IRQn);

  Serial.println("GO");
  adc_configure_trigger(ADC, ADC_TRIG_SW,0);
}

void loop()
{
  Serial.println(ISR1,BIN);
  Serial.println(ISR2,BIN);

  adc_start(ADC);
  delay(1000);
}

void ADC_Handler(void)
{
  ISR1 = adc_get_status(ADC); // chan 6 bit =1
  LAST = adc_get_latest_value(ADC);
  ISR1 = adc_get_status(ADC); // chan 6 bit =1 (still)

  CHAN6 = adc_get_channel_value(ADC, ADC_CHANNEL_6);
  ISR2 = adc_get_status(ADC); // chan 6 bit = 0
}

```

However, I will note that the datasheet for the chip says on page 1322 `Reading one of the ADC_CDR registers clears the corresponding EOC bit. Reading ADC_LCDR clears the DRDY bit and EOC bit corresponding to the last converted channel.`

**This appears to be false**. Reading ADC\_LCDR *does not* clear the status bit and will cause a hang. `ADC_CDR6` **must** be read specifically to avoid a hang.
> 2 votes

---
Tags: interrupt, arduino-due
---


title: X and Y axis on Arduino Serial Plotter?

text:
# Question
Title: X and Y axis on Arduino Serial Plotter?
I am trying to plot my counter vs. time on the serial plotter, but the values on the y axis are so big there is no way that it's displaying the counter values. I have printed both values:

```
  Serial.print("counter: ");
  Serial.println(counter);
  time = millis();
  Serial.print("Time: ");
  Serial.println(time);

```

I expected time to show up in the x-axis, but I think it's displaying on the y-axis and I'm not sure how to change this. The plot should just be an increasing line as the counter and time get bigger... what am I missing? Thanks.

Slashing out the Serial.print("Time:") does not correct anything.

# Answer
> 3 votes
Inorder to plot multiple variables or waveforms simultaneously a 'space' is printed between the two print statements.

```
Serial.print(counter);
Serial.print(" ");
time = millis();
Serial.println(time);

```

OR

```
Serial.print(counter);
Serial.print("\t");
time = millis();
Serial.println(time);

```

# Answer
> 1 votes
Comment out the `Serial.print("Time: ");` line. The Arduino serial plotter wants only numbers.

# Answer
> 1 votes
The X-axis is fixed and nothing gets plotted on the X-axis. It has its own divisions and they are automatically set by the Arduino IDE. The Arduino IDE still has to do some improvements to its software so that the X- axis can be adjusted and plotted too! This is my experience so far and corrections are welcome!

# Answer
> 0 votes
To plot multiple values over time you need to output just the numbers on a single line per iteration, and delimit with a space or tab:

```
Serial.print(counter);
Serial.print("\t"); // delimit with tab
time = millis();
Serial.print(time);
Serial.println();

```

It's worth noting however, the time (x axis) is implied by each line. In essence each line of output advances "time" by 1 unit. So I suspect you'll want to remove the time variable output and just output the count variable by it self.

---
Tags: arduino-uno, time
---


title: Peculiar behaviour of arduino pro micro

text:
# Question
Title: Peculiar behaviour of arduino pro micro
I am working with an arduino pro micro and I am facing a peculiar problem. The project I am working with includes arduino MKR NB 1500 as well. I am transferring data from MKR NB 1500 to arduino pro micro through Serial1(Rx/Tx pins). I have added the sample code that i am using on both boards

program in arduino MKR NB 1500

```
void setup() {
  Serial1.begin(9600);
}
void loop() {
  Serial1.print("printing");
  delay(2000);
}

```

program in pro micro

```
#include "Keyboard.h"

void setup() {
  Serial1.begin(9600);
  Keyboard.begin();
}

void loop() {
  Keyboard.write(Serial1.read());
}

```

I would like to transfer some data from MKR NB 1500 to pro micro which emulates a keyboard and prints the data in a editor. I am powering the arduino MKR NB 1500 via USB using its native USB port. The pro micro works as expected when I connect both these boards to USB ports in the same laptop. (Output: printingprintingprintingprinting)

However, the pro micro prints garbage values when I connect the MKR NB 1500 to a USB port belonging to a different laptop. (Output: a10joh\<qqj\<zstjo)

Is there any reason for such a behavior. Please let me know if you need more information from my side or if i have not made myself clear.

# Answer
You have to connect ground between the modules. Without common ground the logic level of signal can't be measured. While both boards were powered over USB from the same laptop the boards had common ground.

---

`read` returns -1 if nothing is available so check if some character was received:

```
void loop() {
  if (Serial1.available()) {
    Keyboard.write(Serial1.read());
  }
}

```

btw: The MKR can emulate a keyboard too with the Keyboard library.
> 1 votes

---
Tags: serial, usb, arduino-pro-micro, keyboard, samd21g
---


title: Why do I see error in this code

text:
# Question
Title: Why do I see error in this code
```
NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE);

AF_DCMotor motor1(1, MOTOR12_1KHZ);
AF_DCMotor motor2(2, MOTOR12_1KHZ);
AF_DCMotor motor3(3, MOTOR34_1KHZ);
AF_DCMotor motor4(4, MOTOR34_1KHZ);
Servo myservo;

boolean goesForward=false;
int distance = 100;
int speedSet = 0;

void setup() {

  myservo.attach(10);
  myservo.write(115);
  delay(2000);
  distance = readPing();
  delay(100);
  distance = readPing();
  delay(100);
  distance = readPing();
  delay(100);
  distance = readPing();
  delay(100);
}

void loop() {
 int distanceR = 0;
 int distanceL =  0;
 delay(40);

 if(distance<=15)
 {
  moveStop();
  delay(100);
  moveBackward();
  delay(300);
  moveStop();
  delay(200);
  distanceR = lookRight();
  delay(200);
  distanceL = lookLeft();
  delay(200);

  if(distanceR>=distanceL)
  {
    turnRight();
    moveStop();
  }else
  {
    turnLeft();
    moveStop();
  }
 }else
 {
  moveForward();
 }
 distance = readPing();
}

int lookRight()
{
    myservo.write(50);
    delay(500);
    int distance = readPing();
    delay(100);
    myservo.write(115);
    return distance;
}

int lookLeft()
{
    myservo.write(170);
    delay(500);
    int distance = readPing();
    delay(100);
    myservo.write(115);
    return distance;
    delay(100);
}

int readPing() {
  delay(70);
  int cm = sonar.ping_cm();
  if(cm==0)
  {
    cm = 250;
  }
  return cm;
}

void moveStop() {
  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
  }

void moveForward() {

 if(!goesForward)
  {
    goesForward=true;
    motor1.run(FORWARD);
    motor2.run(FORWARD);
    motor3.run(FORWARD);
    motor4.run(FORWARD);
   for (speedSet = 0; speedSet < MAX_SPEED; speedSet +=2) // slowly bring the speed up to avoid loading down the batteries too quickly
   {
    motor1.setSpeed(speedSet);
    motor2.setSpeed(speedSet);
    motor3.setSpeed(speedSet);
    motor4.setSpeed(speedSet);
    delay(5);
   }
  }
}

void moveBackward() {
    goesForward=false;
    motor1.run(BACKWARD);
    motor2.run(BACKWARD);
    motor3.run(BACKWARD);
    motor4.run(BACKWARD);
  for (speedSet = 0; speedSet < MAX_SPEED; speedSet +=2) // slowly bring the speed up to avoid loading down the batteries too quickly
  {
    motor1.setSpeed(speedSet);
    motor2.setSpeed(speedSet);
    motor3.setSpeed(speedSet);
    motor4.setSpeed(speedSet);
    delay(5);
  }
}

void turnRight() {
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);
  delay(500);
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}

void turnLeft() {
  motor1.run(BACKWARD);
  motor2.run(BACKWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
  delay(500);
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}

```

# Answer
> 1 votes
All of the errors I got were "NewPing does not name a type", "AF\_DCMOtor does not name a type" and "motor\<\> was not declared in this scope". I don't see library includes; at least one for NewPing is needed. I don't know where AF\_DCMotor is supposed to be declared but, as it is not declared as a type, it leaves all of the motor undefined. Those are the bulk (if not all) of the errors as the code stands now. Add the missing NewPing library do whatever you need to to define AF\_DCMotor.

# Answer
> 0 votes
It probably needs a library. Looks like you have some kind of AFDC library and did not use it.

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


title: Driving higher loads with PWM

text:
# Question
Title: Driving higher loads with PWM
My Arduino Pro Micro can source 500mA from 3.3V VCC, when it is USB powered.

The chip itself, is rated for 200mA, though, and its output pins for 20mA recommended, 40mA max.

I am looking to have 3 PWM outputs, though, each doing 120mA. The combined 360mA would be in-spec for VCC, but not for the chip.

Is there a buffer IC that I can use that will switch these loads at that current, and can keep up with a few hundred Hz PWM?

From what I've read, you can switch loads with discrete transistors, but these require extra components like resistors? Are there CMOS chips that will take the PWM signal and output it at 120mA?

I am looking to source the current, not sink it.

The load in my application are LEDs driven with constant-current drivers that are daisy chained. I just want to PWM the Vled supply so I can dim per channel, of the entire daisy chain.

**UPDATE:** I went with @Majenko's solution of pre-biased DTB114EK. Although it somewhat works, it seems to struggle to deliver 30mA out, even though it is rated at 500mA?

**UPDATE:** The DTB113ZC works better. Due to a lower bias resistor, I can get more current through it.

# Answer
> 0 votes
Here is a part that will do the job for you, just 4 wires to connect. Use your favorite search engine or go to your favorite china supplier and use this term: "Low Control High Voltage 12V 24V 36V switch Mosfet Module For Arduino Connect IO MCU PWM Control Motor Speed 3V 5V". You will get many choices several in the dollar range. It is opto isolated so that eliminates the ground connections etc. I have used them several times and they work nicely.

---
Tags: pwm, current, switch
---


# Question
Title: can differential drive work together with ultrasonic sensor?
I've written a sketch to drive a differential drive system, specifically - to be able to drive strait. This does work.

So I am trying to add the ability to stop when the path is blocked using US sensor directed towards the front of the "car". I manage to get correct readings, but my "car" cannot move strait anymore.

I tried using the ping\_timer() functionality of NewPing library, but it did not solve the problem. When the ultrasonic code is commented out, my "car" can go strait.

My algorithm for strait driving is essentially to compare the pulses from two rotary encoders fitted to the wheels, and if one exceeds the other by more than one pulse, shut down the relevant motor and turn on the other motor (if it wasn't on already) so the slower motor has a chance to keep-up.

I wonder if there is a problem in my code that I cannot find, I will be very thankful for anyone who can review my sketch:

```
#include <Arduino.h>
// #include <Servo.h>
#include <TimedAction.h>
#include <NewPing.h>

#define RIGHT_MOTOR_ON (0 - int(pulseCountRight <= pulseCountLeft + 1))
#define LEFT_MOTOR_ON (0 - int(pulseCountLeft <= pulseCountRight + 1))

const int EN_RIGHT = 6;
const int IN1_RIGHT = 7;
const int IN2_RIGHT = 8;
const int ENCODER_RIGHT = 2;

const int EN_LEFT = 5;
const int IN1_LEFT = 10;
const int IN2_LEFT = 11;
const int ENCODER_LEFT = 3;

const int SPEED = 100;

const int BW_TRUE = -1;
const int BW_FALSE = 0;

// const int SERVO_PIN = 9;
// const int SERVO_MAX_RIGHT = 0;
// const int SERVO_MAX_LEFT = 125;
const int SERVO_SWEEP_DELAY = 150;
// const int SERVO_TURN_RIGHT = -25;
// const int SERVO_TURN_LEFT = 25;

const int ULTRASONIC_TOO_CLOSE = 20;
// Timeout is the maximum time it would take sound to do a roundtrip with length of "ULTRASONIC_TOO_CLOSE".
// Formula is: DIST(cm) x TIME(us per cm).
const int ULTRASONIC_TIMEOUT = ULTRASONIC_TOO_CLOSE * US_ROUNDTRIP_CM;
const int ULTRASONIC_TRIG_PIN = 13;
const int ULTRASONIC_ECHO_PIN = 12;

unsigned int pulseCountRight = 0;
unsigned int pulseCountLeft = 0;

int movingStrait = BW_TRUE;
int stopping = BW_TRUE;

double distance = 0.0;

void pingTimer();
void checkTimer();

NewPing sonar(ULTRASONIC_TRIG_PIN, ULTRASONIC_ECHO_PIN, 400);

TimedAction pingTimerAction(SERVO_SWEEP_DELAY, pingTimer);

// Servo myServo;

void countPulse(unsigned int &counter) {
  ++counter;

  char c[1000];
  sprintf(c, "Pulses (right,left): %d,%d, Motor on (right,left): %d,%d", pulseCountRight, pulseCountLeft, RIGHT_MOTOR_ON, LEFT_MOTOR_ON);
  Serial.println(c);

  analogWrite(EN_RIGHT, SPEED & (RIGHT_MOTOR_ON | ~movingStrait) & ~stopping);
  analogWrite(EN_LEFT, SPEED & (LEFT_MOTOR_ON | ~movingStrait) & ~stopping);
}

void forward() {
  movingStrait = BW_TRUE;
  stopping = BW_FALSE;
  pulseCountRight = 0;
  pulseCountLeft = 0;

  digitalWrite(IN1_RIGHT, LOW);
  digitalWrite(IN2_RIGHT, HIGH);

  digitalWrite(IN1_LEFT, LOW);
  digitalWrite(IN2_LEFT, HIGH);

  analogWrite(EN_RIGHT, SPEED);
  analogWrite(EN_LEFT, SPEED);
}

void backwards() {
  movingStrait = BW_TRUE;
  stopping = BW_FALSE;
  pulseCountRight = 0;
  pulseCountLeft = 0;

  digitalWrite(IN1_RIGHT, HIGH);
  digitalWrite(IN2_RIGHT, LOW);

  digitalWrite(IN1_LEFT, HIGH);
  digitalWrite(IN2_LEFT, LOW);

  analogWrite(EN_RIGHT, SPEED);
  analogWrite(EN_LEFT, SPEED);
}

void right() {
  movingStrait = BW_FALSE;
  stopping = BW_FALSE;

  digitalWrite(IN1_RIGHT, LOW);
  digitalWrite(IN2_RIGHT, HIGH);

  digitalWrite(IN1_LEFT, HIGH);
  digitalWrite(IN2_LEFT, LOW);

  analogWrite(EN_RIGHT, SPEED);
  analogWrite(EN_LEFT, SPEED);
}

void left() {
  movingStrait = BW_FALSE;
  stopping = BW_FALSE;

  digitalWrite(IN1_RIGHT, HIGH);
  digitalWrite(IN2_RIGHT, LOW);

  digitalWrite(IN1_LEFT, LOW);
  digitalWrite(IN2_LEFT, HIGH);

  analogWrite(EN_RIGHT, SPEED);
  analogWrite(EN_LEFT, SPEED);
}

void stop() {
  movingStrait = BW_FALSE;
  stopping = BW_TRUE;

  digitalWrite(IN1_RIGHT, LOW);
  digitalWrite(IN2_RIGHT, LOW);

  digitalWrite(IN1_LEFT, LOW);
  digitalWrite(IN2_LEFT, LOW);
}

void setup() {
  Serial.begin(9600);
  Serial.println("DifferentialDrive2");

  pinMode(EN_RIGHT, OUTPUT);
  pinMode(EN_LEFT, OUTPUT);
  pinMode(IN1_RIGHT, OUTPUT);
  pinMode(IN2_RIGHT, OUTPUT);
  pinMode(IN1_LEFT, OUTPUT);
  pinMode(IN2_LEFT, OUTPUT);

  pinMode(ENCODER_RIGHT, INPUT_PULLUP);
  pinMode(ENCODER_LEFT, INPUT_PULLUP);

  // pinMode(SERVO_PIN, OUTPUT);

  pinMode(ULTRASONIC_TRIG_PIN, OUTPUT);
  pinMode(ULTRASONIC_ECHO_PIN, INPUT);

  attachInterrupt(digitalPinToInterrupt(ENCODER_RIGHT), [] { countPulse(pulseCountRight); }, CHANGE);
  attachInterrupt(digitalPinToInterrupt(ENCODER_LEFT), [] { countPulse(pulseCountLeft); }, CHANGE);

  digitalWrite(IN1_RIGHT, LOW);
  digitalWrite(IN2_RIGHT, HIGH);

  digitalWrite(IN1_LEFT, LOW);
  digitalWrite(IN2_LEFT, HIGH);

  analogWrite(EN_RIGHT, SPEED);
  analogWrite(EN_LEFT, SPEED);

  // myServo.attach(SERVO_PIN);
  // myServo.write((SERVO_MAX_RIGHT + SERVO_MAX_LEFT) / 2);

  forward();
}

unsigned long start_time = 0;

void pingTimer() {
  sonar.timer_stop();
  start_time = micros();
  sonar.ping_timer(checkTimer);
  // NewPing::timer_us(ULTRASONIC_TIMEOUT * 4, checkTimer);
}

void checkTimer() {
  // static int angle = SERVO_MAX_RIGHT;
  // static int direction = SERVO_TURN_LEFT;
  if (micros() - ULTRASONIC_TIMEOUT >= start_time && sonar.check_timer()) {
    distance = ((float) sonar.ping_result / (float) US_ROUNDTRIP_CM) / 2.0;
    if (distance < ULTRASONIC_TOO_CLOSE) {
      stop();
      Serial.println("stoppeing");
    }
  }
  // sonar.timer_stop();
}

void loop() {
  pingTimerAction.check();
  if (distance == 0 || distance > ULTRASONIC_TOO_CLOSE) {
    // forward();
  }
}

```

Here is a printout of the pulse counts and the status of the motors for a run:

```
DifferentialDrive2
Pulses (right,left): 1,0, Motor on (right,left): -1,-1
Pulses (right,left): 1,1, Motor on (right,left): -1,-1
Pulses (right,left): 2,1, Motor on (right,left): -1,-1
Pulses (right,left): 3,1, Motor on (right,left): 0,-1
Pulses (right,left): 4,1, Motor on (right,left): 0,-1
Pulses (right,left): 5,1, Motor on (right,left): 0,-1
Pulses (right,left): 6,1, Motor on (right,left): 0,-1
Pulses (right,left): 7,1, Motor on (right,left): 0,-1
Pulses (right,left): 8,1, Motor on (right,left): 0,-1
Pulses (right,left): 9,1, Motor on (right,left): 0,-1
Pulses (right,left): 9,2, Motor on (right,left): 0,-1
Pulses (right,left): 9,3, Motor on (right,left): 0,-1
Pulses (right,left): 9,4, Motor on (right,left): 0,-1
Pulses (right,left): 9,5, Motor on (right,left): 0,-1

Pulses (right,left): 9,6, Motor on (right,left): 0,-1
Pulses (right,left): 9,7, Motor on (right,left): 0,-1
Pulses (right,left): 9,8, Motor on (right,left): -1,-1
Pulses (right,left): 9,9, Motor on (right,left): -1,-1
Pulses (right,left): 10,9, Motor on (right,left): -1,-1
Pulses (right,left): 11,9, Motor on (right,left): 0,-1
Pulses (right,left): 12,9, Motor on (right,left): 0,-1
Pulses (right,left): 13,9, Motor on (right,left): 0,-1
Pulses (right,left): 14,9, Motor on (right,left): 0,-1
Pulses (right,left): 15,9, Motor on (right,left): 0,-1
Pulses (right,left): 16,9, Motor on (right,left): 0,-1
Pulses (right,left): 17,9, Motor on (right,left): 0,-1
Pulses (right,left): 17,10, Motor on (right,left): 0,-1
Pulses (right,left): 17,11, Motor on (right,left): 0,-1
Pulses (right,left): 17,12, Motor on (right,left): 0,-1
Pulses (right,left): 17,13, Motor on (right,left): 0,-1
Pulses (right,left): 17,14, Motor on (right,left): 0,-1
Pulses (right,left): 17,15, Motor on (right,left): 0,-1
Pulses (right,left): 17,16, Motor on (right,left): -1,-1
Pulses (right,left): 17,17, Motor on (right,left): -1,-1
Pulses (right,left): 18,17, Motor on (right,left): -1,-1
Pulses (right,left): 19,17, Motor on (right,left): 0,-1
Pulses (right,left): 20,17, Motor on (right,left): 0,-1
Pulses (right,left): 21,17, Motor on (right,left): 0,-1
Pulses (right,left): 22,17, Motor on (right,left): 0,-1
Pulses (right,left): 23,17, Motor on (right,left): 0,-1
Pulses (right,left): 24,17, Motor on (right,left): 0,-1
Pulses (right,left): 24,18, Motor on (right,left): 0,-1
Pulses (right,left): 24,19, Motor on (right,left): 0,-1
Pulses (right,left): 24,20, Motor on (right,left): 0,-1

```

What bugs me about this output is that I am expecting the slower motor not to open such large gaps, and I also know that in reality it did not open such large gaps. I suspect some pulses don't get counted for some reason, perhaps I am putting too much work on the micro-controller.

If the problem is not in my code, I wonder if this problem can be solved on a single Arduino device and I just have a weak algorithm, or perhaps it requires a separate device for the ultrasonic and a separate device for the differential drive.

Thanks in advance for any helpers.

PS. I am using this motor shield: https://osoyoo.com/2020/08/06/osoyoo-motor-shield/

# Answer
> 0 votes
Thanks to @chrisl, here is the answer:

The NewPing library uses Timer2 on UNO, which means pin 3 (and 11) is not available for use. I have been using pin 3 for interrupts from a rotary encoder, which is probably the reason for the sluggish performance.

The bad news are there are only two interrupt pins on UNO - 2 and 3, so if I want to attach two rotary encoders to my two drive wheels, I cannot use interrupts to count the pulses. There may be a workaround, I couldn't think of one, but I think IR proximity sensors may be a better choice than my ultrasonic sensor because judging from code examples they are neither blocking nor do they need timers, but I didn't really dive deep into them yet so I may be wrong on this.

---
Tags: arduino-uno, motor, ultrasonics
---


title: Adding L293D motor shield to Breadboard

text:
# Question
Title: Adding L293D motor shield to Breadboard
Anyone knows how to attach the l293D motor driver shield on a breadboard?

I need to put the shield on top of a breadboard and then use an Atmega328P as the main way of controlling it. Than you :)

# Answer
Acknowledging that it is not exactly the answer to your question, the folks at Adafruit have written an excellent tutorial on breadboarding the raw L293D *chip*. Which may be a more compact option for you?

Your question asks how to attach an L293D shield to a breadboard, and as @Juraj said in the comments, you can't do this easily directly. As @Jsotola mentioned, a UNO format shield is designed to connect directly to a uno, not to breadboard.

On a UNO format shield the pin alignment on the 18 pin (10+8) header sider of the shield (the digital pins) is not a comfortable fit into breadboard hole spacing (the shorter 14 pin side does align OK with breadboard). To make matters worse a UNO shield is wider than the available rows on a single standard breadboard. However, if you're willing to use more force and bend a few pins on the shield (**not recommended**) you can make this work using two breadboards side by side. The photo shows one possibility.

A **better solution** as mentioned by @ChrisL in the comments might be to use dupont connectors to connect the shield pins as needed (e.g. to a non-UNO format arduino).

There are different versions and clones of the L293D shield in circulation. I think most of these are based on the (now obsolete) Adafruit open source version 1. In any case you'll need to refer to the datasheet for the version you're using and be sure to connect every pin required from the shield to the arduino using the dupont connectors.

There are plenty of tutorials available regarding using the L293D shield, one example is at Last Minute Engineers
> 1 votes

---
Tags: arduino-uno, atmega328, arduino-motor-shield, l293d
---


# Question
Title: avrdude: stk500v2_ReceiveMessage(): timeout error for bluetooth arduino
I am trying to link the Bluetooth module to my arduino UNO in order to wirelessly program a robot. The only issue that I am having is that the bluetooth module does not seem to pick up the arduino.

Here is how the bluetooth module is wired up to my arduino:

The bluetooth module is paired to my PC via a bluetooth dongle. I know that the bluetooth module is working on port COM7. The LED then on the bluetooth module blinks quickly. After this I set the port to the correct port that the bluetooth module uses:

One thing that I found strange was that the name of the arduino board does not come up just like when I use a USB to upload the program.

When I open up the serial monitor the LED on the bluetooth module begins to blink more slowly possibly indicating it is connected. I afterwards try to send an AT command via the serial monitor to the arduino by typing in AT to the serial input at the top of the serial monitor and hitting enter and nothing happens. I then tried to send 3 different pieces of code separately to the arduino one at a time:

First code sample:

```
void setup() {

 Serial.begin(9600);

while (!Serial) {
   ; // wait for serial port to connect. Needed for native USB port only
 }

 Serial.println("ASCII Table ~ Character Map");
}

int thisByte = 33;

void loop() {

 Serial.write(thisByte);

 Serial.print(", dec: ");
 Serial.print(thisByte);

 Serial.print(", hex: ");
 Serial.print(thisByte, HEX);

 Serial.print(", oct: ");
 Serial.print(thisByte, OCT);

 Serial.print(", bin: ");
 Serial.println(thisByte, BIN);

 if (thisByte == 126) {
   while (true) {
     continue;
   }
 }
 thisByte++;

}

```

Second code sample:

```
#include <SoftwareSerial.h>
SoftwareSerial BTSerial (2,3);
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("Enter AT Commands");
  BTSerial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
  if(BTSerial.available()){
    Serial.write(BTSerial.read());
  }
  if(Serial.available()){
    BTSerial.write(Serial.read());
  }
}

```

Third code sample:

```
char inputByte;
void setup() {
 Serial.begin(9600);
 pinMode(13,OUTPUT);

}

void loop() {
while(Serial.available()>0){
  inputByte= Serial.read();
  Serial.println(inputByte);
  if (inputByte=='Z'){
  digitalWrite(13,HIGH);
  }
  else if (inputByte=='z'){
  digitalWrite(13,LOW);
  }
  }
}

```

(The following situation occurs for all 3 samples of code I copied from online). When I set the port to COM7 and then click upload to the board, the IDE says "Uploading" and the LED begins to blink more slowly just like as I was mentioning before with the serial monitor. After a while eventually the following error messages came up:

```
avrdude: stk500v2_ReceiveMessage(): timeout
avrdude: stk500v2_getsync(): timeout communicating with programmer

```

I looked online for answers. The internet suggested to use a larger baud rate so I switched it from 9600 to 57600 and also at the same time switch from Newline to Both NL and CR. Still nothing happened and I got the following error message. One final suggestion I saw on the internet was to put a resistor divider/voltage divider across the RX pin (I haven't done this as I don't see how this could make a difference, I could be wrong about it though and it could make the whole difference).

# Answer
The Bluetooth range is small so the robot can't be far from the computer for upload.

---

To solve the reset for the Bluetooth you could add a reset button on the robot and use it while avrdude attempts to upload the sketch. Baud rate on HC-05 must be set to 115200 baud.

---

As an alternative you could have USB connector on the robot. You can use a short USB extension cable as internal cable from the USB connector of the Arduino to the outer shell of the robot.
> 1 votes

---
Tags: bluetooth, rx-pin
---


title: Reverse engineering an i2c signal

text:
# Question
Title: Reverse engineering an i2c signal
I have an i2c device that i would like to rreverse engineer. Using the oringal master of the device here is a snapshot from the logical analyzer

I would like to replace the orginal master of the device with an arduino, the device has an interrupt pin that when detected it will do the trasaction above.

So far what i have figuerd out is the address is 0x53 (the first byte). I have also figured out by interactive with the device that the second,third, and last byte are data from the slave device.

How do i write an arduino code to simulate this transaction? Here is the code i have written and the response i got is not quite the same

```
#include <Wire.h>

void setup() {
  Wire.begin();        // join i2c bus (address optional for master)
  Wire. setClock(100000)
  Serial.begin(9600);  // start serial for output
}

void loop() {
  Wire.requestFrom(0x53, 6);    // request 6 bytes from slave device #8

  while (Wire.available()) { // slave may send less than requested
    char c = Wire.read(); // receive a byte as character
    Serial.print(c);         // print the character
  }

  delay(500);
}

```

# Answer
> 1 votes
# Customised Protocol

As has been mentioned in the comments, it may be that the controller and target are communicating using a customised protocol for which you will need to modify the `Wire` library and/or the `TWI` library.

Modifying the `TWI` library is not easy because it uses a very convoluted mixture of ISR code and non-ISR polling code.

I've re-written the TWI library so that you can use standard burst-read and burst-write protocols in either ISR mode or polling mode, or **build your own protocol using building-block functions**. It uses the watchdog timer to detect timeouts when the bus freezes due to an error.

# Terminology

The terminology of my TWI library conforms to NXP Semiconductors recently released v7 of the I2C-bus specification which has:

> Updated the terms "master/slave" to "controller/target" throughout to align with MIPI I3C specification and NXP's Inclusive Language Project

---
Tags: i2c
---


title: Arduino Due vs Mega 2560

text:
# Question
Title: Arduino Due vs Mega 2560
What can an Arduino Due do that a Mega 2560 can't? What can a Mega 2560 do that a Due can't? I've heard the Due is 3.3V so it can't work with most shields.

# Answer
The 'R3' version boards and shields are compatible with 3.3V and 5V. For example the Ethernet Shield V1 version 'R3' can be used with the Due. The new Arduino Ethernet Shield 2 is also compatible with the Due.
Many older shield are not compatible with the Due, but do you really need to use an old shield ?

Most sensors are 3.3V, and also a SD memory card is 3.3V. That is a lot easer with the Arduino Due which runs at 3.3V.

The Arduino Mega 2560 board is the only board with 10k pullup resistors at SDA and SCL, therefor it has a 5V I2C bus. When a 3.3V sensor with I2C is used, you need a I2C level shifter. When a 3.3V with SPI is used, you need more hardware.

The Arduino Mega pins can drive more than 20mA, it can be used to drive 10 leds with 20mA simultaneously, the Arduino Due can't do that.

My suggestion is to use an Arduino Uno for all kind of testing. It's always good to have one lying around. Start with an Arduino Uno if you want to learn programming and have fun with leds and buttons.

The Arduino Zero or MKRzero or M0 have a M0+ processor at 3.3V and they can be used for all kind of nice projects. When you already know a little about programming and electronics, this is a very good choice.

The Arduino Due has more processing power then the M0+.

The Arduino Mega 2560 is still used, because there are many libraries and shields that are compatible with the Arduino Mega 2560.
> 6 votes

# Answer
The Due can do a lot of things much faster. It has more memory and far more processing power. It has more flexible and more powerful built-in peripherals.

It can't easily interface with 5V devices though.

The Mega2560 has less memory and far less processing power, but interfacing with legacy 5V devices is far easier. It's also more forgiving to the novice user than the more complex SAM3X chip.

From an Arduino programming point of view both boards are pretty much programmed the same. The language is, excepting a few esoteric anomalies, largely the same. However when you come to do low-level programming instead if relying on the Arduino API you would find that the ATMega2560 is a much simpler chip to program. Power comes at a price. The more powerful SAM3X chip is much harder to get to grips with and program.

It's like comparing a Ford Escort with a Boeing 737. They're both vehicles, and they can both get you from A to B. The Boeing does it much faster and can carry more people, but flying it is a lot harder than driving a Ford Escort, and you can't fly it on an old-fashioned road.
> 5 votes

# Answer
Ahhhh... There is a more profound problem than these mentioned because the MEGA treats double precision declarations as floating point ( far less precision ). I was working with 1 CM GPS Location coordinates requiring double precision variables. It took a while for me to discover that ONLY the DUE compiles to a true double precision variable. The MEGA and most others do not. They convert double to float at compiler level. This is only meaningful if extremely precise math must occur.

Donald
> 1 votes

---
Tags: arduino-mega, arduino-due
---


# Question
Title: got a compiling error while programming node mcu
i was programming my node mcu i modified the code and got a complination error but when i compiled the original code i got no error modified code

```
#include "arduino_secrets.h"
#include "thingProperties.h"

// define the GPIO connected with Relays and switches
#define RelayPin1 5  //D1
#define RelayPin2 4  //D2
#define RelayPin3 14 //D5
#define RelayPin4 12 //D6

#define RelayPin5 2  //d4
#define RelayPin6 0   //D3
#define RelayPin7 13  //D7
#define RelayPin8 15   //d8

#define wifiLed   16   //D0

int toggleState_1 = 0; //Define integer to remember the toggle state for relay 1
int toggleState_2 = 0; //Define integer to remember the toggle state for relay 2
int toggleState_3 = 0; //Define integer to remember the toggle state for relay 3
int toggleState_4 = 0; //Define integer to remember the toggle state for relay 4
int toggleState_5 = 0; //Define integer to remember the toggle state for relay 5
int toggleState_6 = 0; //Define integer to remember the toggle state for relay 6
int toggleState_7 = 0; //Define integer to remember the toggle state for relay 7
int toggleState_8 = 0; //Define integer to remember the toggle state for relay 8

void relayOnOff(int relay) {

  switch (relay) {
    case 1:
      if (toggleState_1 == 0) {
        digitalWrite(RelayPin1, HIGH); // turn on relay 1
        toggleState_1 = 1;
        Serial.println("Device1 ON");
      }
      else {
        digitalWrite(RelayPin1, LOW); // turn off relay 1
        toggleState_1 = 0;
        Serial.println("Device1 OFF");
      }
      delay(100);
      break;
    case 2:
      if (toggleState_2 == 0) {
        digitalWrite(RelayPin2, HIGH); // turn on relay 2
        toggleState_2 = 1;
        Serial.println("Device2 ON");
      }
      else {
        digitalWrite(RelayPin2, LOW); // turn off relay 2
        toggleState_2 = 0;
        Serial.println("Device2 OFF");
      }
      delay(100);
      break;
    case 3:
      if (toggleState_3 == 0) {
        digitalWrite(RelayPin3, HIGH); // turn on relay 3
        toggleState_3 = 1;
        Serial.println("Device3 ON");
      } else {
        digitalWrite(RelayPin3, LOW); // turn off relay 3
        toggleState_3 = 0;
        Serial.println("Device3 OFF");
      }
      delay(100);
      break;
     case 4:
      if (toggleState_4 == 0) {
        digitalWrite(RelayPin4, HIGH); // turn on relay 3
        toggleState_4 = 1;
        Serial.println("Device4 ON");
      } else {
        digitalWrite(RelayPin4, LOW); // turn off relay 3
        toggleState_4 = 0;
        Serial.println("Device4 OFF");
      }
      delay(100);
      break;
     case 5:
      if (toggleState_5 == 0) {
        digitalWrite(RelayPin5, HIGH); // turn on relay 3
        toggleState_5 = 1;
        Serial.println("Device5 ON");
      } else {
        digitalWrite(RelayPin5, LOW); // turn off relay 3
        toggleState_5 = 0;
        Serial.println("Device5 OFF");
      }
      delay(100);
      break;
     case 6:
      if (toggleState_6 == 0) {
        digitalWrite(RelayPin6, HIGH); // turn on relay 3
        toggleState_6 = 1;
        Serial.println("Device6 ON");
      } else {
        digitalWrite(RelayPin6, LOW); // turn off relay 3
        toggleState_6 = 0;
        Serial.println("Device6 OFF");
      }
      delay(100);
      break;
     case 7:
      if (toggleState_7 == 0) {
        digitalWrite(RelayPin7, HIGH); // turn on relay 3
        toggleState_7 = 1;
        Serial.println("Device7 ON");
      } else {
        digitalWrite(RelayPin7, LOW); // turn off relay 3
        toggleState_7 = 0;
        Serial.println("Device7 OFF");
      }
      delay(100);
      break;
    case 8:
      if (toggleState_8 == 0) {
        digitalWrite(RelayPin8, HIGH); // turn on relay 4
        toggleState_8 = 1;
        Serial.println("Device8 ON");
      }
      else {
        digitalWrite(RelayPin8, LOW); // turn off relay 4
        toggleState_8 = 0;
        Serial.println("Device8 OFF");
      }
      delay(100);
      break;
    default : break;
  }
}

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

  // Defined in thingProperties.h
  initProperties();

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);

  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();

  pinMode(RelayPin1, OUTPUT);
  pinMode(RelayPin2, OUTPUT);
  pinMode(RelayPin3, OUTPUT);
  pinMode(RelayPin4, OUTPUT);
  pinMode(RelayPin5, OUTPUT);
  pinMode(RelayPin6, OUTPUT);
  pinMode(RelayPin7, OUTPUT);
  pinMode(RelayPin8, OUTPUT);

  pinMode(wifiLed, OUTPUT);

  digitalWrite(RelayPin1, LOW);
  digitalWrite(RelayPin2, LOW);
  digitalWrite(RelayPin3, LOW);
  digitalWrite(RelayPin4, LOW);
  digitalWrite(RelayPin5, LOW);
  digitalWrite(RelayPin6, LOW);
  digitalWrite(RelayPin7, LOW);
  digitalWrite(RelayPin8, LOW);

  digitalWrite(wifiLed, HIGH);  //Turn ON WiFi LED
}

void loop() {
  ArduinoCloud.update();

  if (WiFi.status() != WL_CONNECTED)
  {
    digitalWrite(wifiLed, HIGH); //Turn ON WiFi LED
  }
  else{
    digitalWrite(wifiLed, LOW); //Turn OFF WiFi LED
  }
}

```

the original code

```
#include "arduino_secrets.h"
#include "thingProperties.h"

// define the GPIO connected with Relays and switches
#define RelayPin1 5  //D1
#define RelayPin2 4  //D2
#define RelayPin3 14 //D5
#define RelayPin4 12 //D6

#define SwitchPin1 10  //SD3
#define SwitchPin2 0   //D3
#define SwitchPin3 13  //D7
#define SwitchPin4 3   //RX

#define wifiLed   16   //D0

int toggleState_1 = 0; //Define integer to remember the toggle state for relay 1
int toggleState_2 = 0; //Define integer to remember the toggle state for relay 2
int toggleState_3 = 0; //Define integer to remember the toggle state for relay 3
int toggleState_4 = 0; //Define integer to remember the toggle state for relay 4

void relayOnOff(int relay) {

  switch (relay) {
    case 1:
      if (toggleState_1 == 0) {
        digitalWrite(RelayPin1, HIGH); // turn on relay 1
        toggleState_1 = 1;
        Serial.println("Device1 ON");
      }
      else {
        digitalWrite(RelayPin1, LOW); // turn off relay 1
        toggleState_1 = 0;
        Serial.println("Device1 OFF");
      }
      delay(100);
      break;
    case 2:
      if (toggleState_2 == 0) {
        digitalWrite(RelayPin2, HIGH); // turn on relay 2
        toggleState_2 = 1;
        Serial.println("Device2 ON");
      }
      else {
        digitalWrite(RelayPin2, LOW); // turn off relay 2
        toggleState_2 = 0;
        Serial.println("Device2 OFF");
      }
      delay(100);
      break;
    case 3:
      if (toggleState_3 == 0) {
        digitalWrite(RelayPin3, HIGH); // turn on relay 3
        toggleState_3 = 1;
        Serial.println("Device3 ON");
      } else {
        digitalWrite(RelayPin3, LOW); // turn off relay 3
        toggleState_3 = 0;
        Serial.println("Device3 OFF");
      }
      delay(100);
      break;
    case 4:
      if (toggleState_4 == 0) {
        digitalWrite(RelayPin4, HIGH); // turn on relay 4
        toggleState_4 = 1;
        Serial.println("Device4 ON");
      }
      else {
        digitalWrite(RelayPin4, LOW); // turn off relay 4
        toggleState_4 = 0;
        Serial.println("Device4 OFF");
      }
      delay(100);
      break;
    default : break;
  }
}

void manual_control() {
  //Manual Switch Control
  if (digitalRead(SwitchPin1) == LOW) {
    delay(200);
    relayOnOff(1);
  }
  else if (digitalRead(SwitchPin2) == LOW) {
    delay(200);
    relayOnOff(2);
  }
  else if (digitalRead(SwitchPin3) == LOW) {
    delay(200);
    relayOnOff(3);
  }
  else if (digitalRead(SwitchPin4) == LOW) {
    delay(200);
    relayOnOff(4);
  }
}

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

  // Defined in thingProperties.h
  initProperties();

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);

  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();

  pinMode(RelayPin1, OUTPUT);
  pinMode(RelayPin2, OUTPUT);
  pinMode(RelayPin3, OUTPUT);
  pinMode(RelayPin4, OUTPUT);

  pinMode(wifiLed, OUTPUT);

  pinMode(SwitchPin1, INPUT_PULLUP);
  pinMode(SwitchPin2, INPUT_PULLUP);
  pinMode(SwitchPin3, INPUT_PULLUP);
  pinMode(SwitchPin4, INPUT_PULLUP);

  //During Starting all Relays should TURN OFF
  digitalWrite(RelayPin1, HIGH);
  digitalWrite(RelayPin2, HIGH);
  digitalWrite(RelayPin3, HIGH);
  digitalWrite(RelayPin4, HIGH);

  digitalWrite(wifiLed, HIGH);  //Turn OFF WiFi LED
}

void loop() {
  ArduinoCloud.update();

  manual_control(); //Control relays manually

  if (WiFi.status() != WL_CONNECTED)
  {
    digitalWrite(wifiLed, HIGH); //Turn OFF WiFi LED
  }
  else{
    digitalWrite(wifiLed, LOW); //Turn ON WiFi LED
  }
}

void onSwitch1Change() {
  if (switch1 == 1)
  {
    digitalWrite(RelayPin1, HIGH);
    Serial.println("Device1 ON");
    toggleState_1 = 1;
  }
  else
  {
    digitalWrite(RelayPin1, LOW);
    Serial.println("Device1 OFF");
    toggleState_1 = 0;
  }
}

void onSwitch2Change() {
  if (switch2 == 1)
  {
    digitalWrite(RelayPin2, HIGH);
    Serial.println("Device2 ON");
    toggleState_2 = 1;
  }
  else
  {
    digitalWrite(RelayPin2, LOW);
    Serial.println("Device2 OFF");
    toggleState_2 = 0;
  }
}

void onSwitch3Change() {
  if (switch3 == 1)
  {
    digitalWrite(RelayPin3, HIGH);
    Serial.println("Device2 ON");
    toggleState_3 = 1;
  }
  else
  {
    digitalWrite(RelayPin3, LOW);
    Serial.println("Device3 OFF");
    toggleState_3 = 0;
  }
}

void onSwitch4Change() {
  if (switch4 == 1)
  {
    digitalWrite(RelayPin4, HIGH);
    Serial.println("Device4 ON");
    toggleState_4 = 1;
  }
  else
  {
    digitalWrite(RelayPin4, LOW);
    Serial.println("Device4 OFF");
    toggleState_4 = 0;
  }
}

```

i have included the arduino\_secrets and thingproperties in my both pieces of code the difference is that i wanted 8 relay pins to be configured instead of 4 pins please ask if any thing is needed from me

this was the exact error

```
C:\Users\akki kisu\Documents\Arduino\libraries\ArduinoIoTCloud\src\property\Property.cpp:25:19: note: '#pragma message: No RTC available on this architecture - ArduinoIoTCloud will not keep track of local change timestamps .'
   25 |   #pragma message "No RTC available on this architecture - ArduinoIoTCloud will not keep track of local change timestamps ."
      |                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
c:/users/akki kisu/appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.4-gcc10.3-1757bed/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld.exe: sketch\Code_NodeMCU_Alexa_ArduinoIotCloud_4Relays.ino.cpp.o:(.text._Z14initPropertiesv+0x1c): undefined reference to `_Z15onSwitch1Changev'
c:/users/akki kisu/appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.4-gcc10.3-1757bed/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld.exe: sketch\Code_NodeMCU_Alexa_ArduinoIotCloud_4Relays.ino.cpp.o:(.text._Z14initPropertiesv+0x34): undefined reference to `_Z15onSwitch2Changev'
c:/users/akki kisu/appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.4-gcc10.3-1757bed/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld.exe: sketch\Code_NodeMCU_Alexa_ArduinoIotCloud_4Relays.ino.cpp.o:(.text._Z14initPropertiesv+0x40): undefined reference to `_Z15onSwitch3Changev'
c:/users/akki kisu/appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/3.0.4-gcc10.3-1757bed/bin/../lib/gcc/xtensa-lx106-elf/10.3.0/../../../../xtensa-lx106-elf/bin/ld.exe: sketch\Code_NodeMCU_Alexa_ArduinoIotCloud_4Relays.ino.cpp.o:(.text._Z14initPropertiesv+0x4c): undefined reference to `_Z15onSwitch4Changev'
collect2.exe: error: ld returned 1 exit status
exit status 1
Error compiling for board NodeMCU 1.0 (ESP-12E Module).

```

# Answer
> 0 votes
In Arduino IoT cloud the *variables* synced between the Cloud and the sketch are defined in the definition of the (IoT) *thing*. The *variables* are reflected into the thingProperties.h file which is maintained by the Cloud editor. The on\<variable\_name\> functions in the sketch handle the synchronization of these *variables*. They are declared in the thingProperties.h

You removed the `onSwitchChange` functions, but you didn't remove the switchChange *variables* in the definition of the Thing. The thingProperties.h still contains declarations of `onSwitchChange` functions, but the linker can't find the definition of the function because you removed it from the sketch.

The errors are like this one:

```
undefined reference to `_Z15onSwitch1Changev'

```

To solve this, remove the switchChange *variables* from the *thing* in the Cloud UI.

---
Tags: arduino-iot-cloud
---