text:
How to use a USB host shield with different HID Joysticks
I bought a Sparkfun USB host shield a while ago and have been using it using my Logitech Extreme 3D Pro Joystick. There is some example code for that one which makes it nice and easy to work with. There is also some example code for a generic USB HID Joystick.
My goal is to be able to use any joystick I want with the shield. All the channels on each of my flight sticks are being detected but they all have issues like they are mapped wrongly and don't have a full range of motion.
I understand I need to use USBHID_desc to get the USB HID Descriptor (unique for each joystick right?) and plug those numbers somewhere into the USBHIDJoystick code, but I don't know where to put this information.
My problem boils down to how should I use the data recovered from the USBHID_desc program.
Any help would be appreciated as I'm at a bit of a loss
Thanks
Report Descriptor for Random Flight Stick
Start
0000: 05 01 09 04 A1 01 09 01 A1 00 05 01 09 30 09 31
0010: 15 00 26 FF 03 35 00 46 FF 03 65 00 75 0A 95 02
0020: 81 02 09 35 09 32 15 00 26 FF 01 35 00 46 FF 01
0030: 65 00 75 09 95 02 81 02 75 01 95 02 81 01 09 39
0040: 15 01 25 08 35 00 46 3B 01 65 14 75 08 95 01 81
0050: 02 05 09 19 01 29 06 15 00 25 01 35 00 45 01 75
0060: 01 95 06 81 02 75 01 95 0A 81 01 C0 C0
Usage Page Gen Desktop Ctrls(01)
Usage Game Pad
Collection Application
Usage Pointer
Collection Physical
Usage Page Gen Desktop Ctrls(01)
Usage X
Usage Y
Logical Min(00)
Logical Max(FF03)
Physical Min(00)
Physical Max(FF03)
Unit(00)
Report Size(0A)
Report Count(02)
Input(00000010)
Usage Rz
Usage Z
Logical Min(00)
Logical Max(FF01)
Physical Min(00)
Physical Max(FF01)
Unit(00)
Report Size(09)
Report Count(02)
Input(00000010)
Report Size(01)
Report Count(02)
Input(00000001)
Usage Hat Switch
Logical Min(01)
Logical Max(08)
Physical Min(00)
Physical Max(3B01)
Unit(14)
Report Size(08)
Report Count(01)
Input(00000010)
Usage Page Button(09)
Usage Min(01)
Usage Max(06)
Logical Min(00)
Logical Max(01)
Physical Min(00)
Physical Max(01)
Report Size(01)
Report Count(06)
Input(00000010)
Report Size(01)
Report Count(0A)
Input(00000001)
End Collection
End Collection Game Pad Pointer X Y(02)(08)
 Rz Z(00)(E3)
(00)(00)
 Hat Switch(00)
 Btn0001
(00) Btn0002
(01) Btn0003
(00) Btn0004
(00) Btn0005
(00) Btn0006
(00)
(00)(00)(00)(00)(00)(00)(00)(00)(00)(00)

USB HID Joystick .INO
#include <usbhid.h>
#include <hiduniversal.h>
#include <usbhub.h>

// Satisfy IDE, which only needs to see the include statment in the ino.
#ifdef dobogusinclude
#include <spi4teensy3.h>
#endif
#include <SPI.h>

#include "hidjoystickrptparser.h"

USB Usb;
USBHub Hub(&Usb);
HIDUniversal Hid(&Usb);
JoystickEvents JoyEvents;
JoystickReportParser Joy(&JoyEvents);

void setup() {
        Serial.begin(115200);
#if !defined(__MIPSEL__)
        while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
#endif
        Serial.println("Start");

        if (Usb.Init() == -1)
                Serial.println("OSC did not start.");

        delay(200);

        if (!Hid.SetReportParser(0, &Joy))
                ErrorMessage<uint8_t > (PSTR("SetReportParser"), 1);
}

void loop() {
        Usb.Task();
}

USB HID Joystick .cpp
#include "hidjoystickrptparser.h"

JoystickReportParser::JoystickReportParser(JoystickEvents *evt) :
joyEvents(evt),
oldHat(0xDE),
oldButtons(0) {
        for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++)
                oldPad[i] = 0xD;
}

void JoystickReportParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf) {
        bool match = true;

        // Checking if there are changes in report since the method was last called
        for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++)
                if (buf[i] != oldPad[i]) {
                        match = false;
                        break;
                }

        // Calling Game Pad event handler
        if (!match && joyEvents) {
                joyEvents->OnGamePadChanged((const GamePadEventData*)buf);

                for (uint8_t i = 0; i < RPT_GEMEPAD_LEN; i++) oldPad[i] = buf[i];
        }

        uint8_t hat = (buf[5] & 0xF);

        // Calling Hat Switch event handler
        if (hat != oldHat && joyEvents) {
                joyEvents->OnHatSwitch(hat);
                oldHat = hat;
        }

        uint16_t buttons = (0x0000 | buf[6]);
        buttons <<= 4;
        buttons |= (buf[5] >> 4);
        uint16_t changes = (buttons ^ oldButtons);

        // Calling Button Event Handler for every button changed
        if (changes) {
                for (uint8_t i = 0; i < 0x0C; i++) {
                        uint16_t mask = (0x0001 << i);

                        if (((mask & changes) > 0) && joyEvents) {
                                if ((buttons & mask) > 0)
                                        joyEvents->OnButtonDn(i + 1);
                                else
                                        joyEvents->OnButtonUp(i + 1);
                        }
                }
                oldButtons = buttons;
        }
}

void JoystickEvents::OnGamePadChanged(const GamePadEventData *evt) {
        Serial.print("X1: ");
        PrintHex<uint8_t > (evt->X, 0x80);
        Serial.print("\tY1: ");
        PrintHex<uint8_t > (evt->Y, 0x80);
        Serial.print("\tX2: ");
        PrintHex<uint8_t > (evt->Z1, 0x80);
        Serial.print("\tY2: ");
        PrintHex<uint8_t > (evt->Z2, 0x80);
        Serial.print("\tRz: ");
        PrintHex<uint8_t > (evt->Rz, 0x80);
        Serial.println("");
}

void JoystickEvents::OnHatSwitch(uint8_t hat) {
        Serial.print("Hat Switch: ");
        PrintHex<uint8_t > (hat, 0x80);
        Serial.println("");
}

void JoystickEvents::OnButtonUp(uint8_t but_id) {
        Serial.print("Up: ");
        Serial.println(but_id, DEC);
}

void JoystickEvents::OnButtonDn(uint8_t but_id) {
        Serial.print("Dn: ");
        Serial.println(but_id, DEC);
}

USB HID Joystick .h
#if !defined(__HIDJOYSTICKRPTPARSER_H__)
#define __HIDJOYSTICKRPTPARSER_H__

#include <usbhid.h>

struct GamePadEventData {
        uint8_t X, Y, Z1, Z2, Rz;
};

class JoystickEvents {
public:
        virtual void OnGamePadChanged(const GamePadEventData *evt);
        virtual void OnHatSwitch(uint8_t hat);
        virtual void OnButtonUp(uint8_t but_id);
        virtual void OnButtonDn(uint8_t but_id);
};

#define RPT_GEMEPAD_LEN     5

class JoystickReportParser : public HIDReportParser {
        JoystickEvents *joyEvents;

        uint8_t oldPad[RPT_GEMEPAD_LEN];
        uint8_t oldHat;
        uint16_t oldButtons;

public:
        JoystickReportParser(JoystickEvents *evt);

        virtual void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
};

#endif // __HIDJOYSTICKRPTPARSER_H__

Edit of the current problem:
(This was fixed with a bit of trial and error in the packed struct)
X: 512 Y: 512 Hat Switch: 0 Twist: 768 Slider: 108 Buttons A: 0 Buttons B: 0
X: 512 Y: 512 Hat Switch: 0 Twist: 256 Slider: 108 Buttons A: 0 Buttons B: 0
X: 512 Y: 512 Hat Switch: 0 Twist: 768 Slider: 108 Buttons A: 0 Buttons B: 0
X: 512 Y: 512 Hat Switch: 0 Twist: 256 Slider: 108 Buttons A: 0 Buttons B: 0
X: 512 Y: 512 Hat Switch: 0 Twist: 768 Slider: 108 Buttons A: 0 Buttons B: 0
X: 512 Y: 512 Hat Switch: 0 Twist: 256 Slider: 108 Buttons A: 0 Buttons B: 0
X: 512 Y: 512 Hat Switch: 0 Twist: 768 Slider: 108 Buttons A: 0 Buttons B: 0
X: 512 Y: 512 Hat Switch: 0 Twist: 256 Slider: 108 Buttons A: 0 Buttons B: 0
X: 512 Y: 512 Hat Switch: 0 Twist: 768 Slider: 108 Buttons A: 0 Buttons B: 0
X: 512 Y: 512 Hat Switch: 0 Twist: 256 Slider: 108 Buttons A: 0 Buttons B: 0
X: 512 Y: 512 Hat Switch: 0 Twist: 768 Slider: 108 Buttons A: 0 Buttons B: 0

Edit for if statement issue:
Below is a section of the what my issue pretty much goes down to.
Now, I am assuming here that structs act in a similar way to dictionaries in python which I think is a massive simplification as they also seem to work as a class? Anyway, I was working on a way to have a first struct with the data for a specific joystick in, then using the data from that first to fill the second that will be used multiple times in the code but I think that is a worse method then what I have below and I couldn't get it to work anyway.
.cpp
#include "le3dp_rptparser.h"
#define __HIDJOYSTICKRPTPARSER_H__

#include <usbhid.h>

struct LogitechGamePro
{
  union { //axes and hut switch
    uint32_t axes;
    struct {
      uint32_t x : 10;
      uint32_t y : 10;
      uint32_t twist : 9;
      uint32_t slider : 10;
    };
  };
  uint8_t hat;
  uint8_t buttons_a;
  uint8_t buttons_b;
};

struct GamePadEventData
{
  union { //axes and hut switch
    uint32_t axes;
    struct {
      uint32_t x : 10;
      uint32_t y : 10;
      uint32_t twist : 9;
      uint32_t slider : 10;
    };
  };
  uint8_t hat;
  uint8_t buttons_a;
  uint8_t buttons_b;
};

JoystickReportParser::JoystickReportParser(JoystickEvents *evt) :
    joyEvents(evt)
{}

void JoystickReportParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
{

    bool match = true;

    // Checking if there are changes in report since the method was last called
    for (uint8_t i=0; i<RPT_GAMEPAD_LEN; i++) {
        if( buf[i] != oldPad[i] ) {
            match = false;
            break;
        }
  }
    // Calling Game Pad event handler
    if (!match && joyEvents) {
        joyEvents->OnGamePadChanged((const GamePadEventData*)buf);

        for (uint8_t i=0; i<RPT_GAMEPAD_LEN; i++) oldPad[i] = buf[i];
    }

}

