message:
Pulling the enable pin on Adafruit PowerBoost to low (It's connected to VBatt!)

I am working on an Tonuino (tonuino.voss.earth), and I am using a PowerBoost-module from Adafruit (https://www.adafruit.com/product/1944) for it. The powerboost-module needs the enable pin driven to LOW(GND) to turn the output 5V off. Currently I have a rocker switch which allows me to permananently connect EN to GND.

I would like to implement a auto-off functionality for this combination, i.e. the arduino can drive the enable pin LOW and in this manner kill its own power. In addition to the auto-off, I want the user to be able to turn on the device via a button press. I come from a software background and my last connection to electronics is from a time long, long ago, which is why I am struggeling.

This shows my initial thoughts:
[![enter image description here][1]][1]

1. The user presses the button to start the Tonuino. The switch disconnects EN from GND, EN goes to UBATT(HIGH) and 5V to the arduino is enabled. By enabling the arduino, a GPIO is set to high and thus EN is maintained high
2. To turn off, the arduino sets the GPIO to LOW, thus setting EN to LOW, 5V are disabled and so forth...

My problem: 5V from the Arduino GPIO will always be at 5V and thus higher than the reference voltage of EN (UBATT 3V - 3.7V). I really am afraid that this will damage my lipo. For me this means, I ideally should switch UBATT for EN (safely) and am failing to come up with a solution.

Any pointers are greatly welcome

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

body:
Your biggest problem is that the module defaults to on. There is a 340kΩ resistor pulling the EN pin up to VBAT all the time, so to turn it off you have to actively override that pullup.

Ideally you would modify the module by removing that resistor (R13) and adding your own resistor between the ENABLE and GND pins. You can the override that with both a button and a P-channel FET in parallel to turn the module on.

For example:

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

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

<!-- End schematic -->

Now normally R1 pulls ENABLE to ground turning the module off.  You press SW1 and it pulls ENABLE up to VBAT and turns it on.  5V then gets supplied to the Arduino, at which point you need to set the GPIO to output and pull it HIGH.

This causes the gate of M2 to be pulled above its threshold voltage (make sure it has a threshold voltage between 0V and 3V) and it starts to conduct pulling the gate of M1 below its threshold voltage (must be between 0V and -2V) bypassing switch SW1 keeping the system enabled.

You can now let go of SW1 and it will all stay powered on until you either set the GPIO LOW or set it to an INPUT.

Note that resetting the Arduino (for programming, for example) would cause the boost module to shut down and require re-powering with SW1 (or through the GPIO if you have the Arduino powered through USB for programming of course).

However if you don't want to or can't modify the module then things get a little nastier.

To make it default to OFF R1 in the above schematic will have to be low enough value that the voltage presented at the ENABLE pin is below 20% of the battery voltage.  R1 and the existing 340kΩ pullup resistor form a voltage divider, so you need to calculate the size of resistor that will allow it to be below 20% VBAT.

Since a voltage divider just gives you a proportion of the input voltage whose ratio is the ratio of the "top" resistance in the divider to the total resistance we don't care what the voltage is, only the ratio.  And we don't really care about the exact value, only that the result is *below* 20%.  So we can pick a good common value.

However we don't want a value that is too low, because the voltage divider will be draining power from the battery all the time, so the higher the resistances the less the power drain will be.

For example if we pick the common value 47kΩ we see that:

        R2           47000
     ------- = --------------- = 0.11 (11%)
     R1 + R2    340000 + 47000

Which is below the 0.2 (20%) that we want, which is good.  Calculating the current at a typical battery voltage of 3.7V we get

         V          3.7
    I = --- = -------------- = 0.000010 (10µA)
         R    340000 + 47000

10µA is not much, on the scale of things, but it's good to know about it when you're working from a battery since it will form part of your power budget calculations.


sender: user

message:
How do you make a Class variable array bigger?

I am making an infrared macro-keyboard, I want to store Unicode for the Keyboard class in an array inside a class I made called `Keybind`and to allow the user to program as many outputs as they want, I want the storage to be mutable.  I currently use the String class and decode within the program but it's cpu intensive and not very practical.
I want to use an array or list, but I haven't found any way to expand the size of an array inside a class.  Casting a temporary array didn't work:

      int intArray[] = {0,1,2,3,4,5};
      int* temp[7];

      for(int x = 0; x<sizeof(intArray)/sizeof(intArray[0]); x++){
        temp[x] = intArray[x];
      }
      temp[6] = 6;
      intArray = temp;

IDE spits out "`incompatible types in assignment of 'int* [7]' to 'int [6]'`"

sender: assistant

body:
> I want to [...] allow the user to program as many outputs as they want

This may be problematic. The microcontroller has a limited amount of
RAM: it will not be able to store arbitrarily long macros. You should
consider a way of telling the user “sorry, no more memory”. Or you can
be optimistic and assume the user will never try to record macros long
enough to exhaust the memory... and let the firmware crash if this
assumption turns out to be invalid.

> I currently use the String class and decode within the program but
> it's cpu intensive and not very practical.

CPU intensive? You mean the allocation? Reading the contents of a String
object is not CPU intensive. And what do you find impractical in the
String class? At it's core, it's just a dynamically sized container for
character data, which seems to be exactly what you are looking for.

> I haven't found any way to expand the size of an array inside a class.

A class is a data structure of _fixed size_. There is no way you can
expand its contents. If you need something of variable size, you will
have to use dynamic allocation. You will then only store a _pointer_ to
the allocated memory in your class. This is exactly what `String` does.
The only other option is to store an array of fixed size within the
class, and make that size large enough so that you never need more.


message:
Trying to switch a 5v fan with a LiPo and can't figure our what's wrong at full duty cycle

I have a simple project where I want to turn a 5v fan on/off and both the MCU  and fan will powered by a LiPo battery.

I'm powering the ESP and fan directly from the battery in the attached circuit. For now I've decided not to boost the power to 5v for the fan because the fan runs fine at lower voltage. Also using a BJT transistor as a low side switch.

This all seems to work fine except at full duty cycle the voltage to the fan seems to completely collapse. At just below full (like if a do analogWrite(pin 1000) it's humming along fine but when I go to 1023 the voltage drops from around 4 to closer to 2 and the fan stops. Even at lower duty cycles like 50% the fan operates nice and slow.

I put a multimeter on the leads to the fan and observe the voltage drop at full duty.

I'm very new to all this and have done a lot of reading but I haven't been able to solve this. Also this is my first fritzing drawing so I hope it makes sense.

Edit: I made some changes to the circuit and it's working as expected. I have also updated the circuit diagram below.

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

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

body:
According to specs I found online, the NodeMCU wants 7-12V on Vin. Most LiPo cells put out around 4 volts, which isn't enough. The battery voltage may drop and the MCU's voltage regulator probably fails to keep putting out 3.3V when the fan's average power draw exceeds some threshold.

It might also be that the fan itself is slowing when the duty cycle approaches 100% and the battery voltage drops.

Doesn't the NodeMCU run on 3.3V, not 5V? If you feed 5V into the 3V pin and that's supposed to have 3.3V, it will likely damage or destroy the board.


message:
Arduino expected ':' before '{' token

I wanted to compile a project yesterday which always worked until now. Probably since an adjustment of the libraries (update) I have not been able to do this anymore. I ask for help.

ERRORMESSAGE:
exit status 1
expected ':' before '{' token

Line from Error

    #define MSG_PRINT(...) { MSG_PRINTER.print(__VA_ARGS__); }

body:
`MSG_PRINT` is a macro.  It gets replaced in your code verbatim *before* compilation.

The error message will give you more information. Specifically it will tell you *where* the error is. For example:

```
/tmp/untitled1/untitled1.ino: In function 'void loop()':
/tmp/untitled1/untitled1.ino:1:24: error: expected ':' before '{' token
/tmp/untitled1/untitled1.ino:12:13: note: in expansion of macro 'MSG_PRINT'
```

Here I have defined `MSG_PRINT` at line 1, which is where it "says" the error is. However that's only where the macro is. The actual error is at line 12, where the error says the macro is being expanded. That's the *last* line in the error message.

The little bit of code I used to trigger that error is actually a `switch` command where I deliberately omitted the `:` at the end of a case statement:

```
    switch (v) {
        case 3 // <---- missing colon here
            MSG_PRINT("foo");
            break;
    }
```

If we replace `MSG_PRINT` as the preprocessor would we end up with:

```
    switch (v) {
        case 3
            { Serial.println("foo"); }
            break;
    }
```

(I defined `MSG_PRINT` to just call `Serial.println`...) and now we can better see the context of the error.

With the expansion now in place it is obvious that there is indeed a `:` missing before a `{`, even though that `{` isn't immediately visible in your code.

Learning to interpret these sometimes cryptic error messages is key to working with C and C++.


message:
Int64_t aka long long acts as int32_t and overflows at 2^31

I have an `int64_t` variable. When I add another `int64_t` variable

 and convert it to a double to print it on the serial monitor, it acts as if it was a `int32_t` variable. This is the program:

```c++
int64_t a = 1 << 31;
double b = static_cast<double>(a);
Serial.println(b);
```

The output on the serial monitor is `-2147483648.00`.

What is going on?

body:
`1 << 31` is interpreted by the compiler as `(int)1 << (int)32`.
See [the implicit types of integer literals][type]. The
rules of usual arithmetic conversions state that no implicit conversion
is performed in this case. The result is then computed as an `int`, and
it overflows. Note that this is undefined behavior. The assignment
`int64_t a = ...` converts the (already overflowed) result to the wider
type, without changing its value.

You probably want to write something like:

```c++
int64_t a = 1LL << 31;
```

[type]: https://en.cppreference.com/w/cpp/language/integer_literal#The_type_of_the_literal


message:
Teensy 2.0 MIDI: Number of notes in a chord limited to 6?

I am using the Teensy 2.0 with USBMidi in a project that allows musicians to use retro computers as "instruments" (https://github.com/fredlcore/midijoy). So far, all these computers had no more than four voices, so the problem I am encoutering now has not arisen so far.

When I now want to play a chord with more than six notes simultaneously, only the first six notes are received and played. However, if I release two from, let's say, eight notes, the remaining two notes are subsequently being played if these keys are still kept pressed.

Here is a script reduced to the bare minimum, when you press eight keys on the MIDI device one after another, you'll see that it stops after the sixth key, and when you then subsequently keep all keys pressed and release one after the other, you'll see that the "remaining" keys/notes will be received then:

```
void setup() {
  Serial.begin(38400);
  usbMIDI.setHandleNoteOn(doNote);
  usbMIDI.setHandleNoteOff(doNoteOff);
}

void loop() {
  usbMIDI.read();
}

void doNote(byte channel, byte pitch, byte velocity) {
  Serial.println(channel);
  Serial.println(pitch);
}

void doNoteOff(byte channel, byte pitch, byte velocity) {
  Serial.println(channel);
  Serial.println(pitch);
}
```

You have to configure the Teensy as a MIDI device so that the USBMidi libraries will be found.

Is there a hardware limit in the Teensy 2.0 that will prevent it from processing more than six notes at a time? Or is this a constraint within the library?

body: @Majenko pointed me to the root cause of the problem: I was sending MIDI notes via Ableton's feature of using the computer's keyboard. It seems that the OS (or the keyboard) cannot send/receive more than six simultaneous keystrokes.


message:
How to power Arduino pro mini and DFPlayer mini togather with 3.7 V LiPo battery?

I made a small box containing Arduino Pro Mini , DFPlayer Mini player and a 3.7V LiPo battery. Is it possible to power two devices with 3.7 V Battery?
What is the best way to save power for longer time performance?

body:
Use a buck/boost voltage regulator. Those are high efficiency switching regulators, and can either increase or decrease the input voltage. Feed the output of the regulator directly into the Arudino's 5V (or 3.3V) line, bypassing the on-board voltage regulator.

What input voltages do the 2 devices need? Both 5V? If so, you can use a single voltage regulator to power both devices. If one needs 3.3V and the other needs 5V you may have to have 2 different voltage regulators.

By using a switching regulator you can bypass the fairly inefficient linear regulator in your Arduino supply 3.3V or 5V to it directly (depending on the type of board you have.)

## Edit:

Ok, I looked it up and a DFPlayer Mini player appears to be a shield designed to plug directly into an Arduino. It looks like it can be powered from 3.2 to 5V, so you should be able to use it with either a 3.3V or 5V Arduino Pro Mini. Once you've decided if you're going to use a 3.3V or 5V Arduino, pick a buck/boost voltage regulator with the desired output voltage (or get an adjustable one and set it appropriately.)


message:
Flash firmware with hex file over serial with Python (no avrdude, Arduino IDE)

I'm trying to make a Python function in the [TCLab package][1] to flash firmware to an Arduino Leonardo (32u4). I can compile the [TCLab ino][2] (firmware) and deploy with the Arduino IDE or with the [Python avryp][3] package. The [Python avr_helpers][4] package looks like a possible solution but is only supported with the older Python 2.7. Forum posts [such as this one][5], https://arduino.stackexchange.com/questions/60599/how-can-i-upload-a-hex-file-to-an-arduino-uno, and others suggest `avrdude` to upload a hex file. However, I need a Python solution that can be used on any platform (MacOS, Windows, Linux, etc) without a requirement to install packages (avrdude, Arduino IDE, etc).

I have the [hex file][6] from a successful Arduino build. Here is an unsuccessful attempt to load the hex file with serial communication:

```python
import serial
import time
import os

# open and close COM8 to activate bootloader
ser = serial.Serial('COM8',baudrate=1200)
print(ser.isOpen()); ser.close()
time.sleep(2)

# load hex file on COM9
filesize = os.path.getsize('tclab_v2.ino.hex')
fid = open('tclab_v2.ino.hex','rb')
offset = 0; MTU = 20
ser2 = serial.Serial('COM9',115200)
while (offset < filesize):
    fid.seek(offset, 0)
    ser2.write(fid.read(MTU))
    offset = offset + MTU
ser2.close()
```

The script is able to activate the bootloader on another port and connect. If I transfer all at once with `ser2.write(fid.read())`, it semi-bricks the Arduino and I recover it by hitting the reset button just before the Arduino IDE installs the firmware. I use a Maximum Transfer Unit (MTU) of 20 but I couldn't verify if there is one for the Leonardo. I can write a Python function to identify the ports and have used `COM8` and `COM9` here just to simply the test. Although the TCLab firmware is preloaded for Python, sometimes users change the firmware to use MATLAB, Octave, or Java and then want to switch back to Python. I'd like to make that as easy as possible without adding more steps or more instructions to the [troubleshooting FAQ][7]. Can I update the firmware like the [MATLAB Arduino Support Package][8] that detects a new device and transfers the firmware automatically with user confirmation?

  [1]: https://pypi.org/project/tclab/
  [2]: https://github.com/APMonitor/arduino/blob/master/0_Test_Device/Python/tclab_v2/tclab_v2.ino
  [3]: https://pypi.org/project/avryp/
  [4]: https://pypi.org/project/avr_helpers/
  [5]: https://forum.arduino.cc/index.php?topic=417659.0
  [6]: https://github.com/APMonitor/arduino/blob/master/0_Test_Device/Python/tclab_v2/tclab_v2.ino.hex
  [7]: https://apmonitor.com/pdc/index.php/Main/ArduinoSetup
  [8]: https://www.mathworks.com/hardware-support/arduino-matlab.html

body:
This isn't the exact answer but it helps.

Uploading without avrdude is complicated and generally slow. The best solution to not using the IDE is to open and close a port then use the avrdude command that the ide usually uses.

```python
from serial import Serial
from time import sleep
from subprocess import run

while input('Press enter to upload ') == '':
    Serial('COM5',baudrate=1200).close()
    sleep(1)
    run(["C:\\Progra~2\\Arduino\\hardware\\tools\\avr/bin/avrdude", "-CC:\\Progra~2\\Arduino\\hardware\\tools\\avr/etc/avrdude.conf", "-v", "-patmega32u4", "-cavr109", "-PCOM6", "-b57600", "-D", "-Uflash:w:C:\\Users\\USER\\Desktop\\Python\\tclab_v2/tclab_v2.ino.hex:i"])
```


message:
How can I make my custom board use the programmer selected in "Tools->Programmer" when the Upload button is pushed?

I've created a custom board that can be programmed using any one of several programmers defined in `programmers.txt`. I would like the user to be able to choose which programmer to use via the "Tools->Programmer" menu options.

I tried using `{protocol}` and `{upload.protocol}` in `platform.txt` to pass the programmer to the upload tool, but neither seem to be defined when the `Upload` button is used to initiate the upload (they are defined if `Upload using programmer` is selected from the menu).

body:
Make sure you do not have a `protocol` listed in the `boards.txt` file. If the uploader sees protocol is `null` then it will fall back to using the same code that "Upload using programmer" does.

Relevant code in `SerialUploader.java`:

```
    if (usingProgrammer || prefs.get("upload.protocol") == null) {
      return uploadUsingProgrammer(buildPath, className);
    }
```


message:
3-instruction remote machine coding Arduino Atmel chip over a serial line from a tethered (host) PC

I'm trying to write a program for AVR Atmel 328 chip on Arduino Nano board that will allow me to send machine code instructions to the chip over a serial line, run/execute them on the chip, and interrogate the results by reading chip memory and sending the contents back over the serial line.  This is the genesis of the idea: [3-instruction Forth by Frank Sergeant][1].

The remote-store and remote-fetch instructions appear to be working fine, but **I've not been able to get the remote-call instruction (`XCALL()` function) to work.** The approach I've taken is to coerce a 16-bit address into a subroutine by casting it as a function pointer.

Below is the code that is running on the Arduino Nano (compiled in the Arduino IDE and uploaded using the USB cable via the bootloader)

Any insight would be greatly appreciated!  (I can add diassembled code, my remote instructions etc, if that helps).

Thanks in advance!

    // Remote serial development platform for machine coding ArduinoNano/ATmel328, AKE, Jun 9, 2020

    // global variables
    unsigned char byt;                  // command token from host
    unsigned char mem[255];             // memory window under programmatic control
    unsigned char dat;                  // data byte from host
    unsigned char adr_lo;               // address from host, low byte first
    unsigned char adr_hi;
    unsigned short adr;                 // combined 16-bit address
    typedef void (*GeneralFunction)();  // template to call memory address (as a subroutine)

    void setup() {
      Serial.begin(9600);              // Turn UART serial protocol ON for comms with host PC
      Serial.write(0xFF);              // magic number to verify transmission
      Serial.write(0xFE);
      Serial.write((int) mem);         // Informs you of the writeable address space available (LSB, MSB) for tethered memory access
      Serial.write((int) mem>>8);
    }

    char get_byte(void) {
        while (!(Serial.available()>0)) { delay(50); }
        return Serial.read();
    }
    short get_adr(void) {
        adr_lo=get_byte();
        adr_hi=get_byte();
        return ( (short)adr_hi<<8 )   |   (short)adr_lo;
    }
    void xstore() {             // Instruction 1 = xstore(data,adr_lo,adr_hi).  Store byte from host at indicated address in target.
        dat=get_byte();
        adr=get_adr();
        *(char *)adr=dat;
    }
    void xfetch() {             //  Instruction 2 = xfetch(adr_lo,adr_hi).  Read byte from target memory and return to host.
            adr=get_adr();
            dat=*(char *)adr;
            Serial.write(dat);
    }
    void xcall() {              //  Instruction 3 = xcall(adr_lo,adr_hi).  Execute subroutine in target memory from indicated address.
                                //  WARNING!  User must have stored RET instruction to send control back to serial monitor.
            adr=get_adr();
            GeneralFunction fGf=adr;
            fGf;
    }

    void loop() {
        byt = get_byte();               // user specified instruction token (1,2,3)
        if(byt == 0x01 )      { xstore(); }
        else if (byt == 0x02) { xfetch(); }
        else if (byt == 0x3 ) { xcall(); } // else ignore any other serial inputs
    }

  [1]: http://pygmy.utoh.org/3ins4th.html

body:
The AVR CPU cannot execute instructions from RAM. It's not a question of what the compiler can do or should be able to do, the physical chip itself cannot do it. There is simply no physical pathway between the RAM and the instruction decoder in the CPU.

Instructions can *only* be executed directly from Flash memory. That is how the chip works. You can only execute code that you send over serial if you first erase a page (or more) of Flash memory then burn the incoming code into that page. You can then call the start of that page's address and your code will execute.

But there is another caveat there: only code running in the bootloader flash area is allowed to modify the flash memory. That means your code can't do it, only the bootloader. That doesn't mean that the bootloader has to be running, but the code that you execute has to reside there.

There is an alternative version of the Optiboot bootloader that can provide flash writing facilities to a user program, but I have no experience using it so can't assist with that.


message:
Serial.print() not fully printing

println() function is being used to send AT commands to GSM module.
```
sim800l.println("AT+CLTS=1");
  delay(3000);
  sim800l.println("AT+COPS=2");
  delay(3000);
  sim800l.println("AT+COPS=0,0");
  delay(3000);
```
But problem is the output -
```
AT+CLTS=1

OK
AT+COP
```
The command AT+COP did not print fully? Why?
Minimal Reproducable Example -
```
#include <SoftwareSerial.h>    //Library required for serial communication
char MYDATA[18];
SoftwareSerial sim800l(3, 2); // RX,TX for Arduino and for the module it's TXD RXD, they should be inverted
void setup() {
  Serial.begin(9600); //Start the serial interface on 9600
  sim800l.begin(9600);
  delay(100);
  // AT command to set sim800l to SMS mode
  sim800l.println("AT+CMGF=1");
  //Serialcom();
  delay(100);
  // Set module to send SMS data to serial out upon receipt
  sim800l.println("AT+CNMI=2,2,0,0,0");
  delay(100);
  sim800l.println("AT+CLTS=1");
  delay(3000);
  sim800l.println("AT+COPS=2");
  delay(3000);
  sim800l.println("AT+COPS=0,0");
  delay(3000);
   sim800l.println("AT+CCLK?");
  Serial.find("+CCLK: \"");
  Serial.readBytesUntil('\+', MYDATA, 17);

}

void loop() {
 Serial.print(MYDATA);
}

body:
You're overflowing the serial receive buffer. There's only a limited amount of space (64 bytes normally, maybe less in SoftwareSerial) for receiving data before you must read it or lose data. Since you are just blindly throwing commands at the SIM800 and not doing anything with its responses until right at the end all that incoming data fills the receive buffer to overflowing.

Your methodology is flawed (not your fault, the examples on the internet are all rubbish and teach you the wrong way of doing things). What you should be doing is issuing a command then receiving the response back and parsing it to see if the command was successful or not, and retrieve any information that the response may include that you would want to know.


message:
Attiny85 microcontroller programming without arduino

I have decided to make a simple project so thinked about arduino but that seems very worthy so i decided to use attiny85 ic for my project,but i don't have arduino or avr to program it. Is there any way to program the below ic without arduino or avr?.

body:
> **Is there any way to program [a bare AVR microcontroller] without Arduino [hardware] or AVR [hardware programmer]?**

Programming a *bare* AVR microcontoller like the ATtiny85 *IC* needs either another Arduino board or an AVR programmer device.

---

### Programmer $4-$7

Something like the Pololu AVR Programmer v2.1 can be bought for $7 and used with the free Arduino development software (IDE). I have used this to program an ATtiny85. This is what I would suggest, because a programmer is the most versatile solution.

[![USBAPS][1]][1] Even cheaper, a $4 USBASP

---

### Arduino as ISP $4.50

I have used an old Arduino Duemilanove using the Arduino as ISP sketch as a programmer for an ATtiny85 but any Arduino with inbuilt USB and enough GPIO could be used. There are some low cost ATmega328P or ATmega32u4 based Arduino clones that would be suitable. A Nano v3 clone costs $4.50.

[![Nano][2]][2]

---

### Development Board with USB $3

As others have commented, you can buy a "digispark" (just Google and click "shopping") for three or four dollars. This is essentially a breakout board with an ATtiny85, a USB connector and a soft-USB-capable bootloader pre-loaded onto the ATtiny85. You can program it with the Arduino IDE after using the IDE's board-manager to install Digistump's "core" definitions for the Digispark. It doesn't need another Arduino nor an AVR Programmer. I bought three on Amazon for $9 a month ago.

[![three digisparks][3]][3]

Since it *is* an Arduino-compatible development board, it doesn't really meet your requirement of "without Arduino" - but it might be the closest solution to what you have in mind.

---

Useful resources and inspiration:

- [ATtiny-Based Beginner's Kit](http://www.technoblogy.com/show?NMX)
- [Twelve PWM outputs from an ATtiny85](http://www.technoblogy.com/show?2H0K).

Yes, 12 LEDs individually controlled with just four resistors and four pins of an eight-pin ATtiny85 and and no other components!

I have no affiliation with the above site, I just think it is one anyone new to electronics with an ATtiny85  would find interesting.

  [1]: https://i.stack.imgur.com/VQxJG.png
  [2]: https://i.stack.imgur.com/8j43Z.png
  [3]: https://i.stack.imgur.com/ZXwDP.png


body:
>  **Is there any way to program [a bare AVR microcontroller] without Arduino [IDE software] or AVR [software development toolkit]?**

I believe you can use

- A text editor of your choice to create and edit source code files.
- The GNU compiler [GCC-AVR](https://www.google.com/search?q=gcc+for+avr) to compile source code into machine-code.
- The [avrdude](https://www.nongnu.org/avrdude/) program to install the compiled code onto the microcontroller.

All these can be obtained at zero cost.


message:
Exit from for function after detecting obstacles

#include <HCSR04.h>

    int red = 13;
    int green = 12;
    int blue = 11;
    int trigger = 9;
    int echo = 8;
    int halt;

    void setup(){
      pinMode(red, OUTPUT);
      pinMode(green, OUTPUT);
      pinMode(blue, OUTPUT);
      pinMode(trigger, OUTPUT);
      pinMode(echo, INPUT);
      Serial.begin(9600);
    }

    void redLed(){
      rgb(255,0,0);
      delay(200);
    }

    void rgb(int r, int g, int b){
      analogWrite(red, r);
      analogWrite(green, g);
      analogWrite(blue, b);
    }

    void fadeBlu(){

        for (int i=0; i<=255; i+=5){
        rgb(0,0,i);
        delay(40);

        Serial.print("halt in IF is ");
        Serial.println(halt);
        }

        for(int i=255; i>=0; i-=5) {
          rgb(0,0,i);
          delay(40);

          Serial.print("halt ELSE is ");
          Serial.println(halt);
        }
    }

    void human() {

      UltraSonicDistanceSensor distanceSensor(trigger, echo);
      double distance = distanceSensor.measureDistanceCm();
      halt = 0;

      // cover sensor
      if (distance<=30) {
        halt=0;
        redLed();
      }
      // no cover
        halt=-1;
        fadeBlu();
    }

    void loop(){
      human();
    }

I'm looking for a way to exit from "for" loop of fadeBlue() function if the hand is detected in front of sensor. I would like that in any case of fading and if there is hand in front of sensor the led became red. In my code the led doesn't stay red if I had hand in front of the sensor and also the value of "halt" doesn't change. I put some serial.println to make debugging.

body:
First, try to avoid duplication of code, so make a sub function (I slightly changed the print statement, but I assume it's only for debugging):

    void fadeBlu()
    {
        fadeBlueCycle(0, 255, 5);
        fadeBlueCycle(255, 0, -5);
    }

    void fadeBlueCycle(uint8_t start, uint8_t end, int8_t step)
    {
        for (int i = start; i != end; i += step)
        {
            rgb(0, 0, i);
            delay(40);

            Serial.print("halt in step ");
            Serial.print(step);
            Serial.println(halt);
        }
    }

Now to break from the `for`, you can use `break`, or simply `return`. It's not a good practice to have multiple `return` statements in one function, thus put it at the end, and use a `break`. Also, some people don't like a `break` and prefer using a `while. This would look like:

    void fadeBlueCycle(uint8_t start, uint8_t end, int8_t step)
    {
        uint8_t i = start;
        bool condition = true;

        while ((i != end) && condition) // or !condition, depending on what you prefer
        {
            rgb(0, 0, i);
            delay(40);

            Serial.print("halt in step ");
            Serial.print(step);
            Serial.println(halt);

            condition = `some condition`;
            i += step;
        }
    }


message:
Ardiuno DUE board. Sketch uploading Error

I am working on Arduino UDE board in Ubuntu 18.04. I've followed following link tutorial.

https://www.arduino.cc/en/Guide/ArduinoDue#:~:text=Use your Arduino Due on the Arduino Desktop IDE,the Arduino Boards Manager page.

In Ardiuno IDE I am getting as /dev/ttyS4. Also, I've gone with follwing procedure :
```
sudo usermod -a -G dialout username
sudo chmod a+rw /dev/ttyS4
ls -l /dev/ttyS4
```
This gave the following outpit
```
crw-rw-rw- 1 root dialout 4, 68 Jun 17 17:26 /dev/ttyS4
```
And I am getting following error while uploading sketch though Ardiuno IDE :
```
Sketch uses 11092 bytes (2%) of program storage space. Maximum is 524288 bytes.
Forcing reset using 1200bps open/close on port /dev/ttyS4
/home/user/.arduino15/packages/arduino/tools/bossac/1.6.1-arduino/bossac -i -d --port=ttyS4 -U false -e -w -v -b /tmp/arduino_build_718911/ardiuno_to_python.ino.bin -R
Send auto-baud
No device found on ttyS4
An error occurred while uploading the sketch
Set binary mode
```
I've tried following solution of decreasing baudrate to 1200 by following command line mulitple times till I get output as 1200 :
```
stty -F /dev/ttyS4 speed 1200 cs8 -cstopb -parenb
```
Still I am facing the error while uploading sketch. I've tried pressing reset and erase buttons few seconds but still not getting anything. Can anyone please help

body: The problem is solved. The cable came with my Arduino was charge only , I tried data transfer cable and it worked. This is so dumb. sorry for wasting your time.


message:
delay() problem for 74HC595 and 7-segment

I'm trying to run a 3-digit 7-segment using single 74HC595 based on Arduino. But I have a serious problem with `delay()` function. When I want to count from 000 to 999 with `delay(1000)`, this delay function causes all digits to be off! My code is as below and I uploaded a video **[Click Here][1]** to understand my purpose. This problem can affect some applications like reading the temperature of DS12b20 which requires a delay itself.

    //                 2        1         0
    //               ----      ----      ----
    //              |    |    |    |    |    |
    //               ----      ----      ----
    //              |    |    |    |    |    |
    //               ----      ----      ----

    int latch = 8; //74HC595  pin STCP
    int clock = 9; //74HC595  pin SHCP
    int data = 10; //74HC595  pin DS

    // Each annode pin (for those that don't know think of it as an on switch when it's assigned HIGH)
    int dig1 = 2; // digit0
    int dig2 = 3; // digit1
    int dig3 = 4; // digit2
    int digit[4]={dig1, dig2, dig3};

    int timer=3;
    // these are bits to make the 8 bit byte accepted by the segment display the 9th is the demical point
    // 0-9 then invald numbers
    byte table[] = {
      B00111111, B00000110, B01011011, B01001111, B01100110,
      B01101101, B01111101, B00000111, B01111111, B01101111, B01111111
    };

    void setup(){
      pinMode(latch, OUTPUT);
      pinMode(clock, OUTPUT);
      pinMode(data, OUTPUT);
      pinMode(dig1, OUTPUT);
      pinMode(dig2, OUTPUT);
      pinMode(dig3, OUTPUT);
    }

    //this sends the data to the digit
    void RunNum(int num, int SelectDigit){
      digitalWrite(latch, LOW);
      shiftOut(data, clock, MSBFIRST, table[num]);
      digitalWrite(latch, HIGH);
      digitalWrite(digit[SelectDigit], LOW);
      delay(timer);
      digitalWrite(digit[SelectDigit], HIGH);

    }

    //main program
    void loop() {
      for (int i=0; i<10; i++){
        for (int j=0; j<10; j++){
          for (int k=0; k<10; k++){
            RunNum(k, 0);
            RunNum(j, 1);
            RunNum(i, 2);
            delay(1000);  //  <====    This line affects the project
          }
        }
      }
    }

 I updated my code (only `void loop()`) as below using `millis()`. You can watch the results (**[Click Here][2]**). But, the delay problem has not been solved so far!

    const long interval = 1000;   //  1000 ms = 1 s
    long previousMillis = 0;
    unsigned long currentMillis=0;

    //main program
    void loop() {
      for (int i=0; i<10; i++){
        for (int j=0; j<10; j++){
          for (int k=0; k<10; k++){
            while (currentMillis - previousMillis < interval){
              currentMillis=millis();
              RunNum(k, 0);
              RunNum(j, 1);
              RunNum(i, 2);
            }
            previousMillis = currentMillis;
          }
        }
      }
    }

  [1]: http://s12.picofile.com/file/8400330784/VID_20200617_212526.mp4.html
  [2]: http://s12.picofile.com/file/8400414976/VID_20200618_195832.mp4.html

body:
With the displays which use shift register to light multiple seven segment digit blocks, the register lights up only one digit at a time. The illusion of multiple digits lit is created by fast switching the digits in round. Small delays in this cause the number to look dim, larger delays create flickering and long delays show only one digit lit. So a sketch handling this type of display must run without delays.

In this type of sketch, everything must be handled without delays, so if some sensor requires a delay, start the reading and a millis timer and after the elapsed time read the result.

There are displays using specialized chips, for example TM1637D, which handle the seven segments even if your sketch stops in delay.

----------

adoption of the [BlinkWithoutDelay][1] basic example for your algorithm:

    unsigned long previousMillis = 0;
    const long interval = 1000;
    int i, j, k;

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

    void loop() {
      unsigned long currentMillis = millis();

      if (currentMillis - previousMillis >= interval) {
        previousMillis = currentMillis;
        k++;
        if ( k == 10) {
          k = 0;
          j++;
          if (j == 10) {
            j = 0;
            i++;
            if (i == 10) {
              i = 0;
            }
          }
        }
        Serial.print(i);
        Serial.print(j);
        Serial.println(k);
      }
    }

  [1]: https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay


body:
<strike>In `loop()` as you've shown it in your code, you can move `RunNum(i,2);` down to outside of the 'j' and 'k' loops. Likewise you can move `RunNum(j,1);` down to outside of the 'k' loop. This won't fix your problem but it will speed up each update of the display.</strike>

Then, know that you can tell one (or all) of your DS18B20 sensors to start a temperature conversion *without waiting for the conversion to finish*. Then you use millis() to tell you when the conversion is done, and you can get the result very quickly. Some libraries provide the amount of time you need to wait for the conversion; some provide some kind of an "is it done yet?" boolean function. Either one of those will let you remove the 'wait til done' delay.

Update:

> This strategy doesn't work properly!...

Sorry if I missed something - it looked like there were opportunities to optimize there.

> About temperature sensor, I should say that reading the temperature takes about 750 ms itself. In other words, it acts as a delay and causes turning off the display for 750 ms.

It is temperature measurement and conversion to a 12-bit result - which takes place *entirely within the DS18B20* sensor itself - that takes 750ms. *The Arduino is not involved in that process* and could be doing other tasks such as maintaining your display during that time.

*Reading* the temperatures, once the conversion is done, is much quicker.  If your library doesn't provide the ability to start a conversion and return, without waiting for the results, and separate entry to read the results, look for a library that does.

Update:
[Miles Burton's Arduino-Temperature-Control-Library][1] provides a 'wait for conversion' flag that you can set false so ::requestsTemperatures() will return immediately, and an ::isConversionComplete() call to check whether the data is ready. (Of course, knowing that the device takes 750ms
for a 12-bit conversion, you could just as well use millis() to decide that.)

  [1]: https://github.com/milesburton/Arduino-Temperature-Control-Library


message:
Using RX TX pin

Can i use pin RX TX on Arduino Uno as reguler pin ? .
For input and output pin , because two digital pin on my board doesn’t work . Thank’s

body: Yes, you can use those pins like regular digital pins on the Uno. They are numbered 0 and 1. That is... provided you do not try to use `Serial`.


message:
Use an LDR to run a sketch

This may sound like a simple question but I have tried to find the right solution but all I find is the usual make an led blink and even I can code that nugget
I am quite new to programming arduino but am a dab hand with a soldering iron.
What I would like to do is combine the attributes of an LDR to allow a lighting sketch to run if it is dark and go off in daylight, but all I seem to find is turn a pin high or low, this is no good as I already have a sketch I would like to run

I am using WS2811 led nodes housed in pinspot style housings so the sketch would need to check the light level and if it is below a set value run the rest of the sketch then check every hour to see if the light level has changed to be above a set level  if it is go into a check loop until the light level falls again to below the set value can anyone point me in the right direction I would be grateful for any assistance

Thanks
Dave

body:
You're unlikely to find exactly what you want as existing code example. Break it into parts and solve it in parts.

You can't "Run a sketch" based on reading a value of an LDR. You can write a new sketch that reads an LDR, and calls a function if it's dark, or a different function if it is light. You will need to refactor your code from your other sketch into functions that you can integrate into your new combined sketch that uses the LDR. That means doing some original programming, not "finding the right solution" ready-made on the internet.

First, how do you use an LDR to determine if it's light or dark? Answer, use an analog input. Build a voltage divider with the LDR and a similar sized resistor, and feed the output into an analog pin. Say the LDR is between +5V and the pin, so more light results in higher voltage, hence a larger value.

Log the output of the LDR to the console in a loop, and decide on your threshold values for light and dark. Make the threshold value a constant. Let's call it DARK.

Now write a loop function. It might look something like this:

    int lightValue;
    #define ldr_pin xxx //your pin number
    #define threshold xxx //your threshold value

    void setup() {
       //set the ldr pin as an analog input
    }

    void loop() {
       lightValue = analogRead(ldr_pin);
       if (lightValue <= threshold) {
          doNightStuff();
       } else {
          stopDoingStuff();
       }
    }

## Edit:

As mentioned by Edgar, the code above will be subject to "jitter", where it will rapidly switch back and forth between the dark and light states.

The solution is to add a buffer range where once it's in one state, it doesn't change states until it leaves the buffer range.

The if statement might look like this:

    #define buffer 5

    if ((lightValue +buffer) <= threshold)
        doNightStuff();
    else if ((lightValue -buffer) >= threshold)
        stopDoingStuff();


message:
How to run my buzzer for few more seconds after switching off

This is a basic level lazer alarm project. When anyone crosed or kept their hands on the lazer. buzzer starts working but when they took their hand from lazer light buzzer stops. But i want even after taking hands my buzzer should work for few (15-30) seconds .so please help me by giving idea..

body:
If you are using a digital buzzer, you can do:
```
digitalWrite(buzzerPin,HIGH);
delay(1000);
digitalWrite(buzzerPin,LOW);


message:
Unable to send UDP packets while performing OTA update on the esp8266

I am sending specific **UDP** packets with my **esp8266** every 5s, I have added an **OTA update** command, and added the update_progress callback aiming to send it back to my laptop, using a serial terminal I noticed that regular packets, as well as the progress packet, are not sent during the update, everything gets back after. Is the esp able to send and receive packets simultaneously?, is there any interference or the **OTA update** process causes an interruption?

*Hardware: ESP8266MOD Nodemcu*

*Software: VS code with portable Arduino 1.8.9, espcore 2.6.3*

body:
esp8266 ArduinoOTA library has
```cpp
  WiFiUDP::stopAll();
  WiFiClient::stopAll();
```
to ensure undisturbed OTA upload


message:
Am not able to call C++ function pointers from inline assembly

Due to some curiosity, I was trying to use some assembly with my Arduino MEGA 2560.
I am not able to invoke a function from a c++ function pointer array.

When I uncomment the call function, `func_a` runs. However, when I almost reproduce the assembly, it doesnt work.

Example:

    extern "C" void __attribute__ ((used, noinline, noreturn)) func_a();

    typedef void (*volatile func_ptr)();

    func_ptr tasks[MAX_TASKS] = {&func_a};

    extern "C"
    void __attribute__ ((used, noinline)) call(func_ptr *ptr) {
        (*ptr)();
    }

    void __attribute__ ((noreturn, used)) setup() {

        // call(tasks);

        asm volatile (
        "lds r26, (tasks)\n"
        "lds r27, (tasks + 1)\n"

        "ld r30, X+\n"
        "ld r31, X\n"

        "eijmp\n"
        );
    }

Generated assembly recovered from avr-objdump

    000001c6 <setup>:
     1c6: a0 91 00 02  lds r26, 0x0200 ; 0x800200 <tasks>
     1ca: b0 91 01 02  lds r27, 0x0201 ; 0x800201 <tasks+0x1>
     1ce: ed 91        ld r30, X+
     1d0: fc 91        ld r31, X
     1d2: 19 94        eijmp
     1d4: 08 95        ret

    000001d6 <call>:
     1d6: dc 01        movw r26, r24
     1d8: ed 91        ld r30, X+
     1da: fc 91        ld r31, X
     1dc: 19 94        eijmp

An specific resources I should refer for things like this?

If it matters, I'm using platformio on a linux system for compilation.

body:
I will start off by saying that I am no expert in AVR assembly, so I have no idea if any of this is actually correct. However from reading the various [documents](http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf) on the subject I have gleaned:

* On the ATMega2560 `EIJMP` uses a combination of both the Z register *and* the `EIND` register to form a full address.

That means that as well as setting up the Z register for the lower 16 bits of the address you also have to set up the `EIND` register for the upper 5 bits of the address.

> Indirect jump to the address pointed to by the Z (16 bits) Pointer Register in the Register File and the EIND Register in the I/O space. This instruction allows for indirect jumps to the entire 4M (words) Program memory space.

It then goes on to show an example:

```
ldi r16,$05 ; Set up EIND and Z-pointer
out EIND,r16
ldi r30,$00
ldi r31,$10
eijmp ; Jump to $051000
```

How you determine what the EIND register should be? Well, in general you don't. You wouldn't use EIJMP. From what I understand for functions outside the lower 64kwords of address space the compiler builds a "jump table" which is stored in the lower area of memory. You jump to the entry in that table with `IJMP` and that table then jumps to the final destination with `EIJMP` for you.

Doing this kind of jumping in assembly isn't really a nice thing to try and figure out. It's messy. Better to let the compiler do it for you and use C rather than assembly.  The AVR-GCC guys put a lot of work into making function pointers work correctly (from what I have read it wasn't easy even for them), and you're just re-inventing the wheel.

At the very least you should implement your code 100% in C to begin with then look at the compiled output to see how the compiler thinks it should be done.


body:
It seems you got confused by the pointer indirections, which is
confounded by the _implicit_ indirections made by the compiler.

Here:

```c++
extern "C"
void __attribute__ ((used, noinline)) call(func_ptr *ptr) {
    (*ptr)();
}
```

The parameter `ptr` is _not_ a function pointer: it's a pointer to a
function pointer. You have to dereference it _twice_ in order to get the
function: `(**ptr)();`. Note that the compiler implicitly dereferences a
function pointer if you call it like a function: that's why you get no
error by explicitly dereferencing the pointer only once. In the
generated assembly, the lines

```lisp
ld  r30, X+
ld  r31, X
```

dereference `ptr` in order to get the address of the function to call.

You probably wanted to write

```c++
extern "C"
void __attribute__ ((used, noinline)) call(func_ptr ptr) {
    ptr();
}
```

And then use it as:

```c++
call(tasks[0]);
```

If you just `call(tasks)`, the array identifier decays to pointer, and
the compiler handles this as a shortcut for `call(&tasks[0]);`, which
turns out to be compatible with your initial implementation of `call()`.

Now, in your inline assembly you have

```lisp
lds r26, (tasks)
lds r27, (tasks + 1)
```

The assembly treats `tasks` as a _symbol_ representing the address of
the `tasks` array. The linker replaces those symbols by the actual
address (`0x0200`). Those instructions read the RAM at this and the
following address. These slots of RAM hold the first item of the array,
namely `&func_a`. So now you have this address in the X register pair.
No need to read RAM again: you can `movw r30, r26` and do the indirect
jump. Or, better yet, load into Z to begin with:

```list
lds r30, (tasks)
lds r31, (tasks + 1)
eijmp
```

See also Majenko's answer: here I am assuming `EIND` is somehow
correctly set up to begin with. On an Uno, you would just use `ijmp`
instead of `eijmp` and not worry about `EIND`.


message:
Fail to convert time_T from past to tm struct

Continuing a [Question asked few days ago][1], answered by Edgar, a new question has rised:

My goal was using a **past** `time_t` value, and convert it into a `struct tm` variable in order to  use it, part as a `Char` to print a readable text and some for logic queries.

At start NTP is configured as:

    void myIOT32::startNTP(const int gmtOffset_sec = 2 * 3600, const int daylightOffset_sec = 3600, const char *ntpServer = "pool.ntp.org")
    {
      configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
    }

and every-time I need to get epoch and or `struct tm` of **current** time I call this function

    void myIOT32::getTime()
    {
      int a = 0;
      while (a < 3)
      {
        if (getLocalTime(&timeinfo))
        {
          delay(100);
          time(&epoch_time);
        }
        a++;
      }

BUT, when using the following function I get not GMT (+3) reference as needed :

    struct tm *myIOT32::convEpoch(time_t in_time)
    {
      struct tm *convTime = gmtime(&in_time);
      //char time_char[40];
      //sprintf(time_char, "d-d-d d:d:d", convTime->tm_year + 1900, convTime->tm_mon + 1, convTime->tm_mday,
              convTime->tm_hour, convTime->tm_min, convTime->tm_sec);
      return convTime;
    }

Meaning I get to correct epoch time, but `strcut tm` is 3 hrs earlier ( and no, I do not want to hard-code `+3`... )

  [1]: https://arduino.stackexchange.com/questions/76290/error-passing-a-time-t-and-struct-tm-esp32

body:
replacing `gmtime(&timeinfo)` with `localtime(&timeinfo)` in `myIOT32::convEpoch` passes definition of time-zone as needed.

for more information [in this cpluspls site][1]

  [1]: http://www.cplusplus.com/reference/ctime/gmtime/


message:
Having trouble with sprintf function and string class

in my code, I was using string class to make an array to store my menu items
~~~~~~~~~~~~~~~~~~~~~~~~
String menu[2] = {{"Menu 1"}, {"Menu2"}};
~~~~~~~~~~~~~~~~~~~~~~~~
How do I convert this into char arrays and how do I call them?
~~~~~~~~~~~~~~~~~~~~~~~
Example:
Serial.println(menu[0]);

body:
Create them as char arrays like this:

    const char* menu[2] = {"Menu 1", "Menu 2"};

and use them like this:

    Serial.println(menu[0]);


message:
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&)'

body:
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](https://www.usb.org/sites/default/files/documents/hid1_11.pdf) 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];
    }

}


message:
Mega: attachInterrupt on pin 18/19/20/21 not working

**Task:**
I'm trying to create a fan-control with the arduino mega. I'm generating a PWM signal on pin 6 and 7 and want to use interrups to measure the rpm of the fans.

**Problem:**
On pin 2 and 3 everything wors fine, but I cannot get it working on any of pins 18-21. The numbers are jumping around wildly. BUT: The numbers are correct on 0% and 100% duty!

**What I've aleady tried:**

 - Changed my timer from 1 to 4 (currently it's 4)
 - Replaced the display to get rid of U8g2lib.
 - Changing connection order of the signal cables (and thus the connected fan).
 - Check the signal with an digital oscilloscope (looks fine on all ports)
 - Set the global ISR variables to volatile and byte to prevent update hazards.
 - Bang my head on the table.

Nothing solved my problem. What am I missing?
``` lang-c
    #include <Arduino.h>
    #include <U8g2lib.h>
    #include <Bounce2.h>

    #ifdef U8X8_HAVE_HW_SPI
    #include <SPI.h>
    #endif
    #ifdef U8X8_HAVE_HW_I2C
    #include <Wire.h>
    #endif

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

    #define PIN_CONTROL_S 6
    #define PIN_CONTROL_L 7
    #define PIN_SENSE_1 18
    #define PIN_SENSE_2 19
    #define PIN_SENSE_3 3
    #define PIN_SENSE_4 2
    #define PIN_BUTTON 22

    #define UPDATE_CYCLE 1000 // Refresh interval of the display/measurement.
    #define SIGNAL_PER_RND 2  // 2 Signals per revolution
    #define DUTY_INC 10       // Increate of the duty in % per button press
    #define PWM_MAX 320       // PWM mode counts up 320 then down 320 counts (25kHz)
    #define lineOffset 10     // Offset (y) per line on display

    word duty = 0;  // 0-100 duty cycle
    word dutyS = 0; // 0-320 = 0-100% duty cycle for small fans
    word dutyL = 0; // 0-320 = 0-100% duty cycle for large fans

    volatile byte counterFan1 = 0;
    volatile byte counterFan2 = 0;
    volatile byte counterFan3 = 0;
    volatile byte counterFan4 = 0;

    unsigned long lastDraw = 0;

    Bounce btnBouncer = Bounce(PIN_BUTTON, 50);

    void setupPwm() {
        // Steuerung
        pinMode(PIN_CONTROL_S, OUTPUT);
        pinMode(PIN_CONTROL_L, OUTPUT);

        // Sensoren
        pinMode(PIN_SENSE_1, INPUT_PULLUP);
        pinMode(PIN_SENSE_2, INPUT_PULLUP);
        pinMode(PIN_SENSE_3, INPUT_PULLUP);
        pinMode(PIN_SENSE_4, INPUT_PULLUP);

        // Clear timer register
        TCCR4A = 0;
        TCCR4B = 0;
        TCCR4C = 0;
        TCNT4 = 0;

        TCCR4A |= _BV(WGM41);  // Set PWM mode, phase correct. TOP is ICR1.  (Mode 10)
        TCCR4B |= _BV(WGM43);  // Start BOTTOM, TOP from OCR1x to OCR1x.

        TCCR4B |= _BV(CS40);   // Prescaler 1:1

        TCCR4A |= _BV(COM4A1); // High output OC1A on compareMatch when up-counting / low when down-counting
        TCCR4A |= _BV(COM4B1); // High output OC1B on compareMatch when up-counting / low when down-counting

        OCR4A = dutyS;         // set initial duty
        OCR4B = dutyL;         // set initial duty

        ICR4 = PWM_MAX; // TOP for TCNTx. 320 => @16Mhz CPU -> 25kHz PWM
    }

    void setupDisplay() {
        u8g2.begin();
        u8g2.setFont(u8g2_font_6x10_tf);
        u8g2.setFontRefHeightExtendedText();
        u8g2.setDrawColor(1);
        u8g2.setFontPosTop();
        u8g2.setFontDirection(0);
    }

    void attachInterrups() {
        attachInterrupt(digitalPinToInterrupt(PIN_SENSE_1), isrFan1, RISING);
        attachInterrupt(digitalPinToInterrupt(PIN_SENSE_2), isrFan2, RISING);
        attachInterrupt(digitalPinToInterrupt(PIN_SENSE_3), isrFan3, RISING);
        attachInterrupt(digitalPinToInterrupt(PIN_SENSE_4), isrFan4, RISING);
    }

    void detachInterrups() {
        detachInterrupt(digitalPinToInterrupt(PIN_SENSE_1));
        detachInterrupt(digitalPinToInterrupt(PIN_SENSE_2));
        detachInterrupt(digitalPinToInterrupt(PIN_SENSE_3));
        detachInterrupt(digitalPinToInterrupt(PIN_SENSE_4));
    }

    void setup() {
        setupDisplay();
        setupPwm();
        attachInterrups();

        pinMode(PIN_BUTTON, INPUT_PULLUP);
    }

    void draw(void) {
        char output[22]; // One line of the display can show 21 characters.
        float uPerSekS1 = counterFan1; // * 60000 / measureDuration / SIGNAL_PER_RND;
        float uPerSekS2 = counterFan2; // * 60000 / measureDuration / SIGNAL_PER_RND;
        float uPerSekL1 = counterFan3; // * 60000 / measureDuration / SIGNAL_PER_RND;
        float uPerSekL2 = counterFan4; // * 60000 / measureDuration / SIGNAL_PER_RND;
        int y = 0;

        sprintf(output, "Duty    :    =", duty);
        u8g2.drawStr(0, y, output);

        y += lineOffset;
        sprintf(output, "U/sec S1: m", (int) uPerSekS1);
        u8g2.drawStr(0, y, output);

        y += lineOffset;
        sprintf(output, "U/sec S2: m", (int) uPerSekS2);
        u8g2.drawStr(0, y, output);

        y += lineOffset;
        sprintf(output, "U/sec L1: m", (int) uPerSekL1);
        u8g2.drawStr(0, y, output);

        y += lineOffset;
        sprintf(output, "U/sec L2: m", (int) uPerSekL2);
        u8g2.drawStr(0, y, output);
    }

    void measure() {
        unsigned long measureDuration = millis() - lastDraw;
        if (measureDuration >= UPDATE_CYCLE) {
            // Deactivate interrupt while we are calculating
            detachInterrups();

            u8g2.clearBuffer();
            draw();
            u8g2.sendBuffer();

            // reset state
            counterFan1 = 0;
            counterFan2 = 0;
            counterFan3 = 0;
            counterFan4 = 0;
            lastDraw = millis();

            // Reactivate interrupt
            attachInterrups();
        }
    }

    void loop() {
        measure();
        btnBouncer.update();
        if (btnBouncer.fell()) {
            // Button was pressed. Increase duty.
            if (duty > 90) {
                duty = 0;
            } else {
                duty += DUTY_INC;
            }

            dutyS = duty * PWM_MAX / 100;
            dutyL = duty * PWM_MAX / 100;

            OCR4A = dutyS;
            OCR4B = dutyL;
        }
    }

    void isrFan1() {
        counterFan1++;
    }

    void isrFan2() {
        counterFan2++;
    }

    void isrFan3() {
        counterFan3++;
    }

    void isrFan4() {
        counterFan4++;
    }
```
**Edit:**
I've tried my best to create a readable circuit diagram. The 4-pin connectors represent the fans.

[![Circuit diagram of 4 4-pin fan control][1]][1]

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

body:
Ok, I did not solve the problem regarding pin 18-21, but I found an other solution: using PinChangeInterrupts and the [PinChangeInterrupt libary][1]

I did not change anything about my hardware setup, excep moving the wires from pin 18/19 to A8/A9. I've changed my code to use PinChangeInterrups for two of the fans, maybe I'll change all 4 fans.

Here is the new code:

```lang-c
#include <Arduino.h>
#include <U8g2lib.h>
#include <Bounce2.h>
#include <PinChangeInterrupt.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

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

#define PIN_CONTROL_S 6
#define PIN_CONTROL_L 7

//#define PIN_SENSE_1 18
//#define PIN_SENSE_2 19
#define PIN_SENSE_1 A8
#define PIN_SENSE_2 A9

#define PIN_SENSE_3 3
#define PIN_SENSE_4 2
#define PIN_BUTTON 22

#define UPDATE_CYCLE 1000 // Refresh interval of the display/measurement.
#define SIGNAL_PER_RND 2  // 2 Signals per revolution
#define DUTY_INC 10       // Increate of the duty in % per button press
#define PWM_MAX 320       // PWM mode counts up 320 then down 320 counts (25kHz)
#define lineOffset 10     // Offset (y) per line on display

word duty = 0;  // 0-100 duty cycle
word dutyS = 0; // 0-320 = 0-100% duty cycle for small fans
word dutyL = 0; // 0-320 = 0-100% duty cycle for large fans

volatile byte counterFan1 = 0;
volatile byte counterFan2 = 0;
volatile byte counterFan3 = 0;
volatile byte counterFan4 = 0;

unsigned long measureDuration;
unsigned long lastDraw = 0;

Bounce btnBouncer = Bounce(PIN_BUTTON, 50);

void setupPwm() {
    // Steuerung
    pinMode(PIN_CONTROL_S, OUTPUT);
    pinMode(PIN_CONTROL_L, OUTPUT);

    // Sensoren
    pinMode(PIN_SENSE_1, INPUT_PULLUP);
    pinMode(PIN_SENSE_2, INPUT_PULLUP);
    pinMode(PIN_SENSE_3, INPUT_PULLUP);
    pinMode(PIN_SENSE_4, INPUT_PULLUP);

    // Clear timer register
    TCCR4A = 0;
    TCCR4B = 0;
    TCCR4C = 0;
    TCNT4 = 0;

    TCCR4A |= _BV(WGM41);  // Set PWM mode, phase correct. TOP is ICR1.  (Mode 10)
    TCCR4B |= _BV(WGM43);  // Start BOTTOM, TOP from OCR1x to OCR1x.

    TCCR4B |= _BV(CS40);   // Prescaler 1:1

    TCCR4A |= _BV(COM4A1); // High output OC1A on compareMatch when up-counting / low when down-counting
    TCCR4A |= _BV(COM4B1); // High output OC1B on compareMatch when up-counting / low when down-counting

    OCR4A = dutyS;         // set initial duty
    OCR4B = dutyL;         // set initial duty

    ICR4 = PWM_MAX; // TOP for TCNTx. 320 => @16Mhz CPU -> 25kHz PWM
}

void setupDisplay() {
    u8g2.begin();
    u8g2.setFont(u8g2_font_6x10_tf);
    u8g2.setFontRefHeightExtendedText();
    u8g2.setDrawColor(1);
    u8g2.setFontPosTop();
    u8g2.setFontDirection(0);
}

void attachInterrups() {
//    attachInterrupt(digitalPinToInterrupt(PIN_SENSE_1), isrFan1, RISING);
    attachPCINT(digitalPinToPCINT(PIN_SENSE_1), isrFan1, RISING);

//    attachInterrupt(digitalPinToInterrupt(PIN_SENSE_2), isrFan2, RISING);
    attachPCINT(digitalPinToPCINT(PIN_SENSE_2), isrFan2, RISING);

    attachInterrupt(digitalPinToInterrupt(PIN_SENSE_3), isrFan3, RISING);
    attachInterrupt(digitalPinToInterrupt(PIN_SENSE_4), isrFan4, RISING);
}

void detachInterrups() {
//    detachInterrupt(digitalPinToInterrupt(PIN_SENSE_1));
    detachPinChangeInterrupt(digitalPinToPCINT(PIN_SENSE_1));

//    detachInterrupt(digitalPinToInterrupt(PIN_SENSE_2));
    detachPinChangeInterrupt(digitalPinToPCINT(PIN_SENSE_2));

    detachInterrupt(digitalPinToInterrupt(PIN_SENSE_3));
    detachInterrupt(digitalPinToInterrupt(PIN_SENSE_4));
}

void setup() {
//    cli();
    setupDisplay();
    setupPwm();
    attachInterrups();

    pinMode(PIN_BUTTON, INPUT_PULLUP);
//    sei();
}

void draw() {
    char output[22]; // One line of the display can show 21 characters.
    float uPerSekS1 = counterFan1 * 60000 / measureDuration / SIGNAL_PER_RND;
    float uPerSekS2 = counterFan2 * 60000 / measureDuration / SIGNAL_PER_RND;
    float uPerSekL1 = counterFan3 * 60000 / measureDuration / SIGNAL_PER_RND;
    float uPerSekL2 = counterFan4 * 60000 / measureDuration / SIGNAL_PER_RND;
    int y = 0;

    sprintf(output, "Duty    :    =", duty);
    u8g2.drawStr(0, y, output);

    y += lineOffset;
    sprintf(output, "U/sec S1: m", (int) uPerSekS1);
    u8g2.drawStr(0, y, output);

    y += lineOffset;
    sprintf(output, "U/sec S2: m", (int) uPerSekS2);
    u8g2.drawStr(0, y, output);

    y += lineOffset;
    sprintf(output, "U/sec L1: m", (int) uPerSekL1);
    u8g2.drawStr(0, y, output);

    y += lineOffset;
    sprintf(output, "U/sec L2: m", (int) uPerSekL2);
    u8g2.drawStr(0, y, output);
}

void measure() {
    measureDuration = millis() - lastDraw;
    if (measureDuration >= UPDATE_CYCLE) {
        // Deactivate interrupt while we are calculating
        detachInterrups();

        u8g2.clearBuffer();
        draw();
        u8g2.sendBuffer();

        // reset state
        counterFan1 = 0;
        counterFan2 = 0;
        counterFan3 = 0;
        counterFan4 = 0;
        lastDraw = millis();

        // Reactivate interrupt
        attachInterrups();
    }
}

void loop() {
    measure();
    btnBouncer.update();
    if (btnBouncer.fell()) {
        // Button was pressed. Increase duty.
        if (duty > 90) {
            duty = 0;
        } else {
            duty += DUTY_INC;
        }

        dutyS = duty * PWM_MAX / 100;
        dutyL = duty * PWM_MAX / 100;

        OCR4A = dutyS;
        OCR4B = dutyL;
    }
}

void isrFan1() {
    counterFan1++;
}

void isrFan2() {
    counterFan2++;
}

void isrFan3() {
    counterFan3++;
}

void isrFan4() {
    counterFan4++;
}

```

  [1]: https://github.com/NicoHood/PinChangeInterrupt


message:
Serial Interrupt

I want to create a simple program, that responds to me sending a character over the Arduino IDE console. I am using an arduino UNO. Here is my program:

    volatile bool MeasReceived=false;

    ISR(PCINT2_vect){
      PCICR = 0b00000000;    // turn off port d
      MeasReceived=true;
    }

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

      Serial.print("Hello PC");
      delay(1000);
      cli();
      PCICR |= 0b00000100;    // turn on port d
      PCMSK2 |= 0b0000001;    // turn on pins PD0 , PCINT16
      sei();

    }

    void loop() {

      if(MeasReceived==true){
        MeasReceived=false;
        inByte = Serial.read();

        if(inByte=='A'){   //A: PC requests measurement data from Arduino
           Serial.print('B');
        }
        else{
          Serial.print(inByte);
        }
      }
      PCICR = 0b00000001; // re-enable port d
    }

What I do is that I set the RX pin as a pin change interrupt. After that, I send a character through the console, for example 'A'. The ISR kicks in, firstly disabling the interrupt, and after that, the flag is set true. That way, I enter the part of the code where I do the Serial.read() command, to find what character was sent to me via the console.

The problem is that, no matter the character I send, the result is always 255. That means that the value of inByte, after the Serial.read() is always 255. What goes wrong?

**EDIT: Original question answered by me below. However, one interesting thing occured in the new code posted below.** If I put the Arduino to sleep (powerDown Mode), and try to wake it up with the serial interrupt, if I send only one character, then the arduino does wake up, but does not enter the ISR! If I send two characters, then the ISR is accessed and the flags set, with the program working fine. Here is the code, to reproduce the issue:

    volatile bool MeasReceived=false;
    uint8_t inByte;

    ISR(PCINT2_vect){
      PCMSK2 = 0b00000000;    // turn off port d
      MeasReceived=true;
    }

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

      Serial.begin(9600);
      Serial.flush();
      Serial.print("Hello PC");
      delay(1000);

      cli();
      PCICR = 0b00000100;    // turn on port d
      PCMSK2 = 0b00000001;    // turn on pins PD0 , PCINT16
      sei();
    }

    void loop() {

      if(MeasReceived==true){
        MeasReceived=false;
        delay(2000);
        inByte = Serial.read();

        if(inByte=='A'){   //A: PC requests measurement data from Arduino
           Serial.print('B');
        }
        else{
          Serial.print(inByte);
        }
        PCMSK2 = 0b00000001;

      }

      set_sleep_mode(SLEEP_MODE_PWR_DOWN);    //Set power down mode
      sleep_bod_disable();  //disable brown-out detection
      digitalWrite(LED_BUILTIN, LOW);
      sleep_enable();
      sleep_cpu();
      sleep_disable();
      digitalWrite(LED_BUILTIN, HIGH);
      delay(1000);
      //int i=Serial.available();
      //Serial.print(i);
      delay(1000);

    }

So, by sending one character, the Arduino wakes up, the LED shines, and after the two seconds, Arduino goes back to sleep, never entering the ISR and as a result not setting the flag. Furthermore, having sent one character, if I uncomment the Serial.available() printing, it prints "0"!

If I send two characters, the Arduino wakes up, and the program works fine.

body:
After more testing, it seems that the problem was that when I sent the character over the console, the interval between the time t1 that the change was noticed and the ISR was fired, and the time t2 that the Serial.read() happened, was very short, almost immediate. As a result, the byte (character) that I had sent over the serial console was not yet ready to be read, and the Serial.read() command returned plain '1's.

Furthermore, to disable/re-enable the pin-change interrupt, the right way seems to be to use the PCMSK register and not the PCICR. The initially posted code, had the extra problem that, when PCICR was re enabled (set to 0x01), the ISR was immediately fired again, reading an extra character (obviously all '1's). That was solved by disabling/ re-enabling the pin change interrupt using PCMSK register. Here is the corrected code, which seems to work fine:

    volatile bool MeasReceived=false;
    uint8_t inByte;

    ISR(PCINT2_vect){   //ISR for pin-change interrupts occuring at PD0-PD7

      PCMSK2 = 0b00000000;    // turn off PD0 interrupt
      MeasReceived=true;      //Set char received Flag

    }

    void setup() {

      Serial.begin(9600);
      Serial.flush();
      Serial.print("Hello PC");
      delay(1000);

      cli();
      PCICR = 0b00000100;    // turn on port d pin change interrupts
      PCMSK2 = 0b0000001;    // turn on pin PD0 , PCINT16
      sei();
    }

    void loop() {

      if(MeasReceived==true){  //If ISR fired
        MeasReceived=false;    //Reset the flag
        delay(1000);           //Wait a while for the character to be set. 1000ms may be too much
        inByte = Serial.read();  // Read the character that was sent

        if(inByte=='A'){   //If the character was A, write B to console
           Serial.print('B');
        }
        else{   //else, write the ASCII code of the character received
          Serial.print(inByte);
        }
        PCMSK2 = 0b00000001;   //re-enable PD0 interrupt
      }
    }


body:
Your diagnostic about the interrupt handled too fast is correct. When a
byte arrives at the serial port, the start bit will trigger the
interrupt, but the byte is only available for reading once the UART
receives the stop bit, which is about one millisecond later.

> to disable/re-enable the pin-change interrupt, the right way seems to
> be to use the PCMSK register and not the PCICR.

The canonical procedure for enabling _any_ edge-triggered interrupt is
to first clear the interrupt flag, then set the interrupt enable bit.
Note that the interrupt flag is cleared by writing a logic one to it.
For the PCINT2 interrupt that would be:

```cpp
PCIFR =  _BV(PCIF2);  // clear interrupt flag
PCICR |= _BV(PCIE2);  // enable interrupt
```

This being said, there is no point in using a pin change interrupt in
the first place. You can instead use the canonical idiom

```cpp
if (Serial.available() > 0) {
    char inByte = Serial.read();
    // ...
}
```

If you plan to sleep, you will likely want to do it with the serial port
enabled, in order for it not to miss the start bit. This means you will
use the IDLE sleep mode. Then, when the serial port receives a full
byte, it will wake up the CPU with its own interrupt, so you do not have
to take care of this yourself.

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

**Edit 1**: The simplest way to put the CPU to sleep until the next
interrupt is received is to call `sleep_mode()` at the end of `loop()`,
e.g.:

```cpp
// Sleep until the next character is received.
set_sleep_mode(SLEEP_MODE_IDLE);
if (!Serial.available()) {
    sleep_bod_disable();
    sleep_mode();
}
```

There is, however, a race condition here: if the interrupt fires after
you test `Serial.available()` but before going to sleep, you will sleep
instead of handling the received character. The solution to this problem
is to do the test with interrupts disabled and then enable them right
before issuing the `sleep` instruction, as explained in the
[documentation of the avr-libc][sleep]:

```cpp
set_sleep_mode(SLEEP_MODE_IDLE);
cli();
if (!Serial.available()) {
    sleep_enable();
    sleep_bod_disable();
    sei();
    sleep_cpu();
    sleep_disable();
}
sei();
```

[sleep]: https://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html

**Edit 2**: answering the questions in the comments.

1. Pin change interrupt allows you to sleep deeper than IDLE, but if you
do so, the UART will be stopped and it will miss the start bit, which
could throw off its timing. I would rather stick with IDLE and use the
`power_*_disable()` functions to turn off the unneeded peripherals.

2. I have a theory, though I don't know if it's valid. Look at [the
schematic of the PCINT detection][pcint]. If the clock is stopped, a
change in the pin level will make the XOR gate switch to 1, which
presumably wakes up the MCU, but that will not be recorded by the
downstream flip-flops, which rely on the clock. If the pin returns to
its original level before the clock restarts (which takes some time when
coming out of PWR\_DOWN), then the flip-flops never see the pin change
condition, and the interrupt flag does not rise.

[pcint]: http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf#G3.1805575

**Edit 3**: I made a test that confirms that, when waking up from
PWR\_DOWN by a pulse-triggered PCINT event, the ISR _does not run_ if
the pulse is too short. The setup involves two Arduinos:

 - the “tester” Arduino:
   - sends pulses of various lengths through digital 8 = PB0
   - forwards on TX the data received on RX
 - the “DUT” Arduino:
   - sleeps in PWR\_DOWN mode
   - wakes up by pin change interrupt on digital 8 = PB0 = PCINT0
   - reports whether the ISR ran on the serial port

The connections are:

    DUT   Tester    PC
    ───────────────────
            USB --- USB
    GND --- GND
    +5V --- +5V
      8 --- 8
     TX --- RX

The “tester” program:

```cpp
const uint32_t PULSE_PERIOD = 500;  // pulses every 500 ms

void setup() {
    DDRB |= _BV(PB0);  // digital 8 = PB0 as output
    Serial.begin(9600);
    Serial.println("Tester: ready");
}

void loop() {
    // Forward the serial communication.
    while (Serial.available())
        Serial.write(Serial.read());

    // Periodically send a pulse.
    static uint32_t last_pulse_time;
    if (millis() - last_pulse_time >= PULSE_PERIOD) {
        last_pulse_time += PULSE_PERIOD;

        // Send a pulse of 2^n microseconds.
        static uint8_t n = 0;
        uint16_t length = 1U << n;
        Serial.print("Tester: sending pulse of ");
        Serial.print(length);
        Serial.println(" us");
        Serial.flush();
        uint32_t now = millis();
        while (millis() == now) ;  // wait for the tick
        PORTB |= _BV(PB0);
        delayMicroseconds(length);
        PORTB &= ~_BV(PB0);

        // Next pulse size.
        if (++n >= 16) n = 0;
    }
}
```

The “DUT” program:

```cpp
#include <avr/sleep.h>

// The PCINT ISR only sets a flag.
volatile bool isr_ran;
ISR(PCINT0_vect) { isr_ran = true; }

void setup() {
    // Setup interrupt.
    PCMSK0 = _BV(PCINT0);  // sense PCINT0 = PB0
    PCIFR |= _BV(PCIF0);   // clear interrupt flag
    PCICR  = _BV(PCIE0);   // enable PCINT0 interrupt

    // Avoid other interrupts.
    TIMSK0 = 0;         // avoid timer interrupt
    PORTD |= _BV(PD0);  // pull RX high to prevent USART_RX interrupt
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);

    Serial.begin(9600);
    Serial.println("DUT: ready");
}

void loop() {
    loop_until_bit_is_clear(PINB, PB0);  // wait for LOW input
    Serial.println("DUT: going to sleep");
    Serial.flush();
    isr_ran = false;
    sleep_mode();
    Serial.print("DUT: woke up, ISR ran: ");
    Serial.println(isr_ran ? "YES" : "NO");
}
```

And the results:

    DUT: going to sleep
    Tester: sending pulse of 1 us
    DUT: woke up, ISR ran: NO
    DUT: going to sleep
    Tester: sending pulse of 2 us
    ...
    Tester: sending pulse of 1024 us
    DUT: woke up, ISR ran: NO
    DUT: going to sleep
    Tester: sending pulse of 2048 us
    DUT: woke up, ISR ran: YES
    DUT: going to sleep
    Tester: sending pulse of 4096 us
    DUT: woke up, ISR ran: YES
    ...

Conclusion: a pulse of 1024 µs or shorter wakes up the Arduino but
the ISR does not run. If the pulse is 2048 µs or longer, the ISR
does run.