message:
Adding another flow sensor to sketch

I have a water flow sketch I use for my freshwater consumption.  I would like to adapt it to use for diesel fuel consumption.  The difference is with a diesel motor the fuel pump sucks more fuel than it burns from the fuel tank and simply returns the excess to the fuel tank.  ie there are 2 hoses from the fuel tank, one to the motor, and one back to the tank.  The difference between what went to the motor and what went back to the tank is how much fuel the motor burned.

So my plan is to have 2 flow sensors (Yf-s201), and subtract the out put of one from the other and print the difference.

I have a sketch that already works to print L/m and total L.  For one sensor on PIN D2.
I have defined another sensor on PIN D3.

    byte sensorInterrupt = 0;  // 0 = digital pin 2
    byte sensorPin       = 2;

    byte sensorInterrupt2 = 1;  //11 = digital pin 3
    byte sensorPin2       = 3;

My first road block is to print them individually. as is they both just add to a single total.

I have tried to just copy bits of code and add a "2" but I really don't have any programing knowledge so I am just stabbing in the dark.   I don't understand how to call upon the value the code has calculated.

This is the whole sketch:

    /*
    Liquid flow rate sensor -DIYhacking.com Arvind Sanjeev

    Measure the liquid/water flow rate using this code.
    Connect Vcc and Gnd of sensor to arduino, and the
    signal line to arduino digital pin 2.

     */
    // include the library code:
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>

    LiquidCrystal_I2C lcd(0x27,20,4);

    byte statusLed    = 13;

    byte sensorInterrupt = 0;  // 0 = digital pin 2
    byte sensorPin       = 2;

    byte sensorInterrupt2 = 1;  // 1 = digital pin 3
    byte sensorPin2       = 3;

    // The hall-effect flow sensor outputs approximately 4.5 pulses per second per
    // litre/minute of flow.
    float calibrationFactor = 7.55;  //biger more / min

    volatile byte pulseCount;

    float flowRate;
    unsigned int flowMilliLitres;
    unsigned long totalMilliLitres;

    unsigned long oldTime;

    void setup()
    {

      // Initialize a serial connection for reporting values to the host
      Serial.begin(9600);
    lcd.init();
    lcd.backlight();
         lcd.begin(16, 2);
       lcd.clear();
       lcd.setCursor(0,0);
       lcd.print("S.V. SAVANNAH");
       lcd.setCursor(0,1);
       lcd.print("DAY TANK FLOW METER");

      // Set up the status LED line as an output
      pinMode(statusLed, OUTPUT);
      digitalWrite(statusLed, HIGH);  // We have an active-low LED attached

      pinMode(sensorPin, INPUT);
      digitalWrite(sensorPin, HIGH);

      pulseCount        = 0;
      flowRate          = 0.0;
      flowMilliLitres   = 0;
      totalMilliLitres  = 0;
      oldTime           = 0;

      // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
      // Configured to trigger on a FALLING state change (transition from HIGH
      // state to LOW state)
      attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
    }

    /**
     * Main program loop
     */
    void loop()
    {

       if((millis() - oldTime) > 1000)    // Only process counters once per second
      {
        // Disable the interrupt while calculating flow rate and sending the value to
        // the host
        detachInterrupt(sensorInterrupt);

        // Because this loop may not complete in exactly 1 second intervals we calculate
        // the number of milliseconds that have passed since the last execution and use
        // that to scale the output. We also apply the calibrationFactor to scale the output
        // based on the number of pulses per second per units of measure (litres/minute in
        // this case) coming from the sensor.
        flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;

        // Note the time this processing pass was executed. Note that because we've
        // disabled interrupts the millis() function won't actually be incrementing right
        // at this point, but it will still return the value it was set to just before
        // interrupts went away.
        oldTime = millis();

        // Divide the flow rate in litres/minute by 60 to determine how many litres have
        // passed through the sensor in this 1 second interval, then multiply by 1000 to
        // convert to millilitres.
        flowMilliLitres = (flowRate / 60) * 1000;

        // Add the millilitres passed in this second to the cumulative total
        totalMilliLitres += flowMilliLitres;

        unsigned int frac;

        // Print the flow rate for this second in litres / minute
        Serial.print("Flow rate: ");
        Serial.print(int(flowRate));  // Print the integer part of the variable
        Serial.print("L/min");
        Serial.print("\t");       // Print tab space

        // Print the cumulative total of litres flowed since starting
        Serial.print("Output Liquid Quantity: ");
        Serial.print(totalMilliLitres);
        Serial.println("mL");
        Serial.print("\t");       // Print tab space
      Serial.print(totalMilliLitres/1000);
      Serial.print("L");

          lcd.clear();
          lcd.setCursor(4,0);
          lcd.print(int(flowRate));  // Print the integer part of the variable
          lcd.print("L/min ");

        // Print the cumulative total of litres flowed since starting
        lcd.setCursor(2,1);
        lcd.print("Total ");
      lcd.print(totalMilliLitres/1000.00);
      lcd.print("L");

        // Reset the pulse counter so we can start incrementing again
        pulseCount = 0;

        // Enable the interrupt again now that we've finished sending output
        attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
      }
    }

    /*
    Insterrupt Service Routine
     */
    void pulseCounter()
    {
      // Increment the pulse counter
      pulseCount++;
    }'''

body:
Your code currently does not use the second flow sensor. I guess you have problems in designing the code, so I try to walk you trough.

First let's look at the prerequisites, that are needed for the two flow sensors. You already have defined the pins of the flow sensors. You are also defining the number of the corresponding interrupts. In fact you don't have to do that. You can easily get the number of the interrupt through the function `digitalPinToInterrupt(pin)`. So we are left with the pin definition. I would suggest using clearer names:

    int flow_out_pin = 2;
    int flow_in_pin = 3;

`flow_out` meaning leaving the tank, `flow_in` coming back into the tank.

Then in `setup()` we need to initiate the pins. You have this

    pinMode(sensorPin, INPUT);
    digitalWrite(sensorPin, HIGH);

This can be then made shorter in one line per sensor:

    pinMode(flow_out_pin, INPUT_PULLUP);
    pinMode(flow_in_pin, INPUT_PULLUP);

Now we attach the interrupts to the pins:

    attachInterrupt(digitalPinToInterrupt(flow_out_pin), flowOutPulseCounter, FALLING);
    attachInterrupt(digitalPinToInterrupt(flow_in_pin), flowInPulseCounter, FALLING);

I used the mentioned function to get the interrupt number and changed the name of the ISR. Here comes a different principle, than your firstly intended way: I would let the sensors count in their own ISR and own variables and only calculate the difference to display it. For that we need to define our 2 ISRs:

    void flowOutPulseCounter()
    {
        flowOutPulseCount++;
    }
    void flowInPulseCounter()
    {
        flowInPulseCount++;
    }

The count variables of course need to be defined (globally at the top of the sketch):

    volatile byte flowOutPulseCount = 0;
    volatile byte flowInPulseCount = 0;

Now we have left the code in `loop()`, which calculates flowrate, fill level and such and displays them. First: When handling interrupt data in the main code, you want to absolutely minimize the time spend with the interrupts deactivated (since in that time you might miss pulses and thus introduce errors). Normally you would just copy the data into local variables, turn on the interrupts again and do the calculation with the local variables. Something like this (inside the `millis()` if statement):

    // Detach interrupts
    detachInterrupt(digitalPinToInterrupt(flow_out_pin));
    detachInterrupt(digitalPinToInterrupt(flow_in_pin));

    // copy pulse count variables
    byte local_flow_out_count = flowOutPulseCount;
    byte local_flow_in_count  = flowInPulseCount;

    // reset pulse counter variables
    flowOutPulseCount = 0;
    flowInPulseCount = 0;

    // Reattach interrupts
    attachInterrupt(digitalPinToInterrupt(flow_out_pin), flowOutPulseCounter, FALLING);
    attachInterrupt(digitalPinToInterrupt(flow_in_pin), flowInPulseCounter, FALLING);

    // Do calculations using above local variables and display the results
    ...

For the calculations you would then calculate a flow rate and the total flow from each pulse count. With that you can then calculate the total net flow and the fill level.

Note: You might wanna change the variable type for the counters to `unsigned int` to get a greater margin, before they overflow, since that would mean incorrect results and it doesn't hurt you to use it.


sender: user

sender: assistant

body:
As chrisl already provided a very good answer, I am just adding some
notes here to complement it.

The variable `pulseCount` is only 8-bits. It will overflow if the flow
rate gets above 33.7 L/min. If the possibility exists that the
actual flow exceeds this rate, then, as pointed out in chrisl's answer,
you should use a 16-bit counter. If, on the other hand, you are sure
that this value cannot be exceeded, then you can keep an 8-bit counter,
and benefit from the fact that accesses to 8-bit values are _atomic_.
This means you do not need to ever disable interrupts:

```c++
// In global scope:
byte oldPulseCount;

// Within loop(), once per second:
byte newPulseCount = pulseCount;  // atomic read
byte pulseCountDifference = newPulseCount - oldPulseCount;
oldPulseCount = newPulseCount;  // save current value
```

then you compute the flow rate from `pulseCountDifference`. Note that
overflows of `pulseCount` are harmless, as the difference
`newPulseCount - oldPulseCount` wraps modulo 256 to the correct value.
Note also that `pulseCount` is never reset, as doing so could lead to
miscounting whenever an interrupt fires after `pulseCount` is read but
before it is reset.

> ```c++
> // Note the time this processing pass was executed. Note that because
> // we've disabled interrupts the millis() function won't actually be
> // incrementing right at this point, but it will still return the value
> // it was set to just before interrupts went away.
> oldTime = millis();
> ```

This comment is wrong. The statement `detachInterrupt(sensorInterrupt)`
disables _only_ an external interrupt. It does not disable interrupts
globally, and specifically does not disable the timer interrupt that
increments `millis()`. There is therefore no guarantee that the various
calls to `millis()` will return the same value within one iteration.
Instead, `millis()` should be called only once, and its value
remembered:

```c++
void loop()
{
    unsigned long now = millis();  // save this value
    if (now - oldTime >= 1000) {
        // ...
        oldTime = now;
    }
}
```

Note that I use `>=` for checking the delay: with the `>` operator the
period is at least 1001 ms.

> ```c++
> flowMilliLitres = (flowRate / 60) * 1000;
> ```

This is incorrect. It should be

```c++
flowMilliLitres = (flowRate / 60) * (now - oldTime);
```

for the same reason that `now - oldTime` is used in the computation of
`flowRate`. It may be noted that this can be simplified to

```c++
flowMilliLitres = (1e3/calibrationFactor/60) * pulseCountDifference;
```

as the factors `now - oldTime` cancel out.


message:
Where is the documentation for writing an Arduino core?

I'm interested in writing an "Arduino core" (i. e. porting Arduino to a new MCU and new board(s)).  I'm having trouble finding much documentation on how to do so.  Am I missing something?

[This page](https://www.arduino.cc/en/guide/cores) says "anyone may develop a core for their own boards following the rules and requirements we have issued."  So, where are those "rules and requirements?"

I found something called the "[Platform Specification](https://arduino.github.io/arduino-cli/latest/platform-specification/)", which sounded promising, but it only documents the config files; it does not say anything about the code that needs to be written to support a new platform.

I found [ArduinoCore-API](https://github.com/arduino/ArduinoCore-API), which says it is the "hardware independent layer of Arduino core."  But it doesn't mention anything about how to write the hardware-dependent part of the core.

I'd be grateful if anyone could point me to the Arduino core documentation.  It's not turning up in my web searches.  Thanks!

**Clarifications:**

* Yes, I can look at existing cores as examples, but I'd rather have the documentation, as well.  Especially since existing cores may be of varying quality, or may not be up to the latest standard.  Documentation is always a good thing.
* The reason I want to write a core is because... I want to use an MCU which is not currently supported!  (Specifically, I want to add support for the [GD32F350](https://www.gigadevice.com/microcontroller/gd32f350cbt6/), but really that shouldn't be relevant to answering "Where is the documentation?")

body:
There are two major parts to writing an Arduino core: the hardware independent portions and the hardware dependent.

The hardware independent portions are pretty much done for you in the ArduinoCore-API. However I wouldn't just use that verbatim but use it as a starting point and adapt it to your needs. This is because it actually has a couple of unresolved issues and not everything may 100% fit your needs. We don't use it for the chipKIT core because:

* It has an unresolved issue around the naming of the `String.h` file which conflicts with the libc's `string.h` on case insensitive filesystems
* Our USB stack is vastly different to how the Arduino "Pluggable USB" works
* We have extra facilities in a number of standard objects to make use of more efficient use of more advanced hardware

Once you have the hardware independent portion sorted you need to write, from scratch, the hardware dependent portion.  The basic list of functions you *need* to implement are listed in the [Arduino reference](https://www.arduino.cc/reference/en/). How you write them cannot be documented, since that depends on the hardware. And you may well need to (or want to) write considerably more functions that just those. For example on chipKIT as well as the standard `analogWrite()` function we also have functions to change the PWM frequency and resolution - things that aren't part of the "standard", but are incredibly useful.

A good starting point is to examine the Arduino.h file of an existing core (the AVR core is a good baseline) which will list most of the functions and their parameter/return types. That gives you what the functions expect to receive and what they should emit, but *how* those functions are written is completely down to you.

And then of course you have to implement the boards variants etc to make the whole things work...

Also, be warned that writing (and maintaining) a core is a long and involved process and will consume the rest of your life.


message:
Can't read data from registers using I2C

I am trying to read data from the registers 6, 7, 8 and 9 of the STC3100 ([Data Sheet][1]) using an arduino uno.

I followed this tutorial: https://howtomechatronics.com/tutorials/arduino/how-i2c-communication-works-and-how-to-use-it-with-arduino/ And adjusted the device and register adress accordingly.

This isn't working and instead of returning the data on the register I'm just getting 16 over and over again.

Here is my code:

```
#include <Wire.h>
int ADXLAddress = 0x70;

#define X_Axis_Register_DATAX0 0x08

#define X_Axis_Register_DATAX1 0x09

#define Power_Register 0x00

int X0,X1,X_out;

void setup() {

  Wire.begin();

  Serial.begin(9600);
  delay(100);
  Wire.beginTransmission(ADXLAddress);
  Wire.write(Power_Register);
  Wire.write(16);
  Wire.endTransmission();
}
void loop() {
  delay(2000);
  Wire.beginTransmission(ADXLAddress);

  Wire.write(X_Axis_Register_DATAX0);
  Wire.write(X_Axis_Register_DATAX1);

  Wire.endTransmission();

  Wire.requestFrom(ADXLAddress,2);

  if(Wire.available()<=2) {
    X0 = Wire.read();
    X1 = Wire.read();
  }

  Serial.print("X0= ");
  Serial.print(X0, BIN);
  Serial.print("   X1= ");
  Serial.println(X1, BIN);
}
```

  [1]: https://www.st.com/resource/en/datasheet/stc3100.pdf

body:
The following code shows, how I would read from a STC3100. But I own none of them, so I can not try the code. I would be very surprised if it works directly. Use it as an example. Perhaps we could improve it together. ;-)

    #include <Wire.h>

    #define STC_ADDRESS 0x70
    #define MODE_REGISTER 0x00
    #define CURRENT_LOW_REGISTER 0x06
    #define VOLTAGE_LOW_REGISTER 0x08

    int voltage, current;
    int high_value = 0;

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

      Wire.begin();
      delay(100);
      // power on the STC
      Wire.beginTransmission(STC_ADDRESS);
      Wire.write(MODE_REGISTER);
      Wire.write(16);
      Wire.endTransmission();
    }

    void loop()
    {
      Wire.beginTransmission(STC_ADDRESS);
      Wire.write(VOLTAGE_LOW_REGISTER);
      Wire.requestFrom(STC_ADDRESS, 2);
      delay(500);
      if( Wire.available() > 0 )
      {
        voltage = Wire.read();
        //Serial.print("REG 8 = ");
        //Serial.println(voltage);
      }
      delay(500);
      if( Wire.available() > 0 )
      {
        high_value = Wire.read();
        //Serial.print("REG 9 = ");
        //Serial.println(high_value);
        voltage += (high_value << 8);
        //Serial.print("voltage = ");
        //Serial.println(voltage);

      }
      Wire.endTransmission();

      Wire.beginTransmission(STC_ADDRESS);
      Wire.write(CURRENT_LOW_REGISTER);
      Wire.requestFrom(STC_ADDRESS, 2);
      delay(500);
      if( Wire.available() > 0 )
      {
        current = Wire.read();
        //Serial.print("REG 6 = ");
        //Serial.println(current);
      }
      delay(500);
      if( Wire.available() > 0 )
      {
        high_value = Wire.read();
        //Serial.print("REG 7 = ");
        //Serial.println(high_value);
        current += (high_value << 8);
        //Serial.print("current = ");
        //Serial.println(current);
      }
      Wire.endTransmission();

      Serial.print("V= ");
      Serial.print(voltage);
      Serial.print("   C= ");
      Serial.println(current);
    }


message:
Interfacing SPI (MCP3903)

I'm trying to interface MCP3903. I haven't really don't any SPI interfacing before and I can't seem to find clear enough answer for newbs. Please bare with me.

I'm trying to use this library. http://www.kerrywong.com/2014/05/10/mcp3903-library/

On the website there is the following circuit diagram.

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

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

I can see SDI, SDO pins on the ESP module, how do I connect the SCK and CS pins? If they can be any pins how do I declare them on the test program on the website?

Thank you

body:
SPI0 and SPI1 are used internally to access the ESP32’s attached flash memory. SPI2 and SPI3 are general purpose SPI controllers, sometimes referred to as HSPI and VSPI, respectively. They are open to users.

A quick google search shows:

[![ESP32 Wroom Pinout][1]][1]

So you can use IO5, IO18, IO19 and IO23.

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


message:
Stm32 Blue Pill Internal reference voltage Arduino IDE

I want to use the internal reference voltage (1.2V) of stm32f103 blue pill using Arduino IDE. I searched the whole internet but couldn't find anything. I need help with this. Thanks.

body:
There's no way of using the internal 1,2v reference as the ADC reference. (in the same way that you can do on an AVR)
You can only use the ADC to read the internal vref, and use that value to adjust the next ADC reading you take. Like a compensation factor.


message:
Programmatically-adjustable buck converter module?

LM2596 is easy to use and cheap, but I have to adjust the output voltage using a screw driver. On the web, there was a "hack" that someone posted, but that hack does not seem as clean or stable as using LM2596 as it is intended to be used, using screw driver. Is there something that is easy-to-use just like LM2596, but has some pins that can be used to dynamically adjust the output voltage using an Arduino?

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

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

body:
The hack you described is most likely just feeding voltage from filtered PWM signal generated by microcontroller to the feedback loop of LM2596. I think you can get good enough noise performance with this approach if voltage change rate is not a concern. It all comes down to the PWM filter parameters. You can decrease noise by adjusting RC filter parameters (increasing capacitor and resistor values). It will cause increased delay in voltage change, but it will reduce the noise from PWM signal. Also, you can increase the PWM frequency by avoiding standard analogWrite which has pretty low frequency and configuring a separate timer for PWM generation.
Alternatively, if you need some specific voltages, you can replace the potentiometer with a fixed value resistor array connected in parallel and connect each resistor though separate low power MOSFET. This way, you can connect and disconnect a specific resistor which will change the total resistance of the array, changing the output voltage. It will only allow changing voltage by steps and the step size is dictated by the number of resistors, but the noise performance will be the same as using a potentiometer.


message:
How to declare char array[] using integers?

Can anyone please tell me how to declare a char variable using a few integers?

I need to declare a byte information for `shiftOut()` function as char.

```
int a = 0;
int b = 1;
int c = 0;
int d = 1;
int e = 1;
int f = 0;
int e = 0;
int f = 1;

char information[] = {"B" + a + b + c + d + e + f};

void setup() {
  Serial.println(information);
}

void loop() {
  shiftOut(pin, pin, MSBFIRST, information);
}
```

In command `Serial.println(information);` I want to get back `B01011001`

Now the output I am getting `⸮⸮`

Of course the simpliest way to create that will be:

`char information[] = "B01011001";`

But I need to change the individual bits in `int bit =` variable.

Please note that substition `int bit =` with `char bit =` is unable for my code, using int of value of individual bits is necessarily. Because I am using my project with blynk, and there is function `a = param.asInt();` ,  `param.asChar();` does not exist.

How to do that?

Thank you for responses!

body:
I think you are getting something wrong about `shiftOut()`. It will transfer exactly 1 byte (or 1 `char`). It does not take an array as parameter. I guess you want to write the 8 bits, that you are defining with your `int`s, as one byte out. Defining at byte directly would look like this:

    byte information = 0b00101100;

The `0b` tells the compiler, that the following number is encoded in binary. So you have one single byte, that contains all your information (all the bits). Then you can do

    shiftOut(data_pin, clock_pin, MSBFIRST, information);

(Please note, that the data_pin and the clock pin need to be different).

If you want to print the `information` variable to Serial, showing the binary representation, you can use the corresponding parameter of the `print()` function.

    Serial.print(information, BIN);

Will print the binary representation (zeros and ones as text) of the variable. So, to get "B1011001", you would do:

    Serial.print("B");
    Serial.println(information, BIN);

Note, that the `print()`/`println()` function will remove all leading zeros.

---

How to put the `information` byte with your `int`s? Each of them is either zero or one and represents one bit. So you can use the bitwise operators to put them together:

    information = (a << 7) | (b << 6) | (c << 5) | (d << 4) | (e << 3) | (f << 2) | (g << 1) | h;

For each `int` only the first (Least significant) bit is important, since the others are always zero (because the int can be only one or zero). So we shift the `int` value to the left by the number of the corresponding bit minus 1 (so shifting `a` 7 places to the left to put its least significant bit to the most significant bit of `information`. We are doing that for all our `int` values. Then we put them all together into one byte by using the `|` (bitwise OR) operator.

**Note:** We don't know, where these `int`s are coming from. Even when stating, that you absolutely need those `int`s, you could organize them in an array instead of single variables. That would look like this:

    int int_data[8] = {0, 0, 1, 0, 1, 1, 0, 0};
    ...
    // in a function (like loop() or setup())
    byte information = 0;
    for(int i=0;i<8;i++) information |= int_data[7-i] << i;

It's up to you, if you want to do that.


message:
Help On Creating Derived classes in Headers

Here's a small problem I encountered while I was trying to make this small header file `Devices.h`:
 >Is it possible to use templates with abstract classes ? If yes, how and how can I use that abstract class to derive another class ?

Here's the contents of the header file :
```
#ifndef Devices_h
#define Devices_h

/* Initial build for MCUOS
Anybody can edit this according to their device needs */

#include "Arduino.h"

template < typename datatype>

class Device_Handler
{
    // a class to handle devices
 public:
  virtual void write_to_device(datatype *send_data)= 0; // write data to device
  virtual void read_from_device(datatype *store_location)= 0 ; // read data from device to location
  virtual void clear_device() = 0; // clear device state
};

class Serial_Handler:public Device_Handler<char*>
{
   public:
          void write_to_device(char *send_data);
          void read_from_device(char *store_location);
          void clear_device();
};

void Serial_Handler<char*>::write_to_device(char *send_data){
        Serial.println(*send_data);
 }

void Serial_Handler<char*>::read_from_device(char *store_location){
       *store_location = Serial.read();
}

void Serial_Handler::clear_device(){
        Serial.flush();
}

#endif
```

This is a small project I am trying at home nowadays (that MCUOS thing up there), also considering it a learning opportunity. I am not sure if I wrote the code in the header the right way. Initially, I made the `Device_Handler` class and used it in my sketch to craft the `Serial_Handler` class, but then it showed an error that the compiler expected a class name before the '{' character right at the place where I started writing the code for the derived class. Thus I decided to move the code for the derived class to the header, but I decided to seek your advice before heading further as I fear that more errors may come up and as I am kind of a beginner at C++.

Thanks in advance !

EDIT : I also doubt if it was because I wrote a comment near the starting line of the abstract class as the syntax highlighter here showed the comments in colour.

**Edit**: I resolved the issue up there (it was due to the misplaced comment), but a new issue has popped up saying that it expected an initialiser before the '<' token at the places where I had defined the functions in the derived class. This is where my actual is.

My snippets of main concern:
```
void Serial_Handler<char>::write_to_device(char *send_data){
        Serial.println(*send_data);
 }

void Serial_Handler<char*>::read_from_device(char *store_location){
       *store_location = Serial.read();
}
```

I doubt if these will be able to handle long sentences or have syntax errors.

**Edit**
I decided to move forward despite errors. Here's how I remade my header file:

```
#ifndef Devices_h
#define Devices_h

/* Initial build for MCUOS
Anybody can edit this according to their device needs */

#include "Arduino.h"

template < typename datatype>
class Device_Handler
{
               // a class to handle devices
 public:
  virtual void write_to_device(datatype *send_data)= 0; // write data to device
  virtual void read_from_device(datatype *store_location)= 0 ; // read data from device to location
  virtual void clear_device() = 0; // clear device state
};

class Serial_Handler:public Device_Handler<char*>
{
   public:
          void write_to_device(char *send_data);
          void read_from_device(char *store_location);
          void clear_device();
};

void Serial_Handler::write_to_device(char *send_data){
        Serial.println(*send_data);
 }

void Serial_Handler::read_from_device(char *store_location){
       *store_location = Serial.read();
}

void  Serial_Handler::clear_device(){
        Serial.flush();
}

#endif
```

Here's the sketch code:
```
#include <Devices.h>

Serial_Handler myserial;
char storage = '\0';
char test_string[] = "Hello";

void setup() {
  Serial.begin(9600);
  myserial.write_to_device(test_string);
  myserial.read_from_device(&storage);
}

void loop() {
  // put your main code here, to run repeatedly:

}
```
(I know that the code up there may also be faulty)
and errors come up:
```
Arduino: 1.8.13 (Windows 10), Board: "Arduino Uno"
Devices_Test:3:16: error: cannot declare variable 'myserial' to be of abstract type 'Serial_Handler'

 Serial_Handler myserial;

                ^~~~~~~~

In file included from C:\Users\<smbdy>\Documents\Arduino\Devices_Test\Devices_Test.ino:1:0:

C:\Users\<smbdy>\Documents\Arduino\libraries\Devices/Devices.h:19:7: note:   because the following virtual functions are pure within 'Serial_Handler':

 class Serial_Handler:public Device_Handler<char*>

       ^~~~~~~~~~~~~~

C:\Users\<smbdy>\Documents\Arduino\libraries\Devices/Devices.h:14:16: note:  void Device_Handler<datatype>::write_to_device(datatype*) [with datatype = char*]

   virtual void write_to_device(datatype *send_data)= 0; // write data to device

                ^~~~~~~~~~~~~~~

C:\Users\<smbdy>\Documents\Arduino\libraries\Devices/Devices.h:15:16: note:  void Device_Handler<datatype>::read_from_device(datatype*) [with datatype = char*]

   virtual void read_from_device(datatype *store_location)= 0 ; // read data from device to location

                ^~~~~~~~~~~~~~~~

exit status 1

cannot declare variable 'myserial' to be of abstract type 'Serial_Handler'

```

How should I resolve this?

body:
You are on the track, but it needs some adjustments:

    template < typename datatype>
    class Device_Handler
    {
        // a class to handle devices
        public:
            virtual void write_to_device(datatype *send_data)= 0; // write data to device
            virtual void read_from_device(datatype *store_location)= 0 ; // read data from device to location
            virtual void clear_device() = 0; // clear device state
    };

    class Serial_Handler:public Device_Handler<char> // instead of char*
    {
       public:
           void write_to_device(char *send_data) override;
           void read_from_device(char *store_location) override;
           void clear_device() override;
    };

    void Serial_Handler::write_to_device(char *send_data){ // It's not template, so no template specialization
            Serial.println(*send_data);
     }

    void Serial_Handler::read_from_device(char *store_location){
           *store_location = Serial.read();
    }

    void Serial_Handler::clear_device(){
            Serial.flush();
    }

The alternative is:

    template < typename datatype>
    class Device_Handler
    {
        // a class to handle devices
        public:
            virtual void write_to_device(datatype send_data)= 0; // write data to device
            virtual void read_from_device(datatype store_location)= 0 ; // read data from device to location
            virtual void clear_device() = 0; // clear device state
    };

    class Serial_Handler:public Device_Handler<char*>
    {
       public:
           void write_to_device(char *send_data) override;
           void read_from_device(char *store_location) override;
           void clear_device() override;
    };


message:
How do I pause a loop just once?

I´m trying to make a pause in a loop, but just for the first time it loops. The next loops i would like the program to NOT do the pause. Just once time, each time a button is pressed. Does anybody knows how to do it?
Thanks!
This is the code i want to pause just once:

    void loop() {
      if(digitalRead(switch_pin) == LOW){
        digitalWrite(led_green_pin,LOW);
        digitalWrite(led_red_pin,HIGH);
        lastMotionState    = currentMotionState;
        currentMotionState = digitalRead(MOTION_SENSOR_PIN); //
          if (currentMotionState == LOW && lastMotionState == HIGH) {
          servo.write(90);
          }
          else
          if (currentMotionState == HIGH && lastMotionState == LOW) { // pin state change: HIGH -> LOW
          servo.write(0);
          }
      }

body:
The following code will pause (Give some delay) when it runs for the first time and also when you press the button.

```

void loop() {
  static int status = true;
  if(status){
    //Pause
    delay(15);
    status=false;
    return;
  }

  if(digitalRead(switch_pin) == LOW){
    digitalWrite(led_green_pin,LOW);
    digitalWrite(led_red_pin,HIGH);
    lastMotionState    = currentMotionState;
    currentMotionState = digitalRead(MOTION_SENSOR_PIN); //
      if (currentMotionState == LOW && lastMotionState == HIGH) {
       servo.write(90);
      }
      else if (currentMotionState == HIGH && lastMotionState == LOW) { // pin state change: HIGH -> LOW
       servo.write(0);
      }
  }
  else{
    status = true;
  }
}
```

Give delay according to your need.


body:
This is pretty simple, although you shouldn't see any difference, because `loop()` is running a lots of times in one second. But:

```cpp
bool firstrun = true;
void loop() {
  if(firstrun == true){};
  else{
    if(digitalRead(switch_pin) == LOW){
      digitalWrite(led_green_pin,LOW);
      digitalWrite(led_red_pin,HIGH);
      lastMotionState    = currentMotionState;
      currentMotionState = digitalRead(MOTION_SENSOR_PIN); //
        if (currentMotionState == LOW && lastMotionState == HIGH) {
          servo.write(90);
        }
        else if (currentMotionState == HIGH && lastMotionState == LOW) { // pin state change: HIGH -> LOW
          servo.write(0);
        }
    }
  }
  firstrun = false;
}
```


message:
How to use float data from a sensor with the Arduino mouse library

I'm using a gyroscope, which returns angular velocity in floats. I'm trying to use this data with the [arduino mouse library][1]. The move function requires a signed character. I'm not what the best way is to convert the `float` data from the sensor into `signed char`.

In what way can I do this, losing the least in terms of precision?

I found out you can use `dtostrf` to transfer floats into an array of characters, but not sure what to do following this or if it's even the best way.

I would appreciate any guidance.

  [1]: https://www.arduino.cc/reference/en/language/functions/usb/mouse/

body:
The mouse library expects the movement coordinates to be provided as
8-bit signed integers, which corresponds to the `int8_t` data type. This
type is actually an alias to `signed char`, but calling it this way is
confusing, as the word `char` somehow implies a type meant to store
characters, which is definitely not the case here.

Converting a `float` to any integer type can be done by plain
assignment, with two caveats:

* If the float exceeds the range of the integer, the assignment will
  wrap around modulo 2^(integer size in bits). This is undesirable and
  can be prevented by first `constrain()`ing the float to the
  appropriate range.
* The assignment rounds towards zero, whereas rounding to the nearest
  integer is better if you want to minimize the errors. This can be
  achieved with the `round()` macro.

In summary:

```c++
// In global context:
const float scale = 0.4;  // scale factor for mouse moves

// Within loop():
float rotation = get_data_from_gyroscope();
int8_t mouse_move = round(constrain(rotation * scale, -128, +127));
```

Note that the optimal scale can only be determined experimentally: you
have to tweak it until your input device “feels” right.


body:
You are misunderstanding the type `char`. It is named character, because in ASCII representation you can use it to save one character. But internally it just is a number. The Arduino doesn't care, if you save characters in it or numbers, because characters are also numbers for it.

A `signed char`, like the `move()` function of the library uses` has 1 byte and is signed, thus can hold numbers from -128 to 127.

While the documentation is not clear about what the x and y parameters really represent the answer to [this question][1] is clear about it. Basically the whole range from -128 to +127 represents a whole inch (or what the computer thinks is an inch). So this results in a resolution of `1" / (127 - -128) = 1" / 255 = 0.0039"` (or about 0.1mm). I don't know, what values you are getting from the sensor, but you will have to scale it to somewhere in the -128 to 127 range (depends on how sensitive you want it to be). And you won't loose precision here. The sensor values most likely are more precise, than the range of the mouse `move()` function.

The calculation will then be as simple as

    signed char mouse_x = sensor_x * factor + offset;

The result of the calculation will implicitly converted to a 1 byte signed integer (this is what `signed char` is). If you want to make it clearer what happens here, you can also write:

    signed char mouse_x = (signed char)(sensor_x * factor + offset);

This is not needed, but you might wanna do it for clarity.

---

Seen in Edgar Bonets answer: You might wanna contrain the value of above calculation to the -128 to 127 range. If you get an unexpected high value from your sensor, the above calculation would overflow the `mouse_x` variable (not good for correct values). So capping the values to that range with the `constrain()` function is definitely good. Refer to Edgars answer and the documentation for this.

  [1]: https://arduino.stackexchange.com/questions/74757/mouse-move-values


message:
ESP32 FREERTOS crash using Adafruit ST7789 in tasks with the Wifi enabled

I am trying to create a clock using a ST7789 display and a DS3231 RTC. In this clock I want to use NTP to keep it synced and maybe use the WiFi to anything else.
My problem started when I have tried to use tasks to split the code into pieces, manage priorities and to keep the loop code as clean as possible. When I try to update the display text from a task the ESP32 just crash and reboots.
I have cleaned the code to see where is the problem and I have noticed that the problem comes when I connect to my Router and then I try to update the text in the display, but doesn't fail if the WiFi is not started or I update the text outside the task. The cleaned code I am using is this:

```
#include <WiFi.h>
#include <Adafruit_ST7789.h>

#if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE_0 0
#define ARDUINO_RUNNING_CORE_1 0
#else
#define ARDUINO_RUNNING_CORE_0 0
#define ARDUINO_RUNNING_CORE_1 1
#endif

#define TFT_MOSI 23  // SDA Pin on ESP32
#define TFT_SCLK 18  // SCL Pin on ESP32
#define TFT_CS   15  // Chip select control pin
#define TFT_DC    2  // Data Command control pin
#define TFT_RST   4  // Reset pin (could connect to RST pin)

// Colors
#define COLOR_TOP_BG tft.color565(125, 125, 125)
#define COLOR_TL_BG tft.color565(3, 96, 7)
#define COLOR_BL_BG tft.color565(3, 96, 7)
#define COLOR_TR_BG tft.color565(117, 70, 2)
#define COLOR_BR_BG tft.color565(117, 109, 2)

#define COLOR_TOP_TEXT ST77XX_WHITE
#define COLOR_TL_TEXT ST77XX_BLACK
#define COLOR_TL_TEXT ST77XX_BLACK
#define COLOR_TL_TEXT ST77XX_BLACK
#define COLOR_TL_TEXT ST77XX_BLACK

static const char* ssid     = "WIFI_SSID";
static const char* password = "**REDACTED**";

// Initialize Adafruit ST7789 TFT library
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

// the setup function runs once when you press reset or power the board
void setup() {

  // initialize serial communication at 115200 bits per second:
  Serial.begin(115200);

  // Now set up two tasks to run independently.
  xTaskCreate(
    updateDateTime,
    "updateDateTime",   // A name just for humans
    1024,  // This stack size can be checked & adjusted by reading the Stack Highwater
    NULL,
    3,  // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
    NULL
  );

  // Connecting to Wifi
   WiFi.begin(ssid, password);

  tft.init(240, 240, SPI_MODE2);    // Init ST7789 display 135x240 pixel
  tft.setRotation(3);
  drawBackground();
}

void loop() {

}

// Function to draw the display background
void drawBackground() {
  tft.fillScreen(0xFFFFFF);
  tft.fillRect(0, 0, 240, 24, COLOR_TOP_BG);
  tft.fillRect(0, 24, 120, 107, COLOR_TL_BG);
  tft.fillRect(0, 133, 120, 107, COLOR_BL_BG);
  tft.fillRect(120, 24, 120, 107, COLOR_TR_BG);
  tft.fillRect(120, 133, 120, 107, COLOR_BR_BG);

  tft.fillRect(0, 22, 240, 4, ST77XX_BLACK);
  tft.fillRect(0, 130, 240, 3, ST77XX_BLACK);
  tft.fillRect(118, 22, 4, 218, ST77XX_BLACK);
}

// Function to update the date/time
void updateDateTime( void * pvParameters ) {
  for( ;; ) {
    //tft.init(240, 240, SPI_MODE2);
    tft.setTextColor(COLOR_TOP_TEXT, COLOR_TOP_BG);
    tft.setCursor(6, 4);
    tft.println("MIE");

    delay(100);
  }
}
```

If I comment the WiFi.begin function or I call the function from loop without create a task or just move the three lines to loop function, it works perfectly.

```
#include <WiFi.h>
#include <Adafruit_ST7789.h>

#if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE_0 0
#define ARDUINO_RUNNING_CORE_1 0
#else
#define ARDUINO_RUNNING_CORE_0 0
#define ARDUINO_RUNNING_CORE_1 1
#endif

#define TFT_MOSI 23  // SDA Pin on ESP32
#define TFT_SCLK 18  // SCL Pin on ESP32
#define TFT_CS   15  // Chip select control pin
#define TFT_DC    2  // Data Command control pin
#define TFT_RST   4  // Reset pin (could connect to RST pin)

// Colors
#define COLOR_TOP_BG tft.color565(125, 125, 125)
#define COLOR_TL_BG tft.color565(3, 96, 7)
#define COLOR_BL_BG tft.color565(3, 96, 7)
#define COLOR_TR_BG tft.color565(117, 70, 2)
#define COLOR_BR_BG tft.color565(117, 109, 2)

#define COLOR_TOP_TEXT ST77XX_WHITE
#define COLOR_TL_TEXT ST77XX_BLACK
#define COLOR_TL_TEXT ST77XX_BLACK
#define COLOR_TL_TEXT ST77XX_BLACK
#define COLOR_TL_TEXT ST77XX_BLACK

static const char* ssid     = "WIFI_SSID";
static const char* password = "**REDACTED**";

// Initialize Adafruit ST7789 TFT library
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

// the setup function runs once when you press reset or power the board
void setup() {

  // initialize serial communication at 115200 bits per second:
  Serial.begin(115200);

  // Connecting to Wifi
   WiFi.begin(ssid, password);

  tft.init(240, 240, SPI_MODE2);    // Init ST7789 display 135x240 pixel
  tft.setRotation(3);
  drawBackground();
}

void loop() {
  void * test;
  updateDateTime(test);
}

// Function to draw the display background
void drawBackground() {
  tft.fillScreen(0xFFFFFF);
  tft.fillRect(0, 0, 240, 24, COLOR_TOP_BG);
  tft.fillRect(0, 24, 120, 107, COLOR_TL_BG);
  tft.fillRect(0, 133, 120, 107, COLOR_BL_BG);
  tft.fillRect(120, 24, 120, 107, COLOR_TR_BG);
  tft.fillRect(120, 133, 120, 107, COLOR_BR_BG);

  tft.fillRect(0, 22, 240, 4, ST77XX_BLACK);
  tft.fillRect(0, 130, 240, 3, ST77XX_BLACK);
  tft.fillRect(118, 22, 4, 218, ST77XX_BLACK);
}

// Function to update the date/time
void updateDateTime( void * pvParameters ) {
  for( ;; ) {
    //tft.init(240, 240, SPI_MODE2);
    tft.setTextColor(COLOR_TOP_TEXT, COLOR_TOP_BG);
    tft.setCursor(6, 4);
    tft.println("MIE");

    delay(100);
  }
}
```

I am starting with FREERTOS and ESP32, and I am not sure what I am doing wrong... I have thougth that the problem was the RTC but after remove the RTC code and see that was the WiFi, I am not sure what can be the problem.

Best regards and thanks.

body:
To pin the function to a core was not working for me surely because the init code is outside the function, so I have moved the init code to inside the function, out of the loop:

```
#include <WiFi.h>
#include <Adafruit_ST7789.h>

#if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE_0 0
#define ARDUINO_RUNNING_CORE_1 0
#else
#define ARDUINO_RUNNING_CORE_0 0
#define ARDUINO_RUNNING_CORE_1 1
#endif

#define TFT_MOSI 23  // SDA Pin on ESP32
#define TFT_SCLK 18  // SCL Pin on ESP32
#define TFT_CS   15  // Chip select control pin
#define TFT_DC    2  // Data Command control pin
#define TFT_RST   4  // Reset pin (could connect to RST pin)

// Colors
#define COLOR_TOP_BG tft.color565(125, 125, 125)
#define COLOR_TL_BG tft.color565(3, 96, 7)
#define COLOR_BL_BG tft.color565(3, 96, 7)
#define COLOR_TR_BG tft.color565(117, 70, 2)
#define COLOR_BR_BG tft.color565(117, 109, 2)

#define COLOR_TOP_TEXT ST77XX_WHITE
#define COLOR_TL_TEXT ST77XX_BLACK
#define COLOR_TL_TEXT ST77XX_BLACK
#define COLOR_TL_TEXT ST77XX_BLACK
#define COLOR_TL_TEXT ST77XX_BLACK

static const char* ssid     = "MOVISTAR_F6112";
static const char* password = "C89qlqMifsjDMWhbdsJQ";

// Initialize Adafruit ST7789 TFT library
Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

// the setup function runs once when you press reset or power the board
void setup() {

  // initialize serial communication at 115200 bits per second:
  Serial.begin(115200);

  xTaskCreatePinnedToCore(
    updateDateTime,   /* Function to implement the task */
    "updateDateTime", /* Name of the task */
    1024,      /* Stack size in words */
    NULL,       /* Task input parameter */
    3,          /* Priority of the task */
    NULL,       /* Task handle. */
    0
  );

  // Connecting to Wifi
   WiFi.begin(ssid, password);

  //tft.init(240, 240, SPI_MODE2);    // Init ST7789 display 135x240 pixel
//  tft.setRotation(3);
//  drawBackground();
}

void loop() {
}

// Function to draw the display background
void drawBackground() {
  tft.fillScreen(0xFFFFFF);
  tft.fillRect(0, 0, 240, 24, COLOR_TOP_BG);
  tft.fillRect(0, 24, 120, 107, COLOR_TL_BG);
  tft.fillRect(0, 133, 120, 107, COLOR_BL_BG);
  tft.fillRect(120, 24, 120, 107, COLOR_TR_BG);
  tft.fillRect(120, 133, 120, 107, COLOR_BR_BG);

  tft.fillRect(0, 22, 240, 4, ST77XX_BLACK);
  tft.fillRect(0, 130, 240, 3, ST77XX_BLACK);
  tft.fillRect(118, 22, 4, 218, ST77XX_BLACK);
}

// Function to update the date/time
void updateDateTime( void * pvParameters ) {
  tft.init(240, 240, SPI_MODE2);
  tft.setRotation(3);
  drawBackground();

  for( ;; ) {
    //tft.init(240, 240, SPI_MODE2);
    tft.setTextColor(COLOR_TOP_TEXT, COLOR_TOP_BG);
    tft.setCursor(6, 4);
    tft.println("MIE");

    delay(100);
  }
}
```

I have kept the function pinned to a core to avoid problems if RTOS decides to run the function on another core later. I have to do more tests, but seems to works.

Best regards.


message:
Best way to add external power supply when main PSU is a solar charge controller?

I have a 12V 20A Solar Charge Controller (which is part of my existing Solar Panel System Setup connected to a 12V Sealed Lead Acid Battery) that I will use to power up some pumps with the help of relays and some sensors. And because its a solar charge controller, the output varies depending on the sun, from 12.1v to 13.8v (I set the Load Reconnect, Load Disconnect, Float Charge etc which technically 12V to 13.8V)

How do I power my Arduino Mega safely in this case?

I am planning on using a separate buck converter that will give my Arduino a fixed 9V from the Solar Charge Controller.

Should I power the Arduino with the buck converter parallel to the same PSU (the 12V 20A Solar Charge Controller) I'm using for the pumps and is it safe that way?

or

Should I use a 9V battery to separately power the Arduino Mega?  and what is the explanation behind the concept of using an external PSU for the Arduino Mega when the total Amperes all in all is not exceeding the limit 20A at all?

body:
> Should I power the Arduino with the buck converter parallel to the same PSU (the 12V 20A Solar Charge Controller) I'm using for the pumps

Yes. However I wouldn't use a 9V buck regulator, but a 5V one and feed it to the 5V pin. That way you bypass the wasteful LDO on the Arduino, and when running from solar every bit of power saving you can muster helps.

> and is it safe that way?

Yes, it's safe. As long as the buck regulator you are using is rated for the voltages in question.


body:
Ok first, you need a battery for all this to work.  The solar charge controller won't drive into nothin', that is not what they are designed to do.

 Its full name is "solar *battery* charge controller".   Size the battery any way you like, just make sure the charge controller knows what kind it is, so it sets the proper charge curves and doesn't overcharge it/boil it dry/make it catch fire (lithium).

Once you have a battery in the system, paralleling in another battery charger is not a problem, be it wind, AC mains, or another solar CC.

- - -

Now, you will need to manage the case where the Arduino calls for the pump to turn on, but the solar panel is not making enough power to successfully power the pump.  This will not magically sort itself out.

- If you did not have a battery, it'll "crow bar".  The pump would effectively pull the solar voltage to near zero, which would cause the Arduino to shut down, turning off the pump and causing solar voltage to recover.  The Arduino would reboot, try again, and fail again.  Repeating.  So a crow-bar condition.

- If you do have a battery, then the Arduino will successfully spin up the pump, *but*, the solar won't be enough and this will be depleting the battery.  If your usage runs the battery flat, see crow-bar above.

- If you have a battery and the Arduino monitors battery voltage, it can defer operation until the Arduino knows the battery is sufficiently charged for the work needed.  At this point you don't need to care if the solar is up, the battery will carry the "buffer".    Make sure to shut the load off before the battery is depleted enough to create a crow-bar condition.

Note that if the battery is lead-acid, it should be managed to stay within 60-100% state of charge.  Depleting a lead-acid below 60% of max will rapidly age the battery.  It probably will be, since they are a happy intersection of "cheap" and "well-supported by every charge controller ever made".

Power to the Arduino itself should be taken as close as possible to the energy source (e.g. battery) — *even if that means a long, redundant cable, **especially** in that case actually*.  Do not share a supply cable with motors or pumps or other heavy loads!!!  I have seen many installations where the startup current of the motor causes enough *voltage drop* down the shared supply cable to cause the Arduino to lose power and reboot.   That is quickly cured by running a redundant V+ and V- power cable just for the Arduino.


message:
Using MCP23017 with 5 rotary encoders, WITHOUT missing a single step from any of them?

I have recently followed the instructions in the answer to this question:
https://arduino.stackexchange.com/questions/52909/reading-several-rotary-encoders/52926
posted by [maximilian-gerhardt](https://github.com/maxgerhardt)

I've wired everything up, and am using the interrupts example that can be found here:
https://github.com/maxgerhardt/rotary-encoder-over-mcp23017/tree/master/examples/Interrupt

Everything seems to work as expected, except that my assumption was that since this was an interrupt-based solution, that I wouldn't be missing any steps of any of the encoders. There are a total of 5 that will move at the same time, and it is clear that while it *almost* works, there are many steps that are missed.

I'm guessing that is because while one interrupt is being handled, all other interrupts are disabled?

Is there any way where I can ensure that every single motion (step CW or CCW) is registered on all 5 encoders?

Thanks!
Brian

body:
Interrupts don't mean that you can do lots of things at the same time. All they mean is that something can be responded to rapidly, as long as nothing else is being responded to of an equal or higher priority.

And coupling that with an IO expander which will inevitably slow things down means that you really can't do what you are trying to do.

If you want to respond instantly to every single pulse of every single encoder then each encoder has to be attached to something that can itself respond to those pulses.

I would be inclined to have a small microcontroller attached to each individual encoder (or maybe two encoders if you have enough interrupt pins) and deal with each separately - that way one encoder *cannot* interfere with any other. The small MCU can then keep track of position or count (depending on what it is you are trying to do) and you communicate that to a "master" controller (the Arduino for example) over some other bus, asynchronously to the encoder's pulses.

If you want more rapid response to the encoder movements then it could be possible to implement your own interrupt signal from the small MCU to the Arduino to say "My encoder has been moved", at which point the Arduino can collect the data. It won't matter how long that takes to happen as the small MCU will be keeping track of any other changes. The ATTiny85 using Pin Change Interrupts could be a good low-cost choice for this.


body: I would use a different approach. Consider setting a flag when an interrupt occurs, a different flag for each interrupt then processing that in the main loop rather then the ISR (Interrupt Service Routine). Connecting with the SPI  in the 1.7 MHz mode will allow you to get in check the interrupt set the flag and leave the ISR. This will be a bit difficult to write but I think it would work very well. Taking a quick scan of the data sheet the MCP23917 should be the correct part to accomplish this. Also do the debouncing externally, will save a lot of code and speed up the process.


message:
strange strings

```

#include "Keypad.h"

char Incoming_value = 0;
String password = "123456";
String input = "";
const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

byte rowPins[ROWS] = {2, 3, 4, 5}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {6,7,8,9}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup()
{
  Serial.begin(9600);
  pinMode(13, OUTPUT);
}

void loop()
{
  if (Serial.available() > 0)
  {
    Incoming_value = Serial.read();
    Serial.print(Incoming_value);
    Serial.print("enter value");
    if (Incoming_value == '1') {
      digitalWrite(13, HIGH);
      Serial.print("ON");
    }
    else if (Incoming_value == '0') {
      Serial.print("OFF");
      digitalWrite(13, LOW);
    }
  }
  // Read the pushed button
  char key = keypad.getKey();
  input = input + key;
  // just print the pressed key
  if (key) {
    Serial.println(key);
  }
  if(key == '*' ){
    Serial.println(input);
    if( input == password){
      digitalWrite(13, HIGH);
    }
  }
  if(key == '#'){
    digitalWrite(13, LOW);
    input = "";
  }

/*
  // this checkes if 4 is pressed, then do something. Here  we print the text but you can control something.
  if (key == '4') {
    Serial.println("Key 4 is pressed");
          digitalWrite(13, HIGH);
      Serial.print("ON");
  }
    if (key == '5') {
    Serial.println("Key 5 is pressed");
          digitalWrite(13, LOW);
      Serial.print("ON");
  }
  */
}
```

when print input variable i get strange text like
>⸮⸮⸮⸮⸮⸮⸮;⸮⸮ߵ⸮⸮⸮⸮u⸮⸮⸮⸮⸮⸮?/}⸮⸮⸮⸮⸮⸮~⸮⸮⸮⸮⸮-d

what i can do ?

body:
**PS**: @lurker's suggestion in the comments - check the baud rate setting in your serial monitor as well.

**EDIT**: I admit that the code in the previous version of this answer was foolishly typed out by me due to lack of patience, so I'll make up for my mistake(not in code, but as a full answer).

First of all, I didn't understand what you wanted to do with the `Incoming_value` variable in your sketch, so I'm not gonna talk about it; I'd suggest adding a sufficiently small delay at the end of the code in the loop. This should provide the serial port some time to handle the incoming data and stop printing the confusing output (perhaps; just because delays make your microcontroller wait for a while to get things done elsewhere , especially where the reception of data is slow and thus avoid collisions)

Also note that I am not a CS student or an electronics geek, but I am speaking from my guesswork. Any correction is accepted.


body:
First of all you have to make sure, that you select the same baudrate in the Serial Monitor, that you used in your sketch with `Serial.begin()`. This error is very common and garbage values is the symptom of this.

But your code also has problems. You have the `input` variable of type `String`, which should hold the user input for comparison with the password. Directly after getting the key, you are appending this key to the string. You are assuming here, that `keypad.getKey()` is waiting for the user to actually press a key and then return that. But this is not the case. `keypad.getKey()` will return `NO_KEY`, when the user currently isn't pressing a key. This is defined in the `Keypad` library as `'\0'` (the null character), which marks the end of a string. Your code runs very fast, so you are adding more and more null characters to your string. Your strings gets bigger and bigger, filling your RAM very fast.

**How to solve this:** You should only use the return value of `keypad.getKey()`, if a key was actually pressed. Put all the code after it in an if statement, checking for `NO_KEY`:

    // Read the pushed button
    char key = keypad.getKey();
    if(key != NO_KEY){
        input = input + key;
        // just print the pressed key
        if (key) {
            Serial.println(key);
        }
        if(key == '*' ){
            Serial.println(input);
            if( input == password){
                digitalWrite(13, HIGH);
            }
        }
        if(key == '#'){
            digitalWrite(13, LOW);
            input = "";
        }
    }


message:
Dealing with noise in arduino interrupt

I'm makeing two modules,
module2 gets sensor signal, and send wireless message to module1, with HC-12. Then module1 is going to do some work it is supposed to do. Circuit configuration is in the picture.

I tested HC-12 communication, and they send, receive well. But my problem is that,
when module1 gets turned ON, Interrupt gets activated (LOW) and module2 sends signal that's not supposed to send. It seems it is because of electromagnetic wave noise, from HC-12.

How can I filter this noise, using code ? Now I'm stuck for the last 3 days.

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

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

```code```
Module1

    #include <SimpleTimer.h>

    #include <LiquidCrystal_I2C.h>
    #include <SoftwareSerial.h>

    // #define IDlen 4
    #define maxID 5

    SoftwareSerial mySerial(2,3);
    LiquidCrystal_I2C lcd(0x27, 16, 2);
    int upButtonPin = 7;
    int selectButtonPin = 6;
    int downButtonPin = 5;
    int sensors[maxID] = {1001,9999,9999,9999,9999};
    int receivedID = 0;
    int currentPos = 0;
    String rcvMsg = "xxxx";

    //void printSensor(int intID);
    void menu();
    void showAllSensors();
    int removeID(int senNumInt);

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

      mySerial.begin(9600);
    //  mySerial.println("0000");

      lcd.begin();
      pinMode(upButtonPin,  INPUT_PULLUP);
      pinMode(selectButtonPin, INPUT_PULLUP);
      pinMode(downButtonPin, INPUT_PULLUP);
    }

    void loop()
    {
      rcvMsg = "xxxx";
      lcd.setCursor(1,1);
      lcd.clear();
      lcd.print("Ready");
      if(digitalRead(upButtonPin)==LOW){
        lcd.clear();
        lcd.print("Up btn pressed!");
      }
      if(digitalRead(downButtonPin)==LOW){
        lcd.clear();
        lcd.print("Down btn pressed!");
      }
      if(digitalRead(selectButtonPin)==LOW){
        lcd.clear();
        lcd.print("Registered sensors:");
        delay(1000);
        lcd.clear();
        showAllSensors();
        menu();
      }
      if(mySerial.available()>0){

    //    String rcvMsg = mySerial.readStringUntil('\n');
        rcvMsg = mySerial.readStringUntil('\n');
        Serial.print("Received msg: ");
        Serial.print(rcvMsg);
        Serial.print('\n');
        receivedID = rcvMsg.substring(0,4).toInt();
        Serial.println(receivedID);
        delay(50);

        for (int i=0;i<maxID;i++){
          if(sensors[i] == receivedID){
            String temp = String(receivedID);
            String ack = String(temp + "01"); // 01: success 02: reject (ID does not exist)
            mySerial.println(ack);
            Serial.print("Ack sent: ");
            Serial.print(ack);
          }
        }
      }
    }

    void menu(){
      lcd.print("UP: add sensor");
      lcd.setCursor(0,1);
      lcd.print("DOWN: del sensor");
      lcd.setCursor(0,0);

      while(1){
        if(digitalRead(upButtonPin)==LOW){
          lcd.clear();
          lcd.print("Add sensor:");
          delay(1500);
          lcd.clear();
          int senNumInt = 1000;
          char senNum[IDlen];
          sprintf(senNum, "%d", senNumInt);

          while(1){
            lcd.print(senNum);
            if(digitalRead(upButtonPin)==LOW){
              senNumInt++;
              sprintf(senNum, "%d", senNumInt);
              lcd.clear();
              lcd.print(senNum);
            }
            if(digitalRead(downButtonPin)==LOW){
              senNumInt--;
              sprintf(senNum, "%d", senNumInt);
              lcd.clear();
              lcd.print(senNum);
            }
            if(digitalRead(selectButtonPin)==LOW){
              lcd.clear();
              lcd.print(senNum);
              lcd.setCursor(0,1);
              lcd.print("Menu: OK, Down: Cancel");
              //센서 입력값을 받아서, 리스트에 넣어 놓기
              sensors[currentPos] = senNumInt;
              lcd.clear();
              showAllSensors();
              delay(1500);
              break; // 값 입력 후 저장한 것 보여주고... 나가기.
            }
            delay(200);
            lcd.clear();
          }
          delay(200);
          break;
        } // up button 누름 메뉴 끝

        if(digitalRead(downButtonPin)==LOW){
          lcd.clear();
          lcd.print("Remove sensor:");
          delay(1500);
          lcd.clear();
          int senNumInt = 1000;
          char senNum[IDlen];
          sprintf(senNum, "%d", senNumInt);

          while(1){
            lcd.print(senNum);
            if(digitalRead(upButtonPin)==LOW){
              senNumInt++;
              sprintf(senNum, "%d", senNumInt);
              lcd.clear();
              lcd.print(senNum);
            }
            if(digitalRead(downButtonPin)==LOW){
              senNumInt--;
              sprintf(senNum, "%d", senNumInt);
              lcd.clear();
              lcd.print(senNum);
            }
            if(digitalRead(selectButtonPin)==LOW){
              lcd.clear();
              lcd.print(senNum);
              lcd.setCursor(0,1);
              lcd.print("Delete sensor");
              delay(600);
              lcd.clear();

              //센서 입력값을 받아서, 리스트에서 찾은 후 삭제
              int result = removeID(senNumInt);
              if(result==1){
                lcd.print("Deleted.");
                showAllSensors();
              }else{
                lcd.print("No such ID!!");
              };
              delay(1500);
              break; // 값 입력 후 저장한 것 보여주고... 나가기.
            }
            delay(200);
            lcd.clear();
          }
          delay(200);
          break;
        } // down button 누름 메뉴 끝

        delay(200);
      }
      return;
    }

    void showAllSensors(){
      char imsi[IDlen];
      for(int i=0;i<maxID;i++){
        Serial.println(sensors[i]);
        sprintf(imsi, "%d", sensors[i]);
        lcd.print(imsi);
        delay(800);
        lcd.clear();
      }
      return;
    }

    int removeID(int senNumInt){
      int isFound = 0;
      for(int i=0;i<maxID;i++){
        if(sensors[i] == senNumInt){
          sensors[i] = 9999;
          isFound = 1;
        }
      }
      return isFound;
    }

```code```Module2

    #include <SoftwareSerial.h>
    #include <avr/sleep.h>
    #include <SimpleTimer.h>

    SimpleTimer timer;
    const int wakeUpPin = 2; // pin of interrupt 0
    const int LED = 8;
    const int numMsg = 1; // For the safety, send multiple messages, everytime.
    boolean armed = false;
    SoftwareSerial mySerial(4,5);
    String ID = "1001";
    String code = "01";
    String msg = "xxxx";
    String rcvMsg = "xxxx";
    int timerID = 0;
    boolean isWaked = false;
    int pulseWidth = 0;

    /*
      Communication protocol
      01: powered on
      02: Sensor touched (Feed is full)
      03: alive
    */

    void setup()
    {
      String msg = String(ID + code);
      pinMode(wakeUpPin, INPUT_PULLUP);
      pinMode(LED, OUTPUT);
      timerID = timer.setInterval(1000, sendMsg);

      Serial.begin(9600);
      mySerial.begin(9600);
      Serial.println(msg);
      delay(100);
    }

    void loop() // 반복
    {
      pulseWidth = pulseIn(wakeUpPin, LOW, 100000);
      Serial.println("start loop.");
      armed = true;
      delay(100);
      Serial.println("Now sleeping..");
      delay(200);
      sleepNow();

      Serial.println(pulseWidth);
      if(armed){
        Serial.println("Waked up. Send Feed full msg.");

        delay(200);
        code = "02";
        msg = String(ID + code);
        sendMsg();
        int count = 0;
        while(1){
          count++;
          if(count>200){      //prevent infinite loop
            count = 0;
            break;
          }
          Serial.print('*');
          if(mySerial.available()>0){
            Serial.println("RECEIVED!!!!");
            rcvMsg = mySerial.readStringUntil('\n');
            if(rcvMsg.substring(0,4).equals(ID)){
    //          timer.deleteTimer(timerID);
              Serial.println("My msg is received successfully. Now sleep again..\n");
              break;
            }
          }
          delay(50);
        }
        armed = false;
      }
    }

    void wakeUpNow(){
      isWaked = true;
      return;
    }

    void sleepNow(){
      Serial.println("Entered sleep now()");
      delay(100);
      set_sleep_mode(SLEEP_MODE_PWR_DOWN);
      sleep_enable();
      attachInterrupt(0,wakeUpNow, LOW);
      sleep_mode();
      // When wakes up, resume codes from here.
      sleep_disable();

      detachInterrupt(0);
      return;
    }

    void sendMsg(){
      for (int i=0;i<numMsg;i++){
        mySerial.println(msg);
      }
      return;
    }

body:
I know, it is not exactly what you asked for, but I recommend hardware filtering. I had problems with noise on interrupts and I was able to solve that with this component: https://www.st.com/content/st_com/en/products/emi-filtering-and-signal-conditioning/integrated-emi-filtering-and-esd-protection/computer-legacy-port-ipad/kbmf.html#overview

It is not expensive and saves you a lot of headache.
If you can't use SMD components, you can rebuild the circuit of that filter with capacitors and resistors, just be sure, that you put the filter as close as possible to the interrupt pin.


message:
Multiple Wire.write() not working for Arduino Nano I2C

Code for Master
--------
```c++
#include <Wire.h>

void setup()
{
  Wire.begin();

  Serial.begin(9600);
}

void loop()
{
    Wire.beginTransmission(9);

    Wire.write('c');
    Serial.println('c');
    Wire.write('a');
    Serial.println('a');
    Wire.endTransmission();
}
```

---

In my case `Wire.write('c')` is performing the task which is assigned to `'c'` in slave board.
Then its printing `'c'` in serial monitor as intended.
But, `Wire.write('a')` line is being neglected and nothing happens on slave board.  But again, it's printing `'a'` in serial monitor as per code.
Why is that `Wire.write('a');` is neglected? Both boards are Arduino Nano.

Code for Slave
--------------
```c++
#include <Wire.h>
#define RED 8
#define GREEN 10
int x = 0;

void setup() {
  pinMode (RED, OUTPUT);
  pinMode (GREEN, OUTPUT);
  Wire.begin(9);
  Wire.onReceive(receiveEvent);
}

void receiveEvent(int bytes) {
  x = Wire.read();    // read one character from the I2C
}

void loop() {
    if (x == 'a') {
        digitalWrite(RED, HIGH);
        digitalWrite(GREEN, LOW);
    }
    if (x == 'b') {
        digitalWrite(RED, LOW);
        digitalWrite(GREEN, HIGH);
    }
    if (x == 'c') {
        digitalWrite(RED, HIGH);
        digitalWrite(GREEN, HIGH);
    }
    if (x == 'd') {
        digitalWrite(RED, LOW);
        digitalWrite(GREEN, LOW);
    }
}
```

body:
**Important information:** `Wire.write()` does NOT send anything over the I2C lines. It just puts the data into the libraries internal buffer. The actual transmission is then done by `Wire.endTransmission()`.

I2C is packaged transmission protocol. That means, that the transmission is done in confined data packages. In your master code you are calling `Wire.write()` two times before `Wire.endTransmission()`. That means you are sending 1 package with 2 data bytes in it.

Now for your slave code: You are using a callback function for the `onReceive` event. This callback function is called once per transmission. In there you can read all the data of that transmission. After that the data is thrown away (I think actually it gets deleted, when a new transmission is received). You are only reading once with `Wire.read()`. So you only ever read the first byte of every transmission, which is always the letter `'c'`.

**What to do know?** This depends on how you want the code to behave. Since you are setting 2 LEDs based on the received byte it would be better to only send 1 byte transmissions. For that, you can change your master code. For example like this:

    #include <Wire.h>

    void setup()
    {
      Wire.begin();

      Serial.begin(9600);
    }

    void loop()
    {
        // Send the command c
        Wire.beginTransmission(9);
        Wire.write('c');
        Wire.endTransmission();

        // Wait 1s, so that we can see the LEDs state accordingly
        delay(1000);

        // Send command a
        Wire.beginTransmission(9);
        Wire.write('a');
        Wire.endTransmission();

        // Wait 1s, so that we can see the LEDs state accordingly
        delay(1000);
    }

This code will change between `'c'` and `'a'` every second. You need a delay there to actually see the LEDs light up. Otherwise they would change too fast for you to see it.

**Note:** Actually you need to declare the variable `x` as `volatile`, because the onReceive callback is called from an ISR. With that keyword you are telling the compiler, that `x` can change at any time (by the ISR of the corresponding I2C interrupt). It might be, that your current code works, because the compiler was smart enough to see that, but in general you should always use `volatile` with every variable, that can change in an ISR. Declaration then looks like this:

    volatile int x = 0;

And to handle the ISR data really correct, you would need to make the usage atomic, because the ISR can happen in the middle of the comparison for the if statements. An `int` is two bytes, so the first byte might be updated and the second byte not. That would corrupt your data. There are two ways to handle that in your case:

- **Make the reading of `x` atomic:** Normally one would turn of the interrupts, read the volatile variables into local variables (as a copy) and then turn the interrupts on again. That way the interrupt cannot corrupt the data in the variable during reading. The further calculation/comparison would then be done with the local variable.

- **Use a single byte as volatile data**: The described problem does not apply to variables, which only use 1 byte (since on the 8bit Arduinos like the Nano the reading of a single byte cannot be interrupted). So just make `x` of type `char` (or `uint8_t` or `byte`).

You should use the second option.


message:
Arduino nano digital I/O overload

Is it possible to kill arduino nano with overload?

I wanted to drive a relay with arduino, and I used a BC547 to switch 12V for the relay.
But in the relay there was a diode, which sorted out the circuit (thats why I drawed in the wrong orientation)

I know it was a mistake to not use current limiting resistor on Base of the transistor.

Is it possible that this shorted circuit made too much current on the transistor base which killed my arduino?

I made this circuit:
[![Schematic][1]][1]

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

body:
Short answer is probably.  There is a voltage drop from base to emitter that is about .7 volts.  But something still has to contend with the rest of the energy.  You might try a different Arduino digital output on the chance that the balance of the processor is working as expected.

I say probably because several things might have happened if the transistor actually turned on.  For instance the forward biased (backwards) diode may have allowed so much current to flow through the relay and transistor that the transistor failed first.  Or, if the power supply had a low current rating, it may not have had the capacity to burn anything out.  As you can see, it is difficult to say what exactly happened with out testing each part individually.


message:
Driving a servo with an ATTiny13A

So, I managed to fry my cheap servo/ESC (electronic speed controller) and decided to make my own using an ATTiny13A on some perfboard. But, I have run into some issues getting the servo to respond.  I'm assuming the servo.h library is not compatible with the ATTiny13A because of incompatible internal clock speeds not creating the right PWM signals. And I haven't found a solution for this.

I have messed around with the Servo8Bit.h library, but this also doesn't seem to work (as its designed for the ATTiny45 and the ATTiny85 ). Is the ATTiny13A even able to produce the needed PWM signals?

Any help/links to documentation would be appreciated!

Thanks in advance.

Code:
```c++
#include <Servo.h>

Servo myservo;
int potpin = A3;
int val;    // variable
int Toggle = 2;

void setup() {
  Serial.begin(9600);
  pinMode(Toggle, INPUT);
  myservo.attach(1);  // Servo/ESC is attached to pb1
}

void loop() {
  int ToggleState = digitalRead(Toggle);
  Serial.println(ToggleState);
    val = analogRead(potpin);

  if (ToggleState == 0) {
  val = map(val, 0, 1023, 0, 180);  //Servo motor
   myservo.write(val);
  delay(15);
}
else {
  val= map(val, 0, 1023,1000,2000); //ESC
  myservo.write(val);
  delay(15);
 }
}
```
[![Circuit][1]][1]
[![Project][2]][2]

  [1]: https://i.stack.imgur.com/JFHF9.png
  [2]: https://i.stack.imgur.com/cQx4n.jpg

body:
Servo8Bit and ATTiny13(A)
-------------------------

I had a look at the Servo8Bit and had pretty much the same thoughts on this as [Edgar Bonet][1] in his comment:

> Servo8Bit relies on an 8-bit timer, and the ATtiny13A does have an
> 8-bit timer. It should not be too hard to port this library to that
> micro. Study the source code, then study the datasheet of the tiny13A
> (mostly the chapter dedicated to the timer). You should then be able
> to easily see what changes are needed.

Ignoring the timing differences between the ATTinyx5 and ATTiny13(A), I just went ahead and saw if I could get it to compile.  And yeah, it's pretty easy to compile.  This mostly consists of adding `0` to some hardware register names.  The bad news is:

> Sketch **uses 1486 bytes (145%)** of program storage space. **Maximum is 1024 bytes.**
> Global variables use 31 bytes (48%) of dynamic memory, leaving 33 bytes for
> local variables. Maximum is 64 bytes.
>
> Sketch too big; see http://www.arduino.cc/en/Guide/Troubleshooting#size for tips on reducing it.
>
> Error during build: text section exceeds available space in board

So, yeah, that was a bit much to hope for, I guess.  The library does use ISRs to support a number of servos kind of like the more common servo library that you'd use on an UNO.  I haven't looked into chopping it down to size; I expect that will be impractical.

PWM... sort of.
--------------

Prior to considering modifying Servo8Bit, I kind of thought it made sense to just use the timer counter directly to produce a waveform.  The problem is the conventional servo signal is 20ms long, and does all of its control in a 1ms window.  If you try to fit the whole 20ms frame into a single 8bit timing interval, what you end up with is pretty crappy angular control.  So, doing it is a bit painful without a 16-bit timer counter.  But, I guess that's the game.

So, the below is a crude and barely tested attempt at it.  The code that follows is state machine inside the OCR0B overflow vector that schedules the rising an falling edges is "normal" mode.  Just to warn you, I don't actually have an ATTiny13(A) on hand.  And in fact I don't happen to have a servo hand either.  But I do have an ancient storage scope and an ATTiny85 and the ability to compile for ATTiny13(A), and a calculator for working out the 8 MHz vs 9.6 MHz difference.

So here's what I came up with, which I *think* (but don't know) will work if you compile and upload using [MCUDude MicroCore][2], ATTiny13(A) with the 9.6 MHz internal oscillator chosen.

It's only designed to operate 1 servo.  Extending it to two should be easily doable.  Going beyond that you're likely run into problems.

Code:

```c++
// +---------------------------------------------------------------------------------------+
// |                                                                                |
// |                                 +-------------+                                       |
// |                                 |             |                                       |
// |                                 |      A      |                                       |
// |  PCINT5 ADC0 dW  /RESET  PB5 *--|-1    T    8-|--* VCC                                |
// |                                 |      T      |                                       |
// |  PCINT3 ADC3      CLKI   PB3 *--|-2    I    7-|--* PB2  SCK   ADC1 T0         PCINT2  |
// |                                 |      N      |                                       |
// |  PCINT4 ADC2             PB4 *--|-3    Y    6-|--* PB1  MISO  AIN1 OC0B  INT0 PCINT1  |
// |                                 |      1      |                                       |
// |                          GND *--|-4    3    5-|--* PB0  MOSI  AIN0 OC0A       PCINT0  |
// |                                 |      A      |                                       |
// |                                 |             |                                       |
// |                                 +-------------+                                       |
// |                                                                                |
// +---------------------------------------------------------------------------------------+

#if !defined(__AVR_ATtiny13__) && !defined(__AVR_ATtiny13A__)
#error This code is written specifically for ATTiny13(A) devices.
#endif

#if F_CPU != 9600000
#error  This code is written specifically for 9.6 MHz
#endif

//
//
//
#include <avr/io.h>
#include <avr/interrupt.h>

//
//
//
constexpr uint8_t TCCR0A_config(
  int com0b // two bits
) {
  return
      (    0 << COM0A1) // normal
    | (    0 << COM0A0) //   port operation
    | (com0b << COM0B0) // bits 5 AND 4
    | (    0 <<      3) // reserved
    | (    0 <<      2) // reserved
    | (    0 <<  WGM01) //  lower two bits
    | (    0 <<  WGM00);//     of Normal (mode 0);
}

//
//
//
constexpr uint8_t TCCR0A_config_for_go_low()  {return TCCR0A_config(0x2);}
constexpr uint8_t TCCR0A_config_for_go_high() {return TCCR0A_config(0x3);}

//
// 50 Hz (hobby servo frame frequency); period 20 ms
//
// In the below you'll see the numbers 150 and 300 and 3000.
// The reason for these numbers is that I've chosen to to use a /64
// timer prescaler.  At 9.6 MHz, with a /64 prescaler, 1 millisecond
// is 150 timer timer counts.  There's as fixed 1 MS high in the servo,
// followed by 0 to 1ms variable portion.  The number 150 helpfully
// fits within the 8-bit timer registers and also gives a reasonable
// number of increments to the servo control.  For 180 degrees, 150 increments
// is 1.2 degrees.
//
// The maximum high time is the fixed 1ms high time and the maximum
// variable high time, totalling 2 MS, or 300 timer ticks, that's what that
// number is about.
//
// 3000 is the number of timer ticks for a full 20ms signal frame,
// that is 20 * 150 = 3000.
//
//
// Deriving the 150 figure:
//
//  At 9.6 MHz and /64 prescaler
//
//        1 second         64 mcu_cycles   A_MS_DURATION timer_counts
//  -------------------- X ------------- X ---------------
//  9_600_000 mcu_cycles   1 timer_count    0.001 seconds
//
//
//       1      64    A_MS_DURATION
//  --------- X -- X  -----
//  9_600_000   1     0.001
//
//
//     64       A_MS_DURATION
//  --------- X -----------
//  9_600_000      0.001
//
//
//     64 x A_MS_DURATION
//  --------------------
//        9_600
//
//
//  A_MS_DURATION
//  -------------
//      150
//

static constexpr uint8_t  ONE_MS_WORTH_OF_TICKS    = 150;
static constexpr uint8_t  MAXIMUM_HIGH_PERIOD      = ONE_MS_WORTH_OF_TICKS * 2;
static constexpr uint16_t TWENTY_MS_WORTH_OF_TICKS = 3000;
static constexpr uint16_t MAX_WASTE_CYCLES         = 0x80;

static volatile uint8_t g_pulse_width = ONE_MS_WORTH_OF_TICKS / 2;  // default to mid-range.

ISR(TIM0_COMPB_vect) {
  static uint8_t l_pulse_width; // this caches g_pulse_width
                                // and is updated from g_pulse_width
                                // only between frames

  //
  // The ISR is a state machine with four macro states.
  //
  enum class t_signal_generator_state : uint8_t {
    timing_to_variable_high_period,
    timing_to_set_pulse_width,
    calculate_time_to_start_of_next_pulse_and_waste_a_bit,
    timing_to_start_of_pulse
  };

  //
  // Macro state variable
  //
  static t_signal_generator_state g_signal_generator_state =
    t_signal_generator_state::timing_to_variable_high_period;

  // low_time_remaining is an extended state variable
  // for the timing_to_start_of_pulse state
  static uint16_t low_time_remaining;

  switch (g_signal_generator_state) {
    case t_signal_generator_state::timing_to_variable_high_period:
      // We just went high at the OCR0B value that triggered this interrupt
      // and we need to retrigger ((MAXIMUM_HIGH_PERIOD==300) - 256 == 44)
      // timing cycles later such that there are 256 timing cycles left of the
      // 2ms (maximum) high part of the frame.
      OCR0B += (MAXIMUM_HIGH_PERIOD - 256);  // 2ms worth of timer nicks minus the resolution of our timer

      // We're remaining HIGH as we head into the variable portion of the HIGH period.
      g_signal_generator_state = t_signal_generator_state::timing_to_set_pulse_width;
      break;
    case t_signal_generator_state::timing_to_set_pulse_width:
      // We're retrieving the global variable which holds a (potentially new) value from 0 to 150
      // representing a span of 0ms to  1ms (the full range of the servo), but
      // we're starting out the variable pulse a head of time, part way through the always-on first ms.
      // There are (150 - 44) timer cycles, that's 1 ms worth of timer cycles
      // where the timer remains high to finish out first millisecond of HIGH.
      // So we add this to the requested variale pulse width time.
      l_pulse_width = g_pulse_width + (ONE_MS_WORTH_OF_TICKS - 44);

      // Set adjust pulse width
      OCR0B += l_pulse_width;

      // We'll be going low and the end of the variable high period.
      TCCR0A = TCCR0A_config_for_go_low();

      g_signal_generator_state = t_signal_generator_state::calculate_time_to_start_of_next_pulse_and_waste_a_bit;
      break;

    case t_signal_generator_state::calculate_time_to_start_of_next_pulse_and_waste_a_bit:
      // We just went low at the OCR0B value.

      // Calculate remaining timer cycles to the beginning of the next pulse
      // accounting for the MAX_WASTE_CYCLES we're about to waste in this state.
      low_time_remaining = (TWENTY_MS_WORTH_OF_TICKS - 44 - MAX_WASTE_CYCLES) - l_pulse_width;
      OCR0B += MAX_WASTE_CYCLES;

      // We will remain LOW since the pulse is done and we've not finished out the 20ms period
      g_signal_generator_state = t_signal_generator_state::timing_to_start_of_pulse;
      break;

  case t_signal_generator_state::timing_to_start_of_pulse:
      // Continue retriggering the timer until we've used up 20ms total,
      // in increments of not more than MAX_WASTE_CYCLES.

      if (low_time_remaining > MAX_WASTE_CYCLES) {
        low_time_remaining -= MAX_WASTE_CYCLES;
        OCR0B += MAX_WASTE_CYCLES;
        // We'll need to wast more, so we're remaining LOW.
      } else {
        OCR0B += low_time_remaining;
        low_time_remaining = 0;

        // This is out last round through this state to finish out the 20ms
        // window, so we'll be returning to HIGH.
        TCCR0A = TCCR0A_config_for_go_high();

        g_signal_generator_state = t_signal_generator_state::timing_to_variable_high_period;
      }
      break;
  }
}

//
//
//
void servo_init() {
  const auto SREG_saved = SREG; cli();

  DDRB |= 1U << 1;  // Servo data pin attached on Attiny PB1 aka (OCR0B)

  // select no clock source / stop counter
  TCCR0B &= ~(
      (1U << CS02)
    | (1U << CS01)
    | (1U << CS00)
  );

  // reset counter
  TCNT0 = 0x00;
  OCR0B = 0x80;

  TIMSK0 =
      (0 <<      7) // reserved
    | (0 <<      6) // reserved
    | (0 <<      5) // reserved
    | (0 <<      4) // reserved
    | (1 << OCIE0B) // we *ARE*  using output-compare B interrupt
    | (0 << OCIE0A) // we aren't using output compare A interrupt
    | (0 <<  TOIE0) //             nor overflow interrupt
    | (0 <<      0);// reserved

  TIFR0 = 1U << OCF0A;

  TCCR0A = TCCR0A_config_for_go_high();

  TCCR0B =
      (0 << FOC0A) // We're not doing any
    | (0 << FOC0B) //   output compare forcing.
    | (0 <<     5) // Reserved.
    | (0 <<     4) // Reserved.
    | (0 << WGM02) // High order bit of Normal mode (0)
    | (0 <<  CS02) // Clock source
    | (1 <<  CS01) //    prescaled
    | (1 <<  CS00);//      by 64.

  SREG = SREG_saved;
}

//
//
//
void setup() {
  servo_init();
}

//
//
//
void loop() {
  for (g_pulse_width = 0; g_pulse_width < 150; ++g_pulse_width) {
    __builtin_avr_delay_cycles(F_CPU >> 5);
  }
  for (; g_pulse_width > 0; --g_pulse_width) {
    __builtin_avr_delay_cycles(F_CPU >> 5);
  }
}

//  vim:sw=2:ts=2:et:nowrap:ft=cpp:
```

On the scope, this produces servo signal that should sweep a servo on pin OCR0B (PB1).  Something like 4 to 5 seconds going one way and same going back.

If I put an ATTiny13A on an order sometime and manage to dig out a servo myself, I'll actually test it.  It may be a very long time before I can do that though.  But the results on the scope look good.  Admittedly everything is scaled by 9.6/8.0.  It should be accurate on a ATTiny13(A).  I verified that it compiles for it.  The workings of the thing are explained in the code as I can.

For comparison:

>Sketch uses **490 bytes (47%)** of program storage space. Maximum is 1024 bytes.
>Global variables use 10 bytes (15%) of dynamic memory, leaving 54 bytes for local variables. Maximum is 64 bytes.

That's still a good chunk of what little code space you have, but it should be enough to read a switch and potentiometer.  This is using the timer the device has, so `millis()`/`delay()` usage are kind of out-the-window, I think, I didn't try to see what happen when you call them or study their code in MicroCore.  You *could* recreate your own `millis()` by making a timer overflow interrupt and it would overflow at about 1.7 ms intervals.  As you can see, I just used `__builtin_avr_delay_cycles` to keep things simple.

If you, or anyone else, gets it working on at ATTiny13 before I try it myself, I'm curious to know that it worked (or didn't).

  [1]: https://arduino.stackexchange.com/users/7508/edgar-bonet
  [2]: https://github.com/MCUdude/MicroCore


message:
Arduino code not working properly (Please Help)

I am having some trouble getting my board to perform the function I want it to perform. This is a project I have due in a few days, and I have hit a wall I just can't seem to get past. Now, I will say the issue is definitely in the way I coded the program, but I don't really know enough about Arduino (and coding) to understand why it is not working. My board is properly hooked up to use 3LEDs, a speaker, a photoresistor, and an ultrasonic sensor (detects distances). My Arduino program takes serial input from a GUI that I created in MATLAB. I have verified the MATLAB code is good, and the serial port is communicating properly. I have made an alarm that goes off when light or motion is detected. It has 3 basic functions:

1) Set the alarm
2) Turn off the alarm
3) "snooze" which just delays for 5 minutes and then the alarm goes off

The snooze and turn off alarm parts of my code are working great, but the set alarm is where I am having trouble. The snooze option sets off the yellow LED to verify it is on "snooze". The red LED comes on when the alarm is currently going off. The green LED comes on when the alarm is set. When I try to activate the "Set Alarm" function, which is case 'O' in a switch case, the light does come on, but the sensors are not picking up any input as far as I can tell. Again I have verified the pins and everything are set up correctly as I have isolated those and verified they work. I have a suspicion that the problem is because I have the sensors initialed within the switch case of the "Set Alarm" (case 'O', not 0). I don't really know how to get the sensors to run continually within that switch case until the "turn alarm off" case is activated. I need the sensors to be activated/reset by "Set Alarm" case.

**I am also new to this forum so please let me know if I am missing anything!

here is my code:
<!-- language-all: lang-C++ -->

```
void setup()
{
  Serial.begin(115200);
  pinMode(12,OUTPUT); //RED
  pinMode(13,OUTPUT); //GREEN
  pinMode(14,OUTPUT); //YELLOW
  pinMode(16,OUTPUT); //SPEAKER
  pinMode(4,INPUT); //Echo
  pinMode(2,OUTPUT); //Trig
}

void loop()
{
 if(Serial.available() >0)
 {
 char b = Serial.read();

  switch(b)
  {
    //Turn Alarm off
    case 'A' :
    {
    digitalWrite(12,LOW);//red off
    digitalWrite(13,LOW); // green off
    digitalWrite(14,LOW); //yellow off
    noTone(16);
    delay(500);
    }
    break;

    // Set alarm
    case 'O' :
    {
      int light;
  light = analogRead(0);
  unsigned long distance;
    digitalWrite(2,LOW);
  delayMicroseconds(2);
  digitalWrite(2,HIGH);
  delayMicroseconds(10);
  digitalWrite(2,LOW);
  distance = pulseIn(4,HIGH);
  distance = distance/58; //centimeters
  delay(500);

    digitalWrite(12,LOW); //red off
    digitalWrite(14,LOW); //yellow off
    digitalWrite(13,HIGH); //green on

  if (light < 400)
    {
     digitalWrite(12,HIGH);//red on
    digitalWrite(13,LOW); // green off
    digitalWrite(14,LOW); //yellow off
    tone(16,832);
    delay(500);
    }

  if (distance < 50)
    {
     digitalWrite(12,HIGH);//red on
    digitalWrite(13,LOW); // green off
    digitalWrite(14,LOW); //yellow off
    tone(16,832);
    delay(500);
    }

    }
    break;

    // snooze option
    case 'Z' :
    {
    digitalWrite(14,HIGH); //yellow on
    digitalWrite(12,LOW); //red off
    digitalWrite(13,LOW); // green off
    noTone(16);
    delay(300000UL);
    digitalWrite(12,HIGH); //red on
    digitalWrite(13,LOW); // green off
    digitalWrite(14,LOW); //yellow off
    tone(16,832);
    delay(500);
    }
    break;
   }

  }
}

```
Any help would be very much appreciated!

body:
The problem is that, if you enter 'O', you go thorugh the set alarm case only once. If no alarm was triggered, it just falls through the if statements and is then back in the main loop. In that main loop, you only check for your sensors, if something was entered to the serial console. That means if you do not enter anything during a loop, nothing happens.

The solution to this would be to implement a finite state machine.
That means you use a state variable for the switch case. You then update your state based on the state and the external conditions. In your case you can just update the state using user input.

I changed your code a bit for a possible (but bad) implementation. I did not verify or check for errors. I recommend using a more solid implementation, if you plan to build upon this code for more complex behavior.

```
char state = 'A'; //initialize state in Off state
char b;          // make user input variable global
void setup()
{
  Serial.begin(115200);
  pinMode(12, OUTPUT); //RED
  pinMode(13, OUTPUT); //GREEN
  pinMode(14, OUTPUT); //YELLOW
  pinMode(16, OUTPUT); //SPEAKER
  pinMode(4, INPUT); //Echo
  pinMode(2, OUTPUT); //Trig
}

void loop()
{
  if (Serial.available() > 0)
  {
    b = Serial.read();
  }
  // close user input section

  switch (state) // run switch case every loop
  {
    //Turn Alarm off
    case 'A' :
      {
        digitalWrite(12, LOW); //red off
        digitalWrite(13, LOW); // green off
        digitalWrite(14, LOW); //yellow off
        noTone(16);

        delay(500);
      }
      break;

    // Set alarm
    case 'O' :
      {
        int light;
        light = analogRead(0);
        unsigned long distance;
        digitalWrite(2, LOW);
        delayMicroseconds(2);
        digitalWrite(2, HIGH);
        delayMicroseconds(10);
        digitalWrite(2, LOW);
        distance = pulseIn(4, HIGH);
        distance = distance / 58; //centimeters
        delay(500);

        digitalWrite(12, LOW); //red off
        digitalWrite(14, LOW); //yellow off
        digitalWrite(13, HIGH); //green on

        if (light < 400)
        {
          digitalWrite(12, HIGH); //red on
          digitalWrite(13, LOW); // green off
          digitalWrite(14, LOW); //yellow off
          tone(16, 832);
          delay(500);
        }

        if (distance < 50)
        {
          digitalWrite(12, HIGH); //red on
          digitalWrite(13, LOW); // green off
          digitalWrite(14, LOW); //yellow off
          tone(16, 832);
          delay(500);
        }

      }
      break;

    // snooze option
    case 'Z' :
      {
        digitalWrite(14, HIGH); //yellow on
        digitalWrite(12, LOW); //red off
        digitalWrite(13, LOW); // green off
        noTone(16);
        delay(300000UL);
        digitalWrite(12, HIGH); //red on
        digitalWrite(13, LOW); // green off
        digitalWrite(14, LOW); //yellow off
        tone(16, 832);
        delay(500);
      }
      break;
  }

  state = b; // update state based on input

}
```


body:
<!-- language-all: lang-C++ -->
The most simplest way to troubleshoot a program is to add `Serial.println();` statements everywhere. For example you could add `Serial.println("Setting Alarm");` in the first line of the case for setting the alarm.

You will notice that the set alarm code only runs once through, instead of continously. You should use the case to set a mode or a state in where the sensors are checked continously.

First I would create a variable called `setAlarmMode` and set it to `false`.

    setAlarmMode = false;

Then I would remove the reading of sensors from the case statement and instead set `setAlarmMode` to `true`.

    // Set alarm
    case 'O' :
      {
        Serial.println("Setting Alarm");

        // Set the LEDs for the mode
        digitalWrite(12, LOW); //red off
        digitalWrite(14, LOW); //yellow off
        digitalWrite(13, HIGH); //green on

        setAlarmMode = true;
      }
      break;

Now I would insert this code outside of the `if (Serial.available() > 0)` code block:

    // Read sensors
    if (setAlarmMode == true)
      {
        Serial.println("Reading sensors");
        int light;
        light = analogRead(0);
        Serial.print("Light sensor value: ");
        Serial.print(light);

        unsigned long distance;

        // Do trigger pulse
        digitalWrite(2, LOW);
        delayMicroseconds(2);
        digitalWrite(2, HIGH);
        delayMicroseconds(10);
        digitalWrite(2, LOW);

        distance = pulseIn(4, HIGH);
        distance = distance / 58; //centimeters
        Serial.print("   Distance sensor value: ");
        Serial.println(distance);

        if (light < 400)
        {
          Serial.println("Light below threshold");
          setAlarmMode = false;
          activateAlarm();
        }

        if (distance < 50)
        {
          Serial.println("Distance below threshold");
          setAlarmMode = false;
          activateAlarm();
        }

        delay(500);
      }

I have also created a function to hold the common code of showing the alarm:

    void activateAlarm(void)
    {
      digitalWrite(12, HIGH); //red on
      digitalWrite(13, LOW); // green off
      digitalWrite(14, LOW); //yellow off
      tone(16, 832);
      delay(500);
    }