void JoystickEvents::OnGamePadChanged(const GamePadEventData *evt)
{
    Serial.print("X: ");
    PrintHex<uint16_t>(evt->x, 0x80);
    Serial.print(" Y: ");
    PrintHex<uint16_t>(evt->y, 0x80);
    Serial.print(" Hat Switch: ");
    PrintHex<uint8_t>(evt->hat, 0x80);
    Serial.print(" Twist: ");
    PrintHex<uint8_t>(evt->twist, 0x80);
    Serial.print(" Slider: ");
    PrintHex<uint8_t>(evt->slider, 0x80);
  Serial.print(" Buttons A: ");
    PrintHex<uint8_t>(evt->buttons_a, 0x80);
    Serial.print(" Buttons B: ");
    PrintHex<uint8_t>(evt->buttons_b, 0x80);
    Serial.println("");
}

.h
#if !defined(__HIDJOYSTICKRPTPARSER_H__)
#define __HIDJOYSTICKRPTPARSER_H__

#include <usbhid.h>

struct GamePadEventData {};

struct ST290 {};
struct LogitechGamePro {};

class JoystickEvents
{
public:
    virtual void OnGamePadChanged(const GamePadEventData *evt);
};

#define RPT_GAMEPAD_LEN sizeof(GamePadEventData)/sizeof(uint8_t)

class JoystickReportParser : public HIDReportParser
{
    JoystickEvents      *joyEvents;

  uint8_t oldPad[RPT_GAMEPAD_LEN];

public:
    JoystickReportParser(JoystickEvents *evt);

    virtual void Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);
};

#endif // __HIDJOYSTICKRPTPARSER_H__

Error from Example code 2:
sketch\le3dp_rptparser.cpp: In member function 'virtual void JoystickReportParser::Parse(USBHID*, bool, uint8_t, uint8_t*)':
le3dp_rptparser.cpp:36:54: error: no matching function for call to 'JoystickEvents::OnGamePadChanged(GamePadEventData&)'
             joyEvents->OnGamePadChanged(currentValues);
                                                      ^
In file included from sketch\le3dp_rptparser.cpp:1:0:
sketch\le3dp_rptparser.h:43:15: note: candidate: virtual void JoystickEvents::OnGamePadChanged(const GamePadEventData*)
  virtual void OnGamePadChanged(const GamePadEventData *evt);
               ^~~~~~~~~~~~~~~~
sketch\le3dp_rptparser.h:43:15: note:   no known conversion for argument 1 from 'GamePadEventData' to 'const GamePadEventData*'
sketch\le3dp_rptparser.cpp: At global scope:
le3dp_rptparser.cpp:46:6: error: prototype for 'void JoystickEvents::OnGamePadChanged(GamePadEventData*)' does not match any in class 'JoystickEvents'
 void JoystickEvents::OnGamePadChanged(GamePadEventData *evt)
      ^~~~~~~~~~~~~~
In file included from sketch\le3dp_rptparser.cpp:1:0:
le3dp_rptparser.h:43:15: error: candidate is: virtual void JoystickEvents::OnGamePadChanged(const GamePadEventData*)
  virtual void OnGamePadChanged(const GamePadEventData *evt);
               ^~~~~~~~~~~~~~~~
exit status 1
no matching function for call to 'JoystickEvents::OnGamePadChanged(GamePadEventData&)'

Reading and understanding a report descriptor can be a bit of a black art at times. They're quite cryptic when you first look at them, but actually they make perfect sense.
If you think of each entry (except "input" or "output") as setting some configuration value, and the "input" and "output" entries as using those configuration values, it makes more sense.
Since you are only working with gamepads and joysticks (essentially the same thing) much of the descriptor can be ignored (however you sill have to parse it to get to the other stuff).  So let's take your example descriptor a line (or group of lines) at a time and see what they all mean, and what they mean to you.
Usage Page Gen Desktop Ctrls(01)
Usage Game Pad
Collection Application
Usage Pointer
Collection Physical
Usage Page Gen Desktop Ctrls(01)

You don't much care about these from a data perspective, but they do define what the following data is interpreted as. This tells you that "The following data is for configuring the pointer aspect (direction, not mouse pointer) of a game pad.
Usage X
Usage Y

These are the parameters that we are now configuring (joystick X and Y movement). We group them together because they have common settings and parameters. Those parameters are coming up.
Logical Min(00)
Logical Max(FF03)
Physical Min(00)
Physical Max(FF03)

This is the range of the values that we are going to be reporting, and what that range means. In this case there is a 1:1 mapping between the values the joystick reports (Logical) and what those values map to (Physical). We see a better usage of this later on.  The numbers are "little endian", which means that "FF03" is actually "0x03FF", so the joystick reports values between 0 and 1023.
Unit(00)

This defines the physical units of the value being reported. In this case there are no units. Again we see a better usage of this later on.
Report Size(0A)
Report Count(02)

Now we get into the nitty gritty of the data being sent.  This tells us that each report value is 0x0A (10) bits in size, and there are 2 of them. That's 1 report for the X value of 10 bits, and 1 report for the Y value of 10 bits (in that order, since that is the order of the "Usage" lines above).
So so far we have 20 bits of data in our report that are laid out in bytes as:
XXXXXXXX
YYYYYYXX
....YYYY

There's 4 bits not filled in our bytes yet, but don't worry, they're coming soon. Next comes the "Input" entry:
Input(00000010)

This is where it actually creates the data in the report according to the settings we have set above.  The 00000010 tells us that it's a variable data value that is being sent.
Now we have another similar chunk for the Z (throttle) and Rz (rotational Z) values:
Usage Rz
Usage Z
Logical Min(00)
Logical Max(FF01)
Physical Min(00)
Physical Max(FF01)
Unit(00)
Report Size(09)
Report Count(02)
Input(00000010)

This is almost the same as above, but the numbers are different.  We have 2 usages of Rz and Z (in that order), and they report values between 0 and 0x01FF (511).  Again there are no units to these numbers.  The report size is 9 bits (by the way, 29-1 is 511), and there are two reports, one for Rz and one for Z.
So lets feed these into our bytes, 9 bits of z (I'll use "z" for Rz) and 9 for Z:
XXXXXXXX
YYYYYYXX
zzzzYYYY
ZZZzzzzz
..ZZZZZZ

You see we still have two bits unused in our bytes. HID reports don't like unused bits, so we need to pad those out before moving on to a new area of interest:
Report Size(01)
Report Count(02)
Input(00000001)

Here we're defining a report size of 1 bit and there's two reports. That's 2 bits. These are our padding bits to fill out those extra two bits above. You see the Input entry has a different number with it.  00000001 tells us that this is constant data. It's nothing that will ever change - just padding.
So now our HID report looks like:
XXXXXXXX
YYYYYYXX
zzzzYYYY
ZZZzzzzz
00ZZZZZZ

Now we move on to the "Hat switch", which is somewhat similar, but not quite:
Usage Hat Switch
Logical Min(01)
Logical Max(08)
Physical Min(00)
Physical Max(3B01)
Unit(14)
Report Size(08)
Report Count(01)
Input(00000010)

Here we have 1 report of 8 bits. We're sending a value between 1 and 8 for the 8 directions of the hat switch (you can only have 1 direction at a time), and we're using an entire byte to send that value in. It sounds wasteful, given that we only need 4 bits to represent the number 8, but remember we would have to pad the other 4 bits with a constant value to bring it up to a round byte. So it's simpler to just use the whole byte in this instance and save having to have a padding section in the descriptor.
You notice that the logical and physical min and max differ in this section. That shows you what you would map the logical values to in a "real world" situation.  In this case the values 1-8 map to the real values 0-315 (0x01b3). It's up to you if you actually do that mapping or not. What are those numbers though? Well, if you divide 315 by 8 (the number of hat positions) you get 45. And each hat position is a 45° increment. So they must map to degrees. And look, "Unit" hs a value of 0x14 in it. If we look that up we see that 0x14 corresponds to "English Rotational Angular Position", or "degrees" in normal speech.
We can now add that to our report format:
XXXXXXXX
YYYYYYXX
zzzzYYYY
ZZZzzzzz
00ZZZZZZ
HHHHHHHH

And finally we have 6 buttons:
Usage Page Button(09)
Usage Min(01)
Usage Max(06)
Logical Min(00)
Logical Max(01)
Physical Min(00)
Physical Max(01)
Report Size(01)
Report Count(06)
Input(00000010)

There is no "Button 1" etc usage in HID, but you can define a range for the usage, which is what has been done here. Basically since we're in the "buttons" usage page we define a range of 1-6 for the buttons - so there's button 1 to button 6 inclusive.
Each button is either 0 or 1 (not pressed, or pressed), and that's the same "In the real world".  Each button has a 1 bit report, since that's all you need, and there are 6 reports, one for each button.
Again we're only using 6 out of the 8 bits of a byte for this, so we pad it out with two more constant bits:
Report Size(01)
Report Count(0A)
Input(00000001)

So if we now add those buttons we get our final report format:
XXXXXXXX
YYYYYYXX
zzzzYYYY
ZZZzzzzz
00ZZZZZZ
HHHHHHHH
00654321

So you have 7 bytes of data that you then have to split up and recombine in the right way with all sorts of bit shifting and masking to extract the real values. And of course this varies from joystick to joystick.
As you can guess writing a parser not only for the HID descriptor itself, but to extract the data in accordance with that descriptor, will be quite a task. Some joysticks will have the values all packed together, some won't. Some will need to have things read in one order, and some in another. Some will have more buttons, or more axes of motion than others.
You can read the HID 1.11 specification here which will tell you all about how the raw numbers map to the different things.
The existing parser code is looking for things in hard coded positions in the data coming in and is doing it in very basic ways. It doesn't honour the report descriptor in any way, and instead just takes each byte as an axis.
You would need to re-write that entire Parse() function (or create a child class that overrides it) to use the information you have parsed from the report descriptor to extract the values from the data bytes in the right way. Given the myriad ways it could be done you will have quite a task ahead of you. It would be easier to just support specific joysticks and hard-code the options for them, maybe make a separate subclass for each joystick each with its own overridden Parse() function. It's up to you to then use the different classes in your code as you need.

To address your other problems:

In the header file have the definitions for your structs:

struct LogitechGamePro
{
  union { //axes and hut switch
    uint32_t axes;
    struct {
      uint32_t x : 10;
      uint32_t y : 10;
      uint32_t twist : 9;
      uint32_t slider : 10;
    };
  };
  uint8_t hat;
  uint8_t buttons_a;
  uint8_t buttons_b;
};

struct GamePadEventData
{
  union { //axes and hut switch
    uint32_t axes;
    struct {
      uint32_t x : 10;
      uint32_t y : 10;
      uint32_t twist : 9;
      uint32_t slider : 10;
    };
  };
  uint8_t hat;
  uint8_t buttons_a;
  uint8_t buttons_b;
};

In the .cpp file use those for casting and population:

void JoystickReportParser::Parse(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf)
{

    struct GamePadEventData currentValues;

    bool match = true;

    // Checking if there are changes in report since the method was last called
    for (uint8_t i=0; i<RPT_GAMEPAD_LEN; i++) {
        if( buf[i] != oldPad[i] ) {
            match = false;
            break;
        }
    }
    // Calling Game Pad event handler
    if (!match && joyEvents) {
        // if (joystick is the logitech game pro) {
            // Overlay the struct on top of the data by casting it to
            // a new variable
            struct LogitechGamePro *jsdata = (LogitechGamePro *)buf;

            // Copy values from the temporary overlaid struct into
            // a real variable of the right type for the callback
            currentValues.x = jsdata->x;
            currentValues.y = jsdata->y;
            currentValues.z = jsdata->z;
            // etc

            // Call the callback with that real variable
            joyEvents->OnGamePadChanged(&currentValues);
        // } else if (joystick is some other joystick) {
        //     do the same as above with a different joystick struct
        // } ... etc ...

        for (uint8_t i=0; i<RPT_GAMEPAD_LEN; i++) oldPad[i] = buf[i];
    }

}

thanks so much, this helped me to actually understand the report desc. It's unfortunate that I don't have the coding skills to rewrite the parse function to use the report descriptor.
For changing the specific options for each joystick, I assume I would need to change the struct GamePadEventData?
would I do something like this: (from example)
uint32_t x : 10;
uint32_t y : 10;
and change the numbers after?
I am probably wrong but do those numbers after correspond to the range of each axis? (mins/maxs),  Thanks again

Yep, using a packed struct like that is a good way of extracting the data.

Hello, I used the struct and it is almost working perfectly. The only issue is that the twist is flickering between 256 and 768. I have edited a sample in my original question from the serial monitor. It happens whenever the slide isn't at the 0 and happens much more quickly when the slide is in motion. Any advice is appreciated thankyou

Okay, I sorted the problem out. For anyone wondering I had the packed struct a bit wrong. Trial and error for about a minute sorted it for me but you could do it with the report descriptor instead.

My issue is now selecting between structs. My original plan was to have an array for each joystick type and then selecting which array to use to fill in the numbers for the struct. Unfortunately, the order of each axis matters so that's a no go. I am not great at c but know the basics. How would you suggest changing between packed structs? Thanks

You would probably want a big if-then-else (or a switch/case) to overlay the struct over the byte array of the incoming data (cast it), then copy the values from the struct into some standard other struct / array to use later in your program.

Ah okay thankyou, that clears it up.

Hey, I'm trying to wrap the struct in an if statement but its just giving me expected unqualified-id before 'if' Any ideas?
Thanks

Not without seeing your code.

good point, I'll edit it into the question with a more details

I added a section of a simple version of what I'm trying to do with some details of another way I went about it.

@VosemMedia There's nothing wrong with that snippet. It compiles fine. And it's a perfectly valid way of doing it.

It doesn't seem to compile for me, probably because its in a header file? I moved the header/cpp to the top of the ino and it still didn't compile. I added a larger portion of my code in. Thanks

Your if must be inside a function. Executable code outside a function is not valid C.

hmm interesting, thankyou. I added in a void function (edited in the original question) and now it's giving me 'GamePadEventData' does not name a type from the .cpp file. Any further ideas? I don't know why putting it in a function/if statement is bringing these problems. Thanks again

Your structure only exists within the scope it is defined in: in this case the function you just wrapped it in.

so I should put everything in that file into a single function?

You should put things in the areas where they are needed. You should first define multiple structs with different names. Then in your packet decoder you cast your incoming data to one of the structs depending on which joystick is connected. Then you copy your data from that cast variable struct to your live data struct. It's those last bits that go in the if, not the definition of the struct.

So in my .h file, I should declare multiple structs for each type of joystick, then where and how should I move the data from the selected struct (e.g logitech joystick) into the live struct. Should I do it in the cpp file? if so, should I wrap all of the areas that require the struct in a single function? Thanks

Yes, do it in the CPP file. In the parse function. Use casting of the data array: if (joystick == LOGITECH_GAME_PRO) {struct LogitechGamePro *jsdata = (struct LogitechGamePro *)data; mydata.x = jsdata->x; ... } for example.

Thanks for the code, I have a couple of questions. If I declare my structs in the CPP file and change the data in the live struct in a CPP function, how will the .h functions get access to it? It's giving me a gamepaddata does not give a type, presumably because it's not defined in the .h file. How can the .h get access to it defined in the cpp? Also, from your code, would I edit to to look something like struct GamePadEventData (the live one) *jsdata = (struct LogitechGamePro (the one we want to chage the live one to) *)data; mydata.x = jsdata->x;  and also add more eg mydata.y = ...

No. GamePadEventData is the struct that would define the variable you want to copy to (mydata in that example).

Ah okay that makes more sense, so the mydata is an example struct which you copy to. I am still getting virtual void OnGamePadChanged(const GamePadEventData *evt); exit status 1 'GamePadEventData' does not name a type from the header. It's because I am declaring the structs in the CPP. What do you reccomend? Thanks

Declare the structs in the .h file (that is, just the struct foo {...}; portion). Use the structs in the CPP file as variable types.

Okay, I removed all the nonsense I had before and am trying to get the bare bones working. I removed the casting of structs because that's a separate problem that ill tackle after this first one. I declared the structs in the .h like you recommended but populated them in the .cpp (as you can see in the code I edited in). Unfortunately, I am getting a redeclaration error (in the .cpp) because I have previously created them in the .h. I would have thought, just removing the struct variable type would have sorted it but I don't think you can do that in C. Thanks

Your empty structs in the .h should be the full structs that are currently in the .cpp. The structs in the .cpp should not exist.

I have edited in some example code to the end of my answer.

Thankyou for all that example code, I think i'm finally wrapping my head around it all. its bringing up one error, no matching function for call to 'JoystickEvents::OnGamePadChanged(GamePadEventData&)' from the line joyEvents->OnGamePadChanged(currentValues); thanks. I also added in the full error into the bottom of my question

Probably needs to be a pointer actually...

Thank you so much, that got it working perfectly. I know the question was super old when I put a new comment and I would have understanded if you just ignored it. Cheers for helping me this has sorted all of my issues :)

Glad to be of help.


text:
Strange behaviour with WS2812B RGB LED Strip
I tried to use a RGB LED strip, following a guide.
I connected the voltage pin to the Arduino UNO 5v pin, the ground pin to the GRN pin and I used the pin 5 for DIN.
I used this image as reference:

I tried two different libraries, with the first one, the FAST LED, I used this code:
#include <FastLED.h>

#define LED_PIN     5
#define NUM_LEDS    15
#define BRIGHTNESS  64
#define LED_TYPE    WS2811
#define COLOR_ORDER GRB
CRGB leds[NUM_LEDS];

#define UPDATES_PER_SECOND 100

CRGBPalette16 currentPalette;
TBlendType    currentBlending;

extern CRGBPalette16 myRedWhiteBluePalette;
extern const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM;

void setup() {
    delay( 3000 ); // power-up safety delay
    FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
    FastLED.setBrightness(  BRIGHTNESS );

    currentPalette = RainbowColors_p;
    currentBlending = LINEARBLEND;
}

void loop()
{
    ChangePalettePeriodically();

    static uint8_t startIndex = 0;
    startIndex = startIndex + 1; /* motion speed */

    FillLEDsFromPaletteColors( startIndex);

    FastLED.show();
    FastLED.delay(1000 / UPDATES_PER_SECOND);
}

void FillLEDsFromPaletteColors( uint8_t colorIndex)
{
    uint8_t brightness = 255;

    for( int i = 0; i < NUM_LEDS; i++) {
        leds[i] = ColorFromPalette( currentPalette, colorIndex, brightness, currentBlending);
        colorIndex += 3;
    }
}

void ChangePalettePeriodically()
{
    uint8_t secondHand = (millis() / 1000) % 60;
    static uint8_t lastSecond = 99;

    if( lastSecond != secondHand) {
        lastSecond = secondHand;
        if( secondHand ==  0)  { currentPalette = RainbowColors_p;         currentBlending = LINEARBLEND; }
        if( secondHand == 10)  { currentPalette = RainbowStripeColors_p;   currentBlending = NOBLEND;  }
        if( secondHand == 15)  { currentPalette = RainbowStripeColors_p;   currentBlending = LINEARBLEND; }
        if( secondHand == 20)  { SetupPurpleAndGreenPalette();             currentBlending = LINEARBLEND; }
        if( secondHand == 25)  { SetupTotallyRandomPalette();              currentBlending = LINEARBLEND; }
        if( secondHand == 30)  { SetupBlackAndWhiteStripedPalette();       currentBlending = NOBLEND; }
        if( secondHand == 35)  { SetupBlackAndWhiteStripedPalette();       currentBlending = LINEARBLEND; }
        if( secondHand == 40)  { currentPalette = CloudColors_p;           currentBlending = LINEARBLEND; }
        if( secondHand == 45)  { currentPalette = PartyColors_p;           currentBlending = LINEARBLEND; }
        if( secondHand == 50)  { currentPalette = myRedWhiteBluePalette_p; currentBlending = NOBLEND;  }
        if( secondHand == 55)  { currentPalette = myRedWhiteBluePalette_p; currentBlending = LINEARBLEND; }
    }
}

void SetupTotallyRandomPalette()
{
    for( int i = 0; i < 16; i++) {
        currentPalette[i] = CHSV( random8(), 255, random8());
    }
}

void SetupBlackAndWhiteStripedPalette()
{
    fill_solid( currentPalette, 16, CRGB::Black);
    currentPalette[0] = CRGB::White;
    currentPalette[4] = CRGB::White;
    currentPalette[8] = CRGB::White;
    currentPalette[12] = CRGB::White;

}

// This function sets up a palette of purple and green stripes.
void SetupPurpleAndGreenPalette()
{
    CRGB purple = CHSV( HUE_PURPLE, 255, 255);
    CRGB green  = CHSV( HUE_GREEN, 255, 255);
    CRGB black  = CRGB::Black;

    currentPalette = CRGBPalette16(
                                   green,  green,  black,  black,
                                   purple, purple, black,  black,
                                   green,  green,  black,  black,
                                   purple, purple, black,  black );
}

const TProgmemPalette16 myRedWhiteBluePalette_p PROGMEM =
{
    CRGB::Red,
    CRGB::Gray,
    CRGB::Blue,
    CRGB::Black,

    CRGB::Red,
    CRGB::Gray,
    CRGB::Blue,
    CRGB::Black,

    CRGB::Red,
    CRGB::Red,
    CRGB::Gray,
    CRGB::Gray,
    CRGB::Blue,
    CRGB::Blue,
    CRGB::Black,
    CRGB::Black
};

and with the second library, Adafruit_Neopixel
#include <Adafruit_NeoPixel.h>
#define PIN 5
#define NUM_LEDS 15
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

// *** REPLACE FROM HERE ***
void loop() {
  RGBLoop();
}

void RGBLoop(){
  for(int j = 0; j < 3; j++ ) {
    // Fade IN
    for(int k = 0; k < 256; k++) {
      switch(j) {
        case 0: setAll(k,0,0); break;
        case 1: setAll(0,k,0); break;
        case 2: setAll(0,0,k); break;
      }
      showStrip();
      delay(3);
    }
    // Fade OUT
    for(int k = 255; k >= 0; k--) {
      switch(j) {
        case 0: setAll(k,0,0); break;
        case 1: setAll(0,k,0); break;
        case 2: setAll(0,0,k); break;
      }
      showStrip();
      delay(3);
    }
  }
}
// *** REPLACE TO HERE ***

void showStrip() {
 #ifdef ADAFRUIT_NEOPIXEL_H
   // NeoPixel
   strip.show();
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED.show();
 #endif
}

void setPixel(int Pixel, byte red, byte green, byte blue) {
 #ifdef ADAFRUIT_NEOPIXEL_H
   // NeoPixel
   strip.setPixelColor(Pixel, strip.Color(red, green, blue));
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   leds[Pixel].r = red;
   leds[Pixel].g = green;
   leds[Pixel].b = blue;
 #endif
}

void setAll(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  showStrip();
}

I don't know why, but only some of the leds in the strips make lights and only blue lights. How can I fix this problem?
I also tried to change the Din pin using 4, 5 and 6, but nothing changed.
EDIT
I found that all my led were broken... I bought a new strip and now I have a prototype perfectly working using any of the code above. Thanks for helping me

How long is the strip? How many LEDs? Did you calculate how much current it can draw? How are you powering your Arduino?

@EdgarBonet the strip has 15 leds and I defined the number in the global variables.I'm powering Arduino using USB cable. Thanks for your reply

15 LEDs, all on full bright, need 15 x 3 x 20mA =  900mA.  USB can only supply 500mA. Try putting a Serial.print in setup() and see if the Arduino is resetting.

Is Serial.print without params in input?

Serial.begin(9600);   Serial.println ("reset");

@CrossRoadsI tried but nothing changed.. Do you have any other suggestions?

In the first sketch you use
#define LED_TYPE    WS2811

While you have WS2812
Each led strip type has different timings, so it can occur that some LEDs will flash, or are on or off while they should not be, if the wrong model is selected.
Probably the first LEDs work better than later ones.

WS2811 data sheet https://cdn-shop.adafruit.com/datasheets/WS2811.pdf vs WS2812 datasheet https://cdn-shop.adafruit.com/datasheets/WS2812.pdf  WS2812 has built in LEDs and can run at a slightly faster speed.

I tried what you proposed but nothing changed..

What makes you sure replacing the LED strip was the solution? I suggest running the LED strip from the Arduino +5V is a likely problem (too much current drawn) and using a different LED strip you've just been lucky that it works now.
Try with a separate power supply for the LEDs but connect grounds together. If you don't have another 5V power supply which can supply at least 1 Amp, try limiting the brightness and/or number of LEDs in software to see if it works and if so, then try with the original strip.

"What makes you sure replacing the LED strip was the solution?" I bought exactly the same model, the same RGB led strip and now it works perfectly. I also tried with a 5V battery and with the old strip the result was the same, only four led worked.

source: Stack Exchange

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

sort: votes


text:
Can someone help me to change this code to u8g2
I would like to change this clock to u8g2.
It works fine with the esp8266 and oled 128x64.

I would start by including the u8g2 library with #include
and all display. with u8g2. replace.
What else should I consider.?
Thanks Else
This is my Code
#include <ESP8266WiFi.h>
#include <WifiUDP.h>
#include <String.h>
#include <Wire.h>
#include <SSD1306.h>
#include <SSD1306Wire.h>
#include <NTPClient.h>
#include <Time.h>
#include <TimeLib.h>
#include <Timezone.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
// Define NTP properties
#define NTP_OFFSET   60 * 60      // In seconds
#define NTP_INTERVAL 60 * 1000    // In miliseconds
#define NTP_ADDRESS  "ca.pool.ntp.org"  // change this to whatever pool is closest (see ntp.org)

// Set up the NTP UDP client
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, NTP_ADDRESS, NTP_OFFSET, NTP_INTERVAL);

// Create a display object // SSD1306 display(0x3c, SDA, SCL);
SSD1306  display(0x3c, D2, D1); //0x3d for the Adafruit 1.3" OLED, 0x3C being the usual address of the OLED

//U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ 5, /* data=*/ 4, /* reset=*/ U8X8_PIN_NONE);

const char* ssid = "my ssid";   // insert your own ssid
const char* password = "my password";    // and password
String date;
String t;
const char * days[] = {"So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"} ;
const char * months[] = {"Jan", "Feb", "Mär", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"} ;

void setup ()
{
  Serial.begin(115200); // most ESP-01's use 115200 but this could vary
  timeClient.begin();   // Start the NTP UDP client

  Wire.pins(4, 5);
  Wire.begin(4, 5);
  display.begin();
  display.flipScreenVertically();

  // Connect to wifi
  Serial.println("");
  Serial.print("Connecting to ");
  Serial.print(ssid);
  display.drawString(0, 10, "Connecting to Wifi...");
  display.display();
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi at ");
  Serial.print(WiFi.localIP());
  Serial.println("");
  display.drawString(0, 24, "Connected.");
  display.display();
  delay(1000);
}

void loop()
{
  if (WiFi.status() == WL_CONNECTED) //Check WiFi connection status
  {
    date = "";  // clear the variables
    t = "";

    // update the NTP client and get the UNIX UTC timestamp
    timeClient.update();
    unsigned long epochTime =  timeClient.getEpochTime();

    // convert received time stamp to time_t object
    time_t local, utc;
    utc = epochTime;

  /*  // Then convert the UTC UNIX timestamp to local time
    TimeChangeRule usEDT = {"EDT", Second, Sun, Mar, 2, -0};  //UTC - 5 hours - change this as needed
    TimeChangeRule usEST = {"EST", First, Sun, Nov, 2, -60};   //UTC - 6 hours - change this as needed
    Timezone usEastern(usEDT, usEST); */

    TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 60};     //Central European Summer Time
    TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 0};       //Central European Standard Time
    Timezone CE(CEST, CET);

    local = CE.toLocal(utc);

    // now format the Time variables into strings with proper names for month, day etc
    date += days[weekday(local)-1];
    date += ", ";
    date += day(local);
    date += " ";
    date += months[month(local)-1];
    date += " ";
    date += year(local);

    // format the time to 12-hour format with AM/PM and no seconds
    if(hour(local) < 10)  // add a zero if houre is under 10
      t += "0";
    t += hour(local);
    t += ":";
    if(minute(local) < 10)  // add a zero if minute is under 10
      t += "0";
    t += minute(local);
    t += ":";
    if(second(local) < 10)  // add a zero if minute is under 10
      t += "0";
    t+= second(local);

    // Display the date and time
    Serial.println("");
    Serial.print("Local date: ");
    Serial.print(date);
    Serial.println("");
    Serial.print("Local time: ");
    Serial.print(t);

    // print the date and time on the OLED
    display.clear();
    display.setTextAlignment(TEXT_ALIGN_CENTER);
    display.setFont(ArialMT_Plain_24);
    display.drawStringMaxWidth(64, 10, 128, t);
    display.setFont(ArialMT_Plain_10);
    display.drawStringMaxWidth(64, 48, 128, date);
    display.fillRect(1, 0, 126*timeClient.getSeconds()/59, 2);
    display.display();
  }
  else // attempt to connect to wifi again if disconnected
  {
    display.clear();
    display.drawString(0, 10, "Connecting to Wifi...");
    display.display();
    WiFi.begin(ssid, password);
    display.drawString(0, 24, "Connected.");
    display.display();
    delay(1000);
  }

  delay(1000);    //Send a request to update every 10 sec (= 10,000 ms)
}

Without really looking at your code: You will have to replace all code, that does something with the display, with code for the new display library. Have you tried that? What was your problem there?

So I have a litle problem with:
display.fillRect(1, 0, 126timeClient.getSeconds()/59, 2); old
u8g2.fillRect(1, 0, 126timeClient.getSeconds()/59, 2); -> new
'class U8G2_SSD1306_128X64_NONAME_F_SW_I2C' has no member named 'fillRect'
and
display.drawStringMaxWidth(64, 48, 128, date); -> old
u8g2.drawStringMaxWidth(64, 48, 128, date); -> new

Please edit your question do add these information. 2. Since these are completely different libraries, the functions won't be the same. You cannot just rename the display object for the new library. You have to go through the code line by line and replace each call to the former library by a suitable call to the new library, that will reach the goal of that line. Changing between different libraries is mostly a complex task (unless they are really designed for being exchangeable for one another. Have you searched the documentation of the new library for a fitting function?

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


text:
WT8266-S1 WiFi module
WT8266-S1 WiFi module in my hand I want to encode this module with Ardino IDE. I have a coded program for Arduino NodeMCU 1.0. How can I convert it to the WT8266-S1 WiFi module? Do you have the WT8266-S1 WiFi module source code? Firebase connection to do the application to turn off the LED. Below is a sample code share.
#include <SoftwareSerial.h>

SoftwareSerial esp01(9,11);

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

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

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

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

  sendData("AT+RST\r\n",2000);
  sendData("AT+CWMODE=2\r\n",1000);
  sendData("AT+CIFSR\r\n",1000);
  sendData("AT+CIPMUX=1\r\n",1000);
  sendData("AT+CIPSERVER=1,80\r\n",1000);
}

void loop()
{
  if(esp01.available())
  {
    if(esp01.find("+IPD,"))
    {
     delay(1000);

     // odczytanie ID połączenia
     int connectionId = esp01.read()-48;

     esp01.find("pin=");

     int pinNumber = (esp01.read()-48)*10;
     pinNumber += (esp01.read()-48);
     digitalWrite(pinNumber, !digitalRead(pinNumber));
      String closeCommand = "AT+CIPCLOSE=";
     closeCommand+=connectionId;
     closeCommand+="\r\n";

     sendData(closeCommand,1000);
    }
  }
}

String sendData(String command, const int timeout)
{
    String response = "";

    esp01.print(command);

    long int time = millis();

    while( (time+timeout) > millis())
    {
      while(esp01.available())
      {
        char c = esp01.read();
        response += c;
      }
    }
    Serial.print(response);
    return response;
}

Warning: espcomm_sync failed when I install this thread
error: espcomm_open failed
error: espcomm_upload_mem failed
error: espcomm_upload_mem failed
 getting the error

what did you try?

I shared a sample code on the subject.

this a sketch for an MCU with external esp8266 module with AT firmware  wired to Serial interface. you try to upload it to the esp8266?

Is it possible that I want to load code into module WT8266? I wrote code for NodeMCU 1.0 and I want to edit it for the wt8266 module. @Juraj

Can I write code for wt8266 as same as esp8266? Is this possible? @Juraj

don't know. but sure is, you can't use the esp8266 AT firmware 'from inside'. because if you upload your sketch, it replaces the AT firmware as the application running on the esp8266. how did you wire the WT8266 and do you put it into flashing mode before upload?

I understood thank you. Connected to computer with USB TTL cable. Yes is currently running in flashing mode. @Juraj

has it AT firmware? can you execute AT command on in from computer? for example from Serial Monitor of the Arduino IDE?


text:
ESP-12F responds only to a few basic AT commands
I previously read a few guides and tutorials about the ESP8266 and i just started using the ESP-12F module as i think that it is a terrific replacement for Arduino with the added benefit of Wi-Fi. I only have the module itself which is basically a metal casing so, i wired up the ESP-12F module according to this schematic.
My USB-TTL board is operating at 3 V for its VCC and also for the TX and RX logic levels. I use Arduino IDE 1.8.9 (i made sure that i am using the latest stable version) and then set the COM port to the USB-TTL RS232 connected to the ESP12F and typed "AT" and got a response "OK". Then, i tried, "AT+RST" and got a big bunch of text which proved that there is successful communication with the ESP module. But then, i tried to connect the ESP-12F to my Wi-Fi network, so i entered: AT+CWJAP_CUR="SSID","password" replacing the SSID and password with my own and it gave the response "ERROR", so i tried the old format AT+CWJAP="SSID","password" and again i got "ERROR". So, what am i doing wrong? How to fix this? I was thinking that maybe the firmware on my ESP is old and needs to be updated, so i entered "AT+GMR" and i got this info:
19:07:27.560 -> ready
19:07:27.560 -> AT+GMR
19:07:27.560 -> AT version:1.2.0.0(Jul  1 2016 20:04:45)
19:07:27.560 -> SDK version:1.5.4.1(39cb9a32)
19:07:27.560 -> Ai-Thinker Technology Co. Ltd.
19:07:27.560 -> Dec  2 2016 14:21:16
19:07:27.560 -> OK

Do i need to update my module to be able to connect it to my Wi-Fi? If yes, how? I want to update it as safely as possible as this is my only ESP module and i don't want to inadvertently damage it.

Try AT+CWMODE=1 first to put it into STA mode.

I did as you said and it worked! Thanks for the help. I will keep digging into the Espressif AT commands datasheet to learn more. By the way, is it advisable to update the firmware at this point?

Personally I never use the AT firmware. I always program the ESP8266 directly from the Arduino IDE (well, from UECIDE actually, but the principle is the same).

AT+CIUPDATE after you connected it to Internet

You can't connect to an access point until you put the module into Station mode.
AT+CWMODE=1

That will put it in STA mode.  You can alternatively make it an access point (AP mode) with:
AP+CWMODE=2


text:
How can i connect the Mics-5132 to Arduino Uno (Carbon Monoxide Sensor)

hi. i don't know how can i connect Mics-5132 CO Sensor to my arduino.
plz help

That is a very skimpy data sheet for the MiCS-5132 .  (Shame on manufacturer for not including isolation information between heater and resistor output).
Connect 3.2 volts (3.3 volts is ok) to pins 1 and 3 (heater). Keep in mind the heater will draw about 32 mA.
Pins 2 and 4 are the output.  The output is a resistor, whose value changes with the degree of detected gases. And the resistance is about 160 k ohms.
Wire a resistor (call it R1) from VCC (positive power) to your input. Start out with R1 = 150k  (anything from 120K to 180K). .
Wire the sensor (pin2) to your input (use an input that can do A/D conversion).  Wire the other side of the sensor (pin 4) to your board ground.
This makes a resistor voltage divider to your input pin. Your input pin should be an A/D converter.  The A/D converter input should return a value dependent upon the sensor resistance.
Experiment with different values for R1, to get the input range that you desire.

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


text:
ESP8266 and Arduino Interfacing
I have connected Arduino with ESP8266 with
Arduino pin 2 connected to ESP's Tx Arduino pin 3 connected to ESP's Rx via Voltage Divider Arduino GND connected to ESP's GND Arduino 3v3 connected to ESP's CH_PD
I have powered ESP8266 using 1117 Voltage regulator
When I initially bought ESP8266 it was working properly(I could even set up a server) but now when I connect it to Arduino an endless stream of garbage values is seen on the Serial Monitor...
The arduino is programmed with the following code
#include <SoftwareSerial.h>

SoftwareSerial esp8266(2,3); // make RX Arduino line is pin 2, make TX Arduino line is pin 3.
                             // This means that you need to connect the TX line from the esp to the Arduino's pin 2
                             // and the RX line from the esp to the Arduino's pin 3
void setup()
{
  Serial.begin(9600);
  esp8266.begin(9600); // your esp's baud rate might be different
}

void loop()
{
  if(esp8266.available()) // check if the esp is sending a message
  {
    while(esp8266.available())
    {
      // The esp has data so display its output to the serial window
      char c = esp8266.read(); // read the next character.
      Serial.write(c);
    }
  }

  if(Serial.available())
  {
    // the following delay is required because otherwise the arduino will read the first letter of the command but not the rest
    // In other words without the delay if you use AT+RST, for example, the Arduino will read the letter A send it, then read the rest and send it
    // but we want to send everything at the same time.
    delay(1000);

    String command="";

    while(Serial.available()) // read the command character by character
    {
        // read one character
      command+=(char)Serial.read();
    }
    esp8266.println(command); // send the read character to the esp8266
  }
}

Maybe it helps if you tell us what happened between "initially" and "now"?

Lose the Arduino and program the ESP directly. You can do it with the same language as Arduino.  https://github.com/esp8266/Arduino - also supported in UECIDE - all you need is a USB -> UART dongle.

If the stream of garbage values comes in response to things you send to the ESP8266, then the problem is most likely the baud rate.  For the ESP8266-01 modules that I have used, the default baud rate is 115200.

I had already changed the Baud Rate of the Module to 9600 using AT+BAUD command..

There is a new command for the ESP8266 in AT version:0.50.0.0 - SDK version:1.4.0 that lets you explicitly set the full UART configuration:
AT+UART_CUR – set the current UART configuration
This command sets the current UART configuration; it does not write to the flash. Hence there is no change in the default baud rate.
For example:
AT+UART_CUR=9600,8,1,0,0

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


text:
PID control for Motor Speed control
I was trying to apply PI controller to a motor using Arduino. I have somewhat achieved the task but the problem is that it oscillates too much. Also i couldn't figure out what to do when pwm signal are calculated as negative
  int counter = 0;
  double end_time=0;
  double ini_time=0;
  double rpm=0;
  double my_time=0;
  double temp = 0;
  int pid_speed=0;
  float kp=2.25;
  float ki=.01;
  float kd=0.005;
  int prev_error=0;
  double pwm_sig=0;
  int integrator  = 0;
  int motor_sig_pin= 5;
  int error=0;
  int absolute = 0;
  float desired_rpm=1000; //my desired RPM value
  double zero_time=0;
  double i_time=0;
  double f_time=0;
  int rpm_tacho=0;
  int previous_error=0;
  int derivative=0;

  void setup() {
    pinMode(2,INPUT);
    digitalWrite(2,HIGH);
    pinMode(motor_sig_pin,OUTPUT);
    pinMode(9,OUTPUT);
    pinMode(10,OUTPUT);
    digitalWrite(9,HIGH);
    digitalWrite(10,LOW );
    attachInterrupt (0,Count,RISING);
    ini_time = micros();
    i_time=micros();
    Serial.begin(115200);
  }

   void Count(){ //calculating time for one round using encoder

      counter++;
      if (counter>=100){
        end_time=micros()-ini_time;

        ini_time=micros();
        counter=0;
      }
   }
  void loop() {
      rpm = ((1000000*60)/(end_time));
      rpm = abs(rpm);
      rpm_tacho = ((1000000*60)/(zero_time));
      if (rpm <10 || rpm>5000){
        rpm=0;
      }
      error=desired_rpm-rpm;

      integrator += error;
      pid_speed = kp*error; + ki*integrator;

      pid_speed=(int)pid_speed;

      Serial.print(pid_speed);
      Serial.print("       ");

      if (pid_speed> 0){
        if (pid_speed>255)
          analogWrite(motor_sig_pin,255);
        else
          analogWrite(motor_sig_pin,pid_speed);
      }
      if(pid_speed<0){
        if(pid_speed<-255)
        {
            analogWrite(motor_sig_pin,0);
        }
        else
       {
          pid_speed=abs(pid_speed);
          analogWrite(motor_sig_pin,255-pid_speed);
       }
      }
      Serial.print ("      ");
      Serial.println(rpm);
  }

Just a few comments: 1) end_time is used both in normal context and in interrupt context, it should therefore be qualified as volatile. 2) In loop, as end_time is more than one byte, you should copy it to a local variable while blocking interrupts. 3) You are not using kd. 4) There is a ; before + ki*integrator, which means that the computation of the integral term is a no-op.

@EdgarBonet what do you mean by blocking the interrupt.

noInterrupts(); double end_time_copy = end_time; interrupts();, then use the copy instead of the original. Otherwise Count() may update end_time while you are in the process of reading it.

ini_time and end_time should be unsigned long or uint32_t, otherwise the tachometer will return garbage when micros() rolls-over to zero. 6) Then there is no point in abs(rpm), as rpm cannot be negative. 7) rpm_tacho is unused, and computed by dividing by zero. 8) You should properly indent your code before posting it.

You should also remove all the variables that you never use. 10) There is no point in casting an int to int. 11) Your set of if...else looks too complicated, why not just constrain(pid_speed, 0, 255)? 12) You should not Serial.print() on every loop iteration as it is too much to read and it slows down loop(). 13) But then you should control the update rate or your PID.

pid calculations also spit out negative values, what should i do for that?? @EdgarBonet

constrain(). Or better yet, use a ready-made PID library.

float kp=2.25;; I don't think the proportional part should be more than 1.0, but I might be mistaken here.

@Gerben: The kp can be larger than 1.  It should be whatever it takes to convert the measured input error to the process output.  If the input was radians per second instead of rpm, kp should be 2pi60=376 times larger than the kP would be for a sensor measuring in RPM.

Instead of thinking of the PID output as pid_speed, think of it as motor_power, and what the PI controller is doing is translating errors in rpm into a motor power setting.
You are probably getting oscillation because of integral windup.  If your loop is fast relative to your system, each loop worth of error adds to integrator quickly/quicker than the system can adjust.   For example, if a loop takes 1ms, an error of 100rpm could overflow the "int integrator" past 32768 in only 0.327 seconds, and past the threshold where the integrator could peg the output 25500 (=255/Ki) in only 0.255sec  If the integrator is faster than the system, it can easily cause overshoot.  You might consider slowing the loop down to 10ms, 100ms or 1000s to match the physical process and make the kI term be a sane conversion of the integrator's rpmErrorseconds/100, rpmErrorseconds/10, or rpmError*seconds into output power.
To handle the numerics and constraints better, like overflowing integrators and negative output values, it would probably be best to use the Arduino PID library from http://playground.arduino.cc/Code/PIDLibrary as in Edgar Bonet's comment.

I do not know if this question still exists or you managed to solve it. Regardless, I was (still am) working on a self balancing robot where I also faced such an issue and I came to this forum. The way I tackled it was to set PID outputs (assuming you are using Arduino 's PID library) 0 - 255 instead of -255 to 255. Now for my project I needed to change direction of the motor depending upon the inclination angle of the robot. So, each time I need to change the motor rotation direction, I do the following

I first reset the Iterm (or make it zero).
Change the direction of rotation.
Begin PID computation again.

Earlier I was also trying to achieve this by -255 to 255, but it was very jerky and I was not sure if that was the correct way to do it. With my current approach, I have managed to solve my problem.


text:
Serial.println Sensor Value and text in one line
How do I put the sensor value and text on the one line in the serial monitor.
I just want Pot Value 30 to show in the serial console. What am I doing wrong?
Serial.println("POT value ")(sensorValue);

You just do two Serial prints:
Serial.print("POT value ");
Serial.println(sensorValue);

The .print prints without moving to a new line, the .println moves to a new line.
If you want to be more fancy and don't mind the processing and memory overhead, you can use snprintf to format the string:
char temp[15];
snprintf(temp, 15, "POT value %4d", sensorValue);
Serial.println(temp);

You can read more about sprintf and formatting here:

http://www.cplusplus.com/reference/cstdio/snprintf/ (function parameters)
http://www.cplusplus.com/reference/cstdio/printf/ (formatting options)

Note that there is no floating point support in the standard library for the Arduino - so you can't use %f etc.

Thanks Mate perfect, i have only just started on this. Thanks for your help it worked!


text:
4 Bit Counter up and down
we are asked to create an Arduino code that would run a 4 Bit Binary UP counter once a push button switch is pressed and then 4 Bit Binary Down counter on the second click. Then vice versa. This should be done using only one switch. I figured out the Count up portion but I don't know how to add the count down code for the same switch. Can someone help me with this. Thank you.
please see below for my program

int buttonState = 0;
int timer = 300;
int pin8 = 8;
int pin9 = 9;
int pin10 = 10;
int pin11 = 11;

void setup()
{
pinMode(7,INPUT);
pinMode(8,OUTPUT);
pinMode(9,OUTPUT);
pinMode(10,OUTPUT);
pinMode(11,OUTPUT);

}

void loop()
{
digitalWrite(pin8, LOW);
digitalWrite(pin9, LOW);
digitalWrite(pin10, LOW);
digitalWrite(pin11, LOW);
buttonState = digitalRead(7);

if(buttonState == HIGH)
{
digitalWrite(pin8, HIGH);
delay(timer);
digitalWrite(pin8, LOW);
delay(timer); //bit 1
digitalWrite(pin9, HIGH);
delay(timer);
digitalWrite(pin9, LOW);
delay(timer); //bit 2
digitalWrite(pin8, HIGH);
digitalWrite(pin9, HIGH);
delay(timer);
digitalWrite(pin8, LOW);
digitalWrite(pin9, LOW);
delay(timer); //bit 3
digitalWrite(pin10, HIGH);
delay(timer);
digitalWrite(pin10, LOW);
delay(timer); //bit 4
digitalWrite(pin8, HIGH);
digitalWrite(pin10, HIGH);
delay(timer);
digitalWrite(pin8, LOW);
digitalWrite(pin10, LOW);
delay(timer); //bit 5
digitalWrite(pin9, HIGH);
digitalWrite(pin10, HIGH);
delay(timer);
digitalWrite(pin9, LOW);
digitalWrite(pin10, LOW);
delay(timer); //bit 6
digitalWrite(pin8, HIGH);
digitalWrite(pin9, HIGH);
digitalWrite(pin10, HIGH);
delay(timer);
digitalWrite(pin8, LOW);
digitalWrite(pin9, LOW);
digitalWrite(pin10, LOW);
delay(timer); //bit 7
digitalWrite(pin11, HIGH);
delay(timer);
digitalWrite(pin11, LOW);
delay(timer); //bit 8
digitalWrite(pin8, HIGH);
digitalWrite(pin11, HIGH);
delay(timer);
digitalWrite(pin8, LOW);
digitalWrite(pin11, LOW);
delay(timer); //bit 9
digitalWrite(pin9, HIGH);
digitalWrite(pin11, HIGH);
delay(timer);
digitalWrite(pin9, LOW);
digitalWrite(pin11, LOW);
delay(timer); //bit 10
digitalWrite(pin8, HIGH);
digitalWrite(pin9, HIGH);
digitalWrite(pin11, HIGH);
delay(timer);
digitalWrite(pin8, LOW);
digitalWrite(pin9, LOW);
digitalWrite(pin11, LOW);
delay(timer); //bit 11
digitalWrite(pin10, HIGH);
digitalWrite(pin11, HIGH);
delay(timer);
digitalWrite(pin10, LOW);
digitalWrite(pin11, LOW);
delay(timer); //bit 12
digitalWrite(pin8, HIGH);
digitalWrite(pin10, HIGH);
digitalWrite(pin11, HIGH);
delay(timer);
digitalWrite(pin8, LOW);
digitalWrite(pin10, LOW);
digitalWrite(pin11, LOW);
delay(timer); //bit 13
digitalWrite(pin9, HIGH);
digitalWrite(pin10, HIGH);
digitalWrite(pin11, HIGH);
delay(timer);
digitalWrite(pin9, LOW);
digitalWrite(pin10, LOW);
digitalWrite(pin11, LOW);
delay(timer); //bit 14
digitalWrite(pin8, HIGH);
digitalWrite(pin9, HIGH);
digitalWrite(pin10, HIGH);
digitalWrite(pin11, HIGH);
delay(timer);
digitalWrite(pin9, LOW);
digitalWrite(pin9, LOW);
digitalWrite(pin10, LOW);
digitalWrite(pin11, LOW);
delay(timer); //bit 15
}
}

why don't you just count a variable from 0 to 0x0F and decide the four bits into the LED outputs? ... the code would be simple and not repetitive

if(buttonState == HIGH)  means "as long as the button is pressed". You probably want to use a flag that changes, when the button is clicked.

Currently you are just setting the LEDs manually one after another in your code. That is not actually a binary counter (as it is most likely wanted by the exercise), but only looks like one.
First you need to understand, what a counter really is: Basically it is just a variable, that holds a number. Where exactly this variable is saved, is not important. For your case you would use a variable in your code. The Counter/Timer hardware in the Arduino uses a fixed SFR (Special Function Register) for it.
That the counter is 4bit, means, that its value is hold by only 4 bits. That gives you a value range from 0 to 15 (2^4 values). So a 4bit counter variable would count from 0 to 15. You could just have a counter variable, that you could increment or decrement (depending on the direction, that you want to count).
// Declare counter variable and initialize with zero
int counter_variable = 0;
// Increment
counter_variable++;
// or Decrement
counter_variable--;

For the "binary" part: Here it is important to understand, that the decimal number from 0 to 15 is already saved in the variable as binary (since microcontrollers/computers only know binary, nothing else). So you can write out the state of the 4 least significant bytes of the counter variable:
digitalWrite(pin8  ,counter_variable & 0b0001);
digitalWrite(pin9  ,counter_variable & 0b0010);
digitalWrite(pin10 ,counter_variable & 0b0100);
digitalWrite(pin11 ,counter_variable & 0b1000);

The & is a bitwise AND. The result of the operation will only leave bits set, when they are set on both sides. So here we are isolating the corresponding bits. digitalWrite() will interpret anything but zero as HIGH. Thus the pin is set HIGH, if the corresponding bit is set in counter_variable. But you see, that we are repeating us here. We could use a for loop and define our pins in an array:
// at global scope
int led_pins[4] = {8, 9, 10, 11};

// in the button if statement
for(int i=0; i<4; i++){
    digitalWrite(led_pins[i], counter_variable & (1 << i));
}

We have organized the pins of the LEDs in an array, so they can be easily indexed. Then we are looping through the pins array and setting the pins similar to the last version. But now we are using (1 << i). The << operator shifts the bits of the number before it by the number of digits, that comes after it. Decimal 1 is binary 0b0001. So, when i is 2 (for example), this would shift the bits 2 digits to the left, giving you 0b0100. We are just generating the same bit patterns as in the last version.
But we can even optimize further via direct port manipulation. Inside the microcontroller the output pins are controlled via simple Special Function Registers. They work somewhat like a variable. All output pins are organized into socalled "Ports" (groups of up to 8 pins). Each port has one PORTx registers (where x stands for the character associated with that port), which sets the state of the pins, if they are in output mode. Setting the corresponding bit in the correct PORTx register will set the pin to HIGH. Clearing the bit (setting to zero) will set the pin to LOW.
You are using the Arduino pins 8 to 11. If you look at a pinout diagram of the Arduino Uno, you will see, that these pins are also marked as PB0 to PB3, which stands for "Port B, pins 0 to 3 (inside that port)". The corresponding PORTx register is PORTB. So we can set all pins of the port at once by assigning a new value to that register. The following code would set an alternating on/off pattern for all 8 pins of PORTB:
PORTB = 0b10101010;

Now we only want to use the lowest 4 bits and set them to the values, that our counter variable has. So we are masking away the 4 higher bits with the bitwise AND operator and then assign that value to the register:
PORTB = counter_variable & 0b00001111;

So now the if statement in void loop() might look like this (using a for loop):
if(buttonState == HIGH){
    // count up counter variable
    for(int counter_variable=0; counter_variable < 16; counter_variable++){
        // write out to the pins
        PORTB = counter_variable & 0b00001111;
        // delay a bit to show the value
        delay(timer);
    }
}

And now we want that each consecutive button to count in the other direction than before. So we can declare another variable as direction and then use another if statement, to switch between two for loops:
// On global scope
int direction = 1;

// in void loop()

if(buttonState == HIGH){
    if(direction == 1){
        // count up counter variable
        for(int counter_variable=0; counter_variable < 16; counter_variable++){
            // write out to the pins
            PORTB = counter_variable & 0b00001111;
            // delay a bit to show the value
            delay(timer);
        }
        // change direction
        direction = -1;
    } else {
        // count up counter variable
        for(int counter_variable=15; counter_variable >= 0; counter_variable--){
            // write out to the pins
            PORTB = counter_variable & 0b00001111;
            // delay a bit to show the value
            delay(timer);
        }
        // change direction
        direction = 1;
    }
}

Note:

This is probably not the most efficient way, but I think it is quite understandable (which is also important).
This still uses much delay() calls, just as your code. That will make your button unresponsive. The counter must first finish, before the button will react again. That might be ok for you. If not, you need to restructure the program for using a non-blocking coding style like in the BlinkWithoutDelay example from the Arduino IDE (using millis()). There are lots of tutorials about that on the web.
When using a non-blocking coding style, you also need to check the button for the transition to HIGH, instead for the state high. Otherwise the code would run only, while the button is pressed.
Buttons bounce, when being pressed. So there are many transitions between HIGH and LOW for a few ms, when the button is pressed. In the code above this is not important, because the started counter needs so long, that every bounce is finished after the counter finished. With code, that needs less than a few ms, you might get into problems there. I would suggest the Bounce2 library for that. It handles the bounce detection for you.


text:
Bluetooth module not working
I was following a tutorial on YouTube to build a Bluetooth car with Arduino.
#include <AFMotor.h>

//initial motors pin
AF_DCMotor motor1(1, MOTOR12_1KHZ);
AF_DCMotor motor4(4, MOTOR34_1KHZ);

char command;

void setup()
{
  Serial.begin(9600);  //Set the baud rate to your Bluetooth module.
}

void loop(){
  if(Serial.available() > 0){
    command = Serial.read();
    stop(); //initialize with motors stoped
    //Change pin mode only if new command is different from previous.
    //Serial.println(command);
    switch(command){
    case 'F':
      forward();
      break;
    case 'B':
       back();
      break;
    case 'L':
      left();
      break;
    case 'R':
      right();
      break;
    case 'S':
      stop();
      break;
    }
  }
}

void forward()
{
  motor1.setSpeed(255); //Define maximum velocity
  motor1.run(FORWARD); //rotate the motor clockwise
  motor4.setSpeed(255);//Define maximum velocity
  motor4.run(FORWARD); //rotate the motor clockwise
}

void back()
{
  motor1.setSpeed(255); //Define maximum velocity
  motor1.run(BACKWARD); //rotate the motor anti-clockwise
  motor4.setSpeed(255); //Define maximum velocity
  motor4.run(BACKWARD); //rotate the motor anti-clockwise
}

void left()
{
  motor1.setSpeed(255); //Define maximum velocity
  motor1.run(BACKWARD); //rotate the motor anti-clockwise
  motor4.setSpeed(255); //Define maximum velocity
  motor4.run(FORWARD);  //rotate the motor clockwise
}

void right()
{
  motor1.setSpeed(255); //Define maximum velocity
  motor1.run(FORWARD); //rotate the motor clockwiseclockwise
  motor4.setSpeed(255); //Define maximum velocity
  motor4.run(BACKWARD); //rotate the motor anti-clockwise
}

void stop()
{
  motor1.setSpeed(0); //Define minimum velocity
  motor1.run(RELEASE); //stop the motor when release the buttonbutton
  motor4.setSpeed(0); //Define minimum velocity
  motor4.run(RELEASE); //stop the motor when release the button
}

Here's the schematic:

I didn't use the resistor, I used 4 aa batteries, and I used 2 motors instead of 4, but the bluetooth module is flashing.

Please include the image directly into your question.

Could you establish the bluetooth connection to the HC-05 on your smartphone? Did you configure the module to use 9600 baud for the serial connection?

ok i will one second

@chrisl i don't understand, but yes i established the bluetooth connection to the hc05 on my smartphone but i don't understand the second part

The HC-05 is a bluetooth-Serial bridge. The pins going to TX and RX of the Arduino are for the Serial (UART) communication interface. For using that interface, both devices need to be configured to the same baudrate/speed. In your sketch you are using 9600 baud. But often the HC-05 modules are configured for something like 38400 baud by default. So have you made sure, that you are using the same baudrate in your code as the HC-05 uses?

yes i set the serial.begin to 38400

but it is still not working

I didn't use the resistor...  so ... you wired the bluetooth module direct to the Arduino with no logic level translation?

no i used the arduinon driver board

and the hc05 module has a 3.3v regulator

@powerdido2007 Most HC-05 modules only have a 3.3V regulator for the power lines. They don't translate the data lines. Thus the 5V from the Arduino at the HC-05s RX line can damage it

so what should i do

generally with the HC-05 it isn't plug&play. Please google for some tutorials about it and try them first. It can be rather complex, so that answering here for all possible problems is too much.


text:
Arduino Nano 3.0 CH340G clone cannot upload sketch from Arduino IDE
I connected my brand new Arduino Nano 3.0 clone with CH340G and installed the drivers. It detects in Device Manager as USB-SERIAL CH340 (COM6). Under the Tools menu, i selected the correct board, the processor set to ATmega328P and the COM port. I couldn't upload my sketch so i tried uploading an example Blink sketch from Arduino IDE. The uploading is stuck. I keep waiting and nothing happens. I have read somewhere else that i should enable verbose output for compilation and upload, which i did and here is the output for trying to upload the basic Blink sketch.
Arduino: 1.8.9 (Windows 7), Board: "Arduino Nano, ATmega328P"

C:\Program Files (x86)\Arduino\arduino-builder -dump-prefs -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -hardware C:\Users\admin\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -tools C:\Users\admin\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\admin\Documents\Arduino\libraries -fqbn=arduino:avr:nano:cpu=atmega328 -vid-pid=1A86_7523 -ide-version=10809 -build-path C:\Users\admin\AppData\Local\Temp\arduino_build_747566 -warnings=none -build-cache C:\Users\admin\AppData\Local\Temp\arduino_cache_890158 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=C:\Users\admin\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\5.4.0-atmel3.6.1-arduino2 -prefs=runtime.tools.avr-gcc-5.4.0-atmel3.6.1-arduino2.path=C:\Users\admin\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\5.4.0-atmel3.6.1-arduino2 -prefs=runtime.tools.avrdude.path=C:\Users\admin\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino14 -prefs=runtime.tools.avrdude-6.3.0-arduino14.path=C:\Users\admin\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino14 -prefs=runtime.tools.arduinoOTA.path=C:\Users\admin\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.2.1 -prefs=runtime.tools.arduinoOTA-1.2.1.path=C:\Users\admin\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.2.1 -verbose C:\Program Files (x86)\Arduino\examples\01.Basics\Blink\Blink.ino
C:\Program Files (x86)\Arduino\arduino-builder -compile -logger=machine -hardware C:\Program Files (x86)\Arduino\hardware -hardware C:\Users\admin\AppData\Local\Arduino15\packages -tools C:\Program Files (x86)\Arduino\tools-builder -tools C:\Program Files (x86)\Arduino\hardware\tools\avr -tools C:\Users\admin\AppData\Local\Arduino15\packages -built-in-libraries C:\Program Files (x86)\Arduino\libraries -libraries C:\Users\admin\Documents\Arduino\libraries -fqbn=arduino:avr:nano:cpu=atmega328 -vid-pid=1A86_7523 -ide-version=10809 -build-path C:\Users\admin\AppData\Local\Temp\arduino_build_747566 -warnings=none -build-cache C:\Users\admin\AppData\Local\Temp\arduino_cache_890158 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.avr-gcc.path=C:\Users\admin\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\5.4.0-atmel3.6.1-arduino2 -prefs=runtime.tools.avr-gcc-5.4.0-atmel3.6.1-arduino2.path=C:\Users\admin\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\5.4.0-atmel3.6.1-arduino2 -prefs=runtime.tools.avrdude.path=C:\Users\admin\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino14 -prefs=runtime.tools.avrdude-6.3.0-arduino14.path=C:\Users\admin\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino14 -prefs=runtime.tools.arduinoOTA.path=C:\Users\admin\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.2.1 -prefs=runtime.tools.arduinoOTA-1.2.1.path=C:\Users\admin\AppData\Local\Arduino15\packages\arduino\tools\arduinoOTA\1.2.1 -verbose C:\Program Files (x86)\Arduino\examples\01.Basics\Blink\Blink.ino
Using board 'nano' from platform in folder: C:\Program Files (x86)\Arduino\hardware\arduino\avr
Using core 'arduino' from platform in folder: C:\Program Files (x86)\Arduino\hardware\arduino\avr
Detecting libraries used...
"C:\\Users\\admin\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\5.4.0-atmel3.6.1-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\variants\\eightanaloginputs" "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_747566\\sketch\\Blink.ino.cpp" -o nul
Generating function prototypes...
"C:\\Users\\admin\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\5.4.0-atmel3.6.1-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\variants\\eightanaloginputs" "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_747566\\sketch\\Blink.ino.cpp" -o "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_747566\\preproc\\ctags_target_for_gcc_minus_e.cpp"
"C:\\Program Files (x86)\\Arduino\\tools-builder\\ctags\\5.8-arduino11/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_747566\\preproc\\ctags_target_for_gcc_minus_e.cpp"
Compiling sketch...
"C:\\Users\\admin\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\5.4.0-atmel3.6.1-arduino2/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_NANO -DARDUINO_ARCH_AVR "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\variants\\eightanaloginputs" "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_747566\\sketch\\Blink.ino.cpp" -o "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_747566\\sketch\\Blink.ino.cpp.o"
Compiling libraries...
Compiling core...
Using precompiled core: C:\Users\admin\AppData\Local\Temp\arduino_cache_890158\core\core_arduino_avr_nano_cpu_atmega328_0c812875ac70eb4a9b385d8fb077f54c.a
Linking everything together...
"C:\\Users\\admin\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\5.4.0-atmel3.6.1-arduino2/bin/avr-gcc" -w -Os -g -flto -fuse-linker-plugin -Wl,--gc-sections -mmcu=atmega328p -o "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_747566/Blink.ino.elf" "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_747566\\sketch\\Blink.ino.cpp.o" "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_747566/..\\arduino_cache_890158\\core\\core_arduino_avr_nano_cpu_atmega328_0c812875ac70eb4a9b385d8fb077f54c.a" "-LC:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_747566" -lm
"C:\\Users\\admin\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\5.4.0-atmel3.6.1-arduino2/bin/avr-objcopy" -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_747566/Blink.ino.elf" "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_747566/Blink.ino.eep"
"C:\\Users\\admin\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\5.4.0-atmel3.6.1-arduino2/bin/avr-objcopy" -O ihex -R .eeprom "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_747566/Blink.ino.elf" "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_747566/Blink.ino.hex"
"C:\\Users\\admin\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\5.4.0-atmel3.6.1-arduino2/bin/avr-size" -A "C:\\Users\\admin\\AppData\\Local\\Temp\\arduino_build_747566/Blink.ino.elf"
Sketch uses 930 bytes (3%) of program storage space. Maximum is 30720 bytes.
Global variables use 9 bytes (0%) of dynamic memory, leaving 2039 bytes for local variables. Maximum is 2048 bytes.
C:\Users\admin\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino14/bin/avrdude -CC:\Users\admin\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino14/etc/avrdude.conf -v -patmega328p -carduino -PCOM6 -b115200 -D -Uflash:w:C:\Users\admin\AppData\Local\Temp\arduino_build_747566/Blink.ino.hex:i
An error occurred while uploading the sketch

avrdude: Version 6.3-20171130
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Users\admin\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino14/etc/avrdude.conf"

         Using Port                    : COM6
         Using Programmer              : arduino
         Overriding Baud Rate          : 115200
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0xd8
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0xd8
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0xd8
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0xd8
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0xd8
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0xd8
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0xd8
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0xd8
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0xd8
avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0xd8

avrdude done.  Thank you.

Problem uploading to board.  See http://www.arduino.cc/en/Guide/Troubleshooting#upload for suggestions.

I have had cheap nano clones come from China without a bootloader installed. Try reinstalling the bootloader.

I searched and found that i would need a working Arduino Nano in order to transfer its working bootloader onto the non-working one. Is it possible to do it if i don't have another Arduino Nano?

Get yourself a USBASP off eBay/AliExpress/Amazon.

select "Old bootloader" in Tools menu

I followed these guides and i got it to work: https://www.instructables.com/id/How-To-Burn-a-Bootloader-to-Clone-Arduino-Nano-30/ and https://www.arduino.cc/en/tutorial/arduinoISP#toc2

so you burned the "new" bootloader

Yes, i assumed that the new bootloader is better and also that's what was recommended in the tutorial. What are the reasons for using or preferring the old bootloader?

if you can't burn the 'new' :-). The 'new' bootloader is the bootloader of Uno (so not really new). It is Arduino version of Optiboot 4. Really new is Optiboot 8.

OK, but i'm wondering what difference does it make? Does the 'old' bootloader enable faster compiling/upload/execution? Or does it make the board less power hungry??

https://arduino.stackexchange.com/questions/51866/arduino-nano-atmega328p-bootloader-difference/51874#51874

You normally just have to press 'reset' on the board button 1 sec before clicking 'Upload'.
I had to do this with cheap Nano clone.

MCU on Nano doesn't have native USB and has a different bootloader.


text:
Why is my relay not triggering?
I have a 4 channel relay for my Arduino. Here's an image:

From what I can tell, it's rated for 5V direct current because of the big 05VDC at the bottom, but please tell me if I'm wrong? If I'm wrong, then that's the problem here.
I've tested out an LED on 5V DC to work and connected it to output side of the relay.
I've connected my Arduino to the input, programmed with the following code:
const int RELAY_PIN = 3;

void setup() {
  pinMode(RELAY_PIN, OUTPUT);
  Serial.begin(96000);

}

void loop() {
  Serial.println("Relay ON");
  digitalWrite(RELAY_PIN, LOW);
  delay(1000);

  Serial.println("Relay OFF");
  digitalWrite(RELAY_PIN, HIGH);
  delay(1000);
}

I can confirm that the corresponding LED on the relay for channel 4 does blink for 1 second and stay off for 1 second, which I'm expecting it's meant to do. I've never worked with an Arduino or a relay before.
However, the 5V DC LED on the other end never lights up. Why is my relay not switching on?
Edit: About the LED circuit. It is on and fully powered. If I bypass the relay and join the two wires, the LED lights up. If I plug the two wires into the relay, the LED never lights up.
Edit2: About the jumper: I have a secondary 5V power supply connected to the VCC for what I'm told is isolation. I've read a little on the matter, but am not fully aware of how it works.
Edit 3:
Connections
I have the following connections:

Output 3 (Arduino) to Input 4 (Relay)
5V (Arduino) to Input VCC (Relay) [The one next to the input pins]
Power supply positive/ground to GND (Relay)
Power supply negative/live to VCC (the one next to the JD-VCC)

This did not work. What did work was the following configuration:

Output 3 (Arduino) to Input 4 (Relay)
5V (Arduino) to Input VCC (Relay) [The one next to the input pins]
Jumper across VCC and JD-VCC on the Relay

Guessing (with out a schematic), you didn't add a power source to the relay to LED circuit?   I don't see any wires on that side of the board.  So I am not sure where the LED that is not lighting up is located.  Let me know here in a follow up comment and I'll post an appropriate answer you can accept so others who find your question with a similar problem will have an appropriate answer.

@st2000 I did. Sorry, I'm not a hardware person so I don't even know how to make a schematic. But let me edit the question.

oh, I see the problem.  You are missing the jumper on JD-VCC.  So, instead of a jumper - there is a blue wire - where is the blue wire going?

@st2000 secondary 5V power supply connected to VCC :) sorry, editing the question.

So, if the secondary power supply is 5V, then your setup will probably work if you move it to the other side of the pair of pins.  Also, you will need to connect the grounds of the 2 power supplies together.  See the schematic in my answer below.  But I think most people just put a jumper across J5 or JD

Note that driving your relay off of the 5V from your Arduino is a bad idea. If memory serves those relays draw about ≈200mA - 250mA per relay, so you could drive maybe 2 of them at the same time, but if you try to drive 3, you'll exceed the 500mA max output you should draw from the Arduino. If you're powering it from USB, it will trip the internal fuse and shut off. If you're running it from the barrel connector, you might get away with it, or you might overheat the Arduino's voltage regulator, depending on various factors. you should really drive your relay with a separate power supply.

Thanks @DuncanC, that's what I'm trying to do.

"Power supply negative/live to VCC (the one next to the JD-VCC)" the secondary power supply should power the relays over JD-VCC

From the image in the question, the jumper across pins J5 (in the
below schematic) or JD as on the silk screen on the PBC is missing.

Using the above schematic, a choice to power the Ardino and the relays off of one 5V power supply can be made.  This appears to be done by connecting the 5V to the VCC pin, Ground to the GND pin & placing a jumper across J5.  However, it appears that the relays can be isolated from the Arduino if desired.  This appears to be done by connecting the Arduino's 5V to pin 2 of J5.  That should be enough to light up the LED indicator and therefor the optical isolator when the Arduino's output to IN1, 2, 3 or 4 is low.  Then, connect the 2nd power source 5V to pin 1 of J5 and the ground from the 2nd power source to pin GND.  This last step should provide the power to close the relays when the Arduino takes IN1, 2, 3 or 4 low.
Lastly, make sure the polarity of the 2nd power supply (if one is used) is correct.  The output side of the optical coupler and the transistor driving the relay only work when the current is passing in the proper direction. Not to mention, the reverse bias flyback diode (D1, 2, 3 & 4) would short out the power supply if connected in the reverse direction.  However, this catastrophe is avoided here as the transistors (Q1, 2, 3 & 4) would not pass current in the reversed direction.

Hi, your suggestion to join the grounds and move the pin to the other side did not work. However, something else did, please see Edit 4 for the configuration that did. However, the Arduino is no longer isolated, what do you suggest?

(I only see an Edit 3.)  The option to drive the relays from a different power source than the Arduino is not necessary.  Especially if you are using a good 5V power supply with plenty of current capability.  What is important is the isolation the relays provide from what ever you are planning on connecting to the relay contacts.  If you want, you can continue using 2 independent power supplies.  Actually, looking at the schematic I found, you don't need to connect the grounds together (my bad).  I'll amend my question as I'm running out of room here in this comment.

The error was so dumb, I don't want to admit it. I had the external power supply connected in reverse because "negative ground" did not make sense to me. But I would never have caught it if not for your diagram.
Could you please add a suggestion to ensure that the connections are correct, and I'll mark yours as accepted? Thank you for your help.

Ah, good to know you've got it working.  And that you understand it. I'll see if I can add something.

A relay is an electromagnet-driven switch. It opens and closes that switch, but doesn't provide power.
Assuming it's like my relays, that relay can either power the relay coils AND the logic inputs, or (if you remove the jumper) use separate power for the relay coils and the logic signals.
Since you've removed the jumper, you need to provide 2 different 5V power sources to drive the relay - one high-current supply to the VCC, which runs the logic circuits and the relay coil. Another to the logic power in. Then you ground the input pin to activate one of the relay channels.
Finally, you need to wire the screw terminals on the left side into a circuit with separate power that controls something. For an LED, you'd need power, the LED, and a current-limiting resistor wired in series with the screw terminals on LED channel 1.
For an LED this is serious overkill. You could drive the LED directly (with a current limiting resistor) from the Arduino logic signal.

Hi Duncan, I have a secondary power supply on the VCC, and this setup is a test setup to learn how Arduinos and relays work. I plan on connecting replacing the LED with something higher powered later on.

In your picture you don't have anything connected to the switched side of the relay (the screw terminals on the left side.)

Yes, when I snapped the photo, I was testing the LED circuit to ensure it was working properly so I took them off. The LED circuit works fine and is inserted properly. I've managed to make the relay finally work with the jumper on. Please see Edit 3.

So who down-voted my answer, and why? It's fine if you think my answer is lacking, but please explain.

Have an upvote on me, since I think it's good. :)


text:
Reading Buffer from Software-Serial & Writing to Serial
My progress so far:
#include <SoftwareSerial.h>

SoftwareSerial ttySerial(10, 11); // RX, TX
byte buffer;

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Native USB only
  }

  Serial.println("Serial Initialized");

  //Set the data rate for the SoftwareSerial port
  ttySerial.begin(115200);
  ttySerial.println("tty Initialized");
}

void loop()
{
  ttySerial.listen();
  while (ttySerial.available())
    //byte buffer = ttySerial.read();
    //Serial.write(buffer);
    Serial.write(ttySerial.read());

//    if (Serial.available())
//      ttySerial.write(Serial.read());
}

I am really confused because if I write the data as the as the buffer I have defined, the serial monitor goes crazy. If I upload the code as shown, I don't get anything weird in the monitor but the behavior is not what I expect.
I am writing to the software-serial on RX10 & TX11 (from javascript) the following data:
Buffer.from([0, 0, 4, 0, 0, 0, 0, 0]) (keystroke "a")
The Buffer.from method comes from node using the serialport npm module. (This is basically irrelevant since sending the data from Buffer.from('test') works and is output to the monitor.
As you can see, the buffer is 1 byte (the array forming the 8 bits). Why is the buffer not read as "a" in the monitor? Is it because the Micro has an abstract HID report descriptor (see below)?
Additionally, what does Serial.write(...) represent? I.e. when I close the Arduino IDE serial monitor, will my Arduino Micro automatically assume its HID function and write the data as an HID device? S
I know there are already keyboard and mouse HID libraries but I already have code that generates the raw HID data that I would prefer to utilize. Note that the buffer described above comes from the HID report descriptor for a generic keyboard i.e. the "4" is not merely the ASCII code for "a". Explained Here Maybe I can use https://www.arduino.cc/en/Reference/HID ?
Thanks in advance!
EDIT 1:
This is the output I see from the code as shown (without the monitor "going crazy")
19:51:03.017 -> Serial Initialized
19:51:13.932 -> //Where I was hoping to see "a"

EDIT 2: I found the report descriptor in Keyboard.cpp:
  //  Keyboard
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)  // 47
    0x09, 0x06,                    // USAGE (Keyboard)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x85, 0x02,                    //   REPORT_ID (2)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)

  0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)
    0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //   REPORT_SIZE (1)

  0x95, 0x08,                    //   REPORT_COUNT (8)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0x95, 0x01,                    //   REPORT_COUNT (1)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x81, 0x03,                    //   INPUT (Cnst,Var,Abs)

  0x95, 0x06,                    //   REPORT_COUNT (6)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x73,                    //   LOGICAL_MAXIMUM (115)
    0x05, 0x07,                    //   USAGE_PAGE (Keyboard)

  0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))
    0x29, 0x73,                    //   USAGE_MAXIMUM (Keyboard Application)
    0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
    0xc0,                          // END_COLLECTION

I will need to compare this to the data I would be sending to Keyboard.write()

you have not said what problems you are experiencing ... serial monitor goes crazy and behavior is not what I expect are both meaningless

please refer to this https://www.arduino.cc/en/Tutorial/SoftwareSerialExample

@jsotola
serial monitor goes crazy - the monitor receives a ton of output that is coming so fast I can't actually see what it is saying and its continuous scrolling wont let me narrow it down.
behavior is not what I expect - If I turn the timestamp on I can see that data was received but it is nothing visible let alone the "a" I was hoping for

@jsotola Thanks but that is the example I used to come up with what you see above. In a sense, the software-serial works fine - it is the reading/writing I am struggling with

use a lower baud rate and you may be able to see what is flying by ... turning off the auto-scroll may also help .... otherwise, use an external serial monitor, such as putty and turn on file capture

@jsotola it looks like it is just saying "Serial Initialized" a bunch of times - yup can confirm: 19:58:43.472 -> Serial Initialized 19:58:43.555 ->  is the continuous output

Don't use listen() this way. It clears the receive buffer. You loose the data received before listen() call.
You have only one SoftwareSerial instance so you don't need to call listen(). The listen() function clears the receive buffer because there is only one buffer for all SoftwareSerial instances.

This did not solve my issue. I will post my output in an edit

I am thinking that the Serial is not sure how to parse the input buffer. I thought that it might work for a Keyboard.write(<buffer>) method since the report descriptor in Keyboard.cpp might know how to parser the buffer input - but to no avail. This was part of reason for the question "what does Serial.write(...) represent?...

Perhaps HID.SendReport(uint8_t id, const void* data, int len) might work but idk what id, data, or len would be exactly in this context... maybe id is the buffer and len is 8 but what would data be?

@SterlingButters, your code in Question doesn't initialize and use HID, so there is no HID in play and sure not over SoftwareSerial

but you think that if I initialized the HID, that buffer might work? Could you also speak to what id, data, and len might be in this case?

what buffer?. SoftwareSerial and HID have nothing to do one with other.

As I understand it, I am using Software Serial to collect the buffer I am transmitting to pin 10 (from js). Then I would like to write the buffer using some HID emulation library. My question is, with the buffer I have defined above, would this work and how would I specify the arguments to HID.SendReport(...)?

if you want to sent keyboard keys, use the Keyboard library. see the examples of the library.

Let us continue this discussion in chat.