title: Writing to a specific I2C register

text:
# Question
Title: Writing to a specific I2C register
I am trying to write to a specific register, but value doesn't change.

Working with SenseAir Sunrise CO2: Info from i2c guideline from sensor manufacter https://rmtplusstoragesenseair.blob.core.windows.net/docs/Dev/publicerat/TDE5531.pdf

> Measurement Period (EE) 0x96 (MSB) 0x97 (LSB)
>
> Measurement period in seconds (range from 2 to 65534). Odd numbers will be rounded up to nearest even number. A system reset is required after changing configuration. Default value is 16.

And that's my code snippet

```
#include <Wire.h>

/* WARINING!!!
  Some wire driver implementations do not corectly implement Wire.endTransmission(false) function,
  so please check this before disable WIRE_WORKAROUND!
  For example, known "bad" implementations are: Nucleo STM32
 */
#define WIRE_WORKAROUND   (0)

#define LED_BUILTIN 2

/* Define serial EN pin */
const int       SUNRISE_EN              = 4;

/* Sunrise communication address, both for Modbus and I2C */
const uint8_t   SUNRISE_ADDR            = 0x68;

/* Amount of wakeup attempts before time-out */
const int       ATTEMPTS                 = 5;
/* It takes 25ms to write one EE register */
const int       EEPROM_UPDATE_DELAY_MS   = 25;

/* Register Addresses */
const uint8_t ERROR_STATUS             = 0x01;
const uint8_t MEASUREMENT_MODE         = 0x95;
const uint8_t METER_CONTROL            = 0xA5;

/* Reading period, in milliseconds. Default is 4 seconds */
int readPeriodMs = 2000;

void setup()
{
  /* I2C */
  /* Initialize I2C and use default pins defined for the board */
  reInitI2C();

  Serial.begin(115200);

  Serial.println("Initialization complete\n");

  change_measurement_period(SUNRISE_ADDR);

  /* Read the sensor's configs */
  Serial.println("Sensor Measurement Configurations:");
  read_sensor_config(SUNRISE_ADDR);
  Serial.println();
}

void change_measurement_period(uint8_t target) {
  /* Function variables */
  int error;

  /* Wakeup */
  if(!(_wakeup(target))) {
    Serial.print("Failed to wake up sensor.");
    /* FATAL ERROR */
    while(true);
  }

  Serial.println("Changing Measurement Period...");

  uint16_t mPeriod = 12;

  Wire.beginTransmission(target);
  Wire.write(0x96);
  Wire.write(highByte(mPeriod));      // sends MSB
  Wire.write(lowByte(mPeriod));       // sends LSB
  error = Wire.endTransmission(true);
  delay(EEPROM_UPDATE_DELAY_MS);

  if(error != 0) {
    Serial.print("Failed to send request. Error code: ");
    Serial.println(error);
    /* FATAL ERROR */
    while(true);
  }

  Serial.println("\n\n\nSensor restart is required to apply changes\n\n\n");
}

/**
 * @brief  Reads and prints the sensor's current measurement mode,
 *         measurement period and number of samples.
 *
 * @param  target: The sensor's communication address
 * @note   This example shows a simple way to read the sensor's
 *         measurement configurations.
 * @retval None
 */
void read_sensor_config(uint8_t target) {
  /* Function variables */
  int error;
  int numBytes = 7;

  /* Wakeup */
  if(!(_wakeup(target))) {
    Serial.print("Failed to wake up sensor.");
    return;
  }

  /* Request values */
  error = WireRequestFrom(target, numBytes, MEASUREMENT_MODE /* from address*/, true /* STOP*/);
  if(error != numBytes ) {
    Serial.print("Failed to write to target. Error code : ");
    Serial.println(error);
    return;
  }

  /* Read values */
  /* Measurement mode */
  uint8_t measMode = Wire.read();

  /* Measurement period */
  uint8_t byteHi = Wire.read();
  uint8_t byteLo = Wire.read();
  uint16_t measPeriod = ((int16_t)(int8_t) byteHi << 8) | (uint16_t)byteLo;

  /* Number of samples */
  byteHi = Wire.read();
  byteLo = Wire.read();
  uint16_t numSamples = ((int16_t)(int8_t) byteHi << 8) | (uint16_t)byteLo;

  /* ABCPeriod */
  byteHi = Wire.read();
  byteLo = Wire.read();
  uint16_t abcPeriod = ((int16_t)(int8_t) byteHi << 8) | (uint16_t)byteLo;

  /* Most propable that the sensor will not go into sleep mode, but to be insure...*/
  /* Wakeup */
  if(!(_wakeup(target))) {
    Serial.print("Failed to wake up sensor.");
    return;
  }

  /* Request values */
  error = WireRequestFrom(target, 1, METER_CONTROL /* from address*/, true /* STOP*/);
  if(error != 1 ) {
    Serial.print("Failed to write to target. Error code : ");
    Serial.println(error);
    return;
  }

  uint8_t meterControl = Wire.read();

  Serial.print("Measurement Mode: ");
  Serial.println(measMode);

  readPeriodMs = measPeriod * 1000;

  Serial.print("Measurement Period, sec: ");
  Serial.println(measPeriod);

  Serial.print("Number of Samples: ");
  Serial.println(numSamples);

  if((0U == abcPeriod) ||  (0xFFFFU == abcPeriod) || (meterControl & 0x02U)) {
    Serial.println("ABCPeriod: disabled");
  } else {
    Serial.print("ABCPeriod, hours: ");
    Serial.println(abcPeriod);
  }

  Serial.println("MeterControl: ");
  Serial.println("Bit [0]:" + (String)bitRead(meterControl,0));
  Serial.println("Bit [1]:" + (String)bitRead(meterControl,1));
  Serial.println("Bit [2]:" + (String)bitRead(meterControl,2));
  Serial.println("Bit [3]:" + (String)bitRead(meterControl,3));
  Serial.println("Bit [4]:" + (String)bitRead(meterControl,4));
  Serial.println("Bit [5]:" + (String)bitRead(meterControl,5));
  Serial.println("Bit [6]:" + (String)bitRead(meterControl,6));
  Serial.println("Bit [7]:" + (String)bitRead(meterControl,7));
  Serial.println(meterControl, BIN);

}

/* Initialize I2C bus and pins */
void  reInitI2C() {
  /* Initialize I2C and use default pins defined for the board */
  Wire.begin();
  /* Setup I2C clock to 100kHz */
  Wire.setClock(100000);
}

/* Workaround regarding BAD implementations of Wire.endTransmission(false) function */
int WireRequestFrom(uint8_t dev_addr, uint8_t bytes_numbers, uint8_t offset_to_read, bool stop) {
 int error;
#if (WIRE_WORKAROUND == 1)
 error = Wire.requestFrom((uint8_t)dev_addr, (uint8_t)bytes_numbers /* how many bytes */, (uint32_t)offset_to_read /* from address*/, (uint8_t)1/* Address size - 1 byte*/, stop /* STOP*/);
#else
  Wire.beginTransmission(dev_addr);
  Wire.write(offset_to_read); //starting register address, from which read data
  Wire.endTransmission(false);
  error = Wire.requestFrom((uint8_t)dev_addr, (uint8_t)bytes_numbers /* how many bytes */, (uint8_t)stop /* STOP*/);
#endif
  return error;
}

/**
 * @brief  Wakes up the sensor by initializing a write operation
 *         with no data.
 *
 * @param  target:      The sensor's communication address
 * @note   This example shows a simple way to wake up the sensor.
 * @retval true if successful, false if failed
 */
bool _wakeup(uint8_t target)
{
  int attemps = ATTEMPTS;
  int error;

  do {
    uint8_t byte_0;
    /* */
    Wire.beginTransmission(target);
    error = Wire.endTransmission(true);
  } while(((error != 0 /*success */) && (error != 2 /*Received NACK on transmit of address*/) && (error != 1 /* BUG in STM32 library*/)) && (--attemps > 0));
  /* STM32 driver can stack under some conditions */
  if(error == 4) {
    /* Reinitialize I2C*/
    reInitI2C();
    return false;
  }
  return (attemps > 0);
}

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

}

```

Mostly i use that code, but it's not have an snippet with writing random number in register with MSB&LSB: https://github.com/Senseair-AB/Sunrise-Examples---Arduino/blob/master/examples/i2c/sunrise\_i2c\_continuous/sunrise\_i2c\_continuous.ino

i reset sensor hardware(physically push the reset button and toogle power from sensor) after data was written and also i wait until all bytes are written `delay(EEPROM_UPDATE_DELAY_MS);` Also i read the sensor configuration after startup, and i see that values of registers doesn't change.

Problem in function **change\_measurement\_period**

What am i doing wrong? maybe someone can help with that?

# Answer
My main goal was to use the opportunity to get the value compensated by atmospheric pressure. But for this it was necessary to understand how to write in registers.

And did not understand what was the problem in the examples of code provided by the manufacturer, it did not correctly work with writing to register 2 bytes data or і did something wrong (most likely). So I rewrote it with the help of a man from the Arduino forum, and now everything works fine.

```
    //Write pressure value to register BAROMETRIC_PRESSURE_VALUE
    int16_t co2Pre = 9772; //977.2 hPa

    // The wake-up is a write command to the I2C address of the sensor.
    Wire.beginTransmission(SUNRISE_ADDR);
    Wire.endTransmission();                   // ignore the return value

    Wire.beginTransmission(SUNRISE_ADDR);
    Wire.write(BAROMETRIC_PRESSURE_VALUE);
    Wire.write(highByte(co2Pre));      // sends MSB
    Wire.write(lowByte(co2Pre));       // sends LSB
    error = Wire.endTransmission(true);
    delay(50);

    if( error != 0) Serial.println( "ERROR, can't find the sensor");

```

```
  int WireRequest(byte target, byte regAddr, int numBytes) {
  // The wake-up is a write command to the I2C address of the sensor.
  Wire.beginTransmission(target);
  Wire.endTransmission();                   // ignore the return value

  // Set register address of the sensor
  Wire.beginTransmission(target);
  Wire.write(regAddr);                        // register address
  int error = Wire.endTransmission(false); // false for a repeated start

  if( error != 0) {
    Serial.println( "ERROR, can't find the sensor");
    return 1;
  }

  // Read the temperature (two bytes, representing a signed integer)
  int n = Wire.requestFrom(target, numBytes);       // request 2 bytes

  if( n != numBytes) {
    Serial.println( "ERROR, can't read data");
    return 1;
  }

  return 0;
}

    //read BAROMETRIC_PRESSURE_VALUE
    error = WireRequest(SUNRISE_ADDR, BAROMETRIC_PRESSURE_VALUE, 2);
    if(error != 0) {
      Serial.println( "Failed to write to target.");
      while(true);
    }
    msb = (byte) Wire.read();
    lsb = (byte) Wire.read();
    int16_t co2Pressure = word( msb, lsb);
    float co2PressureValue = float( co2Pressure) / 10;
    Serial.println("BAROMETRIC_PRESSURE_VALUE: " + (String) co2PressureValue);

```

And also working code snippets for writing registers, that need sensor restart, later i physically restart the sensor, but now do it in code.

```
    // The wake-up is a write command to the I2C address of the sensor.
    Wire.beginTransmission(SUNRISE_ADDR);
    Wire.endTransmission();                   // ignore the return value

    Wire.beginTransmission(SUNRISE_ADDR);
    Wire.write(MEASUREMENT_PERIOD);
    Wire.write(highByte(mPeriod));      // sends MSB
    Wire.write(lowByte(mPeriod));       // sends LSB
    error = Wire.endTransmission(true);
    delay(50);

    if( error != 0) Serial.println( "ERROR, can't find the sensor");

    //RESTART SENSOR
    // The wake-up is a write command to the I2C address of the sensor.
    Wire.beginTransmission(SUNRISE_ADDR);
    Wire.endTransmission();                   // ignore the return value

    Wire.beginTransmission(SUNRISE_ADDR);
    Wire.write(SENSOR_RESTART_SCR);
    Wire.write(0xFF);
    error = Wire.endTransmission(true);
    if( error != 0) Serial.println( "ERROR, can't find the sensor");

    Serial.println("\n\nSensor restart to apply changes\n\n");

    delay(2500); //Wait after sensor restart

```
> 1 votes

# Answer
As written on page 14 of the linked document (emphasis by me):

> All new written data to register (EE) can be read back **after a sensor reset is completed**.

But it seems as if you don't reset the sensor.

You will need to wait as documented, until all bytes are written.
> 0 votes

---
Tags: i2c, esp32
---


# Question
Title: Atmel SAMD21 microcontroller not making a USB port anymore
My custom board with Atmel SAMD21 microcontroller (same as Arduino MKR Zero) is not making a USB port since yesterday. The board was working fine before that.

Please suggest ways to resolve this issue. What are the possible reasons for such an issue?

Since reset is equivalent to powering the board ON and OFF which has not resolved the issue, can burning the bootloader again help?

Further information:

1. The board seems fine. It powers ON and OFF in the usual manner.
2. This problem with the USB port connection happened while I was trying to upload the code.

The USB pin connections on the board have been checked as well as tested with different USB wires.

Appreciate your help.

# Answer
> 1 votes
**Solutions to the problem:**

1. External Hardware Reset -- using a reset button (that I externally managed to solder using the Reset pin-out) -- to get into bootloader mode and start the program from the beginning

Thanks Majenko, from the comments.

2. Burning bootloader again may also work (theoretically) - I have not tried and tested it.

For detailed understanding - follow this post - https://forum.arduino.cc/t/atmel-samd21-microcontroller-not-making-a-usb-port-anymore/882504/5

# Answer
> 0 votes
> **What are the possible reasons for such an issue?**

I noticed that calling

```
Serial.begin(115200);
...
SerialUSB.begin(115200);

```

in the script can cause this.

See post Seeeduino XIAO stopped connecting - Enter Bootloader Mode is not working

---
Tags: samd21g
---


title: Softwareserial send wrong values

text:
# Question
Title: Softwareserial send wrong values
I'm trying to use softwareserial to exchange datas with a sensor. After some tries without any answer from the sensor, I checked the arduino TX with my scope and what I've seen is not what I've sended.

My original byte array (before the setup function):

```
static byte simple_write[] = {0xfe, 0x41, 0x00, 0x80, 0x01, 0x10, 0x28, 0x7e};

```

What I got on my scope:

0X77 , 0x61 , 0x69 , 0x74 , ...

Every single sent byte is wrong. I don't understand why. The only thing on the way is a bridge divider to reduce 5V TTL from the arduino to 3,3V CMOS.

If someone have an idea, thanks in advance.

EDIT2: I use IS.MDuino.21+ (ATmega2560)

EDIT: Here are the parts of my code who involve the softwareserial

```
    #include "SoftwareSerial.h"

    SoftwareSerial LP8_Serial(1, 0);

    static byte simple_write[] = {0xfe, 0x41, 0x00, 0x80, 0x01, 0x10, 0x28, 0x7e}; //Write 0x010 to address 0x0080

void setup(){
LP8_Serial.begin(9600); //Opens the virtual serial port with baud of 9600
}

void loop(){

LP8_val1 = GetDatas_uart();

}

int GetDatas_uart() {
  if (first_loop == 0) {
    //reset_device();  // includes a 500 msec delay
    sendRequest(simple_write, 8, 4); // send to address 0x0080 a 0x10
    first_loop = 1;
  }
  else
    sendRequest(write_to_0x20, 8, 4); // send to address 0x0080 a 0x10
  delay(2000);
  unsigned long valCO2 = getValue(response);
  delay(3000);
  Serial.println("Now reading 32 bytes");   //sendRequest(read_16_bytes,7,21);
  sendRequest(read_32_bytes, 7, 37);
  Serial.print("CO2 from 0x9a-0x9b = ");
  Serial.print(response[29], HEX);
  Serial.print(response[30], HEX);
  Serial.print(" = ");
  int decimal = 256 * response[29] + response[30];
  Serial.print(decimal);
  Serial.println("d");

  return decimal;
}

void sendRequest(byte packet[], int m, int n)
{
  while (!LP8_Serial.available()) //keep sending request until we start to get a response
  {
    Serial.println("waiting for Software.serial port availability");
    LP8_Serial.write(packet, m);
    //LP8_Serial.write(simple_write, m);
    delay(1000); // Necessary to get consistent loading of response[i]
  }
  int timeout = 0; //set a timeout counter
  while (LP8_Serial.available() < n ) //Wait to get a n byte response
  {
    timeout++;
    if (timeout > 10) //if it takes too long there was probably an error
    {
      while (LP8_Serial.available()) //flush whatever we have
        LP8_Serial.read();
      break; //exit and try again
    }
    delay(50);
  }
  for (int i = 0; i < n; i++)
  {
    response[i] = LP8_Serial.read();
    //    Serial.print("response[i] = ");
    Serial.print("response[");
    Serial.print(i);
    Serial.print("] = ");
    Serial.println(response[i], HEX);
  }
  Serial.print("\n\n");
  Serial.flush();
}

```

# Answer
> 2 votes
Sooo, I feel a little ashamed...

After re-reading the documentation of the Arduino from Industrial Shields I use (model 21+), I discovered that using Serial0 on this board is unadvised because these pins are shared with USB.

I connected my serial wires to the Serial1 connection and now, my scope show me exactly what I wanted to see on my TX line.

Sorry for that. Like often, the problem whas between the screen and the chair.

Thanks,

---
Tags: softwareserial, atmega2560
---


# Question
Title: No response from instrument via serial communication
I am using a Teensy 3.6 to communicate with an external instrument via a serial connection. However, I am not able to get the instrument to respond to my commands. The idea is to send a command from the computer via the serial monitor to the Teensy, which then can send it to the instrument (I know that the Teensy is not needed with this configuration but this is just for testing of a more complex set-up). The instrument uses an RS232 connector so I use this RS232 shifter to connect it to the Teensy. The serial communication settings of the instrument are: 38.4k baud rate, 8 data bits, 1 stop bit, no parity and a carriage return character should mark the end of the command string.

A simple example of my code to read the input from the serial monitor and send a command to the instrument:

```
#define FILTser Serial1
char Command;

void setup() {
  Serial.begin(9600);
  FILTser.begin(38400);
  Serial.println("<Teensy is ready>");
}

void loop() {
    Command = 'X';
    recvCmd();

    // Start sampling command
    if (Command == 'S') {
       FILTser.write("pumpctl=1\r");
       FILTser.write('\n');
       Serial.println("Sampling started");
    }
}

void recvCmd() {
    if (Serial.available() > 0) {
        Command = Serial.read();
    }
}

```

If I read the output from the Teensy on the Serial1 port with Putty I get the message correctly. If I send the same command directly to the instrument with Putty or Python I get the instrument to respond as I expect. This means that the instrument is working and the serial output from the Teensy is also fine so I really don't understand what could be wrong.

I know that the instrument is not responding because I would expect a pump to turn on when it receives the command. Additionally, I tried to read the answer of the instrument on the serial port and I was receiving a `-1` but I would expect `OK` for a good command and `ERR` if the command is not recognized.
To read the instrument answer on the serial port I tried using both a single character with `Response = FILTser.read();` and also a full string using the code from here.

An example of the Python code that I use to send commands to the instrument is the following:

```
import datetime
import serial
import io
import time

# =============================================================================
# Configure serial port
# =============================================================================
ser = serial.Serial()
ser.baudrate = 38400
ser.port = 'COM5'
ser.timeout = 1

#%% Define FILT functions
def FILT_send(commnd):
    ser.write(commnd.encode('ascii'))
    time.sleep(0.5)
    value_read = ser.readline().decode('ascii')
    return(value_read)

def FILT_control():
    global q
    user_input = input('Type:\n \
    - S to start sampling\n \
    - E to end sampling\n \
    - Q to quit the program\n')

    if user_input == 'S':
        FILT_send('pumpctl=1\r')
        print('Sampling started')

    if user_input == 'E':
        FILT_send('pumpctl=0\r')
        print('Sampling ended')

    if user_input == 'Q':
        print('The end')
        q = False

#%% Main
ser.open()
q = True
while q:
    FILT_control()
ser.close()

```

# Answer
The Sparkfun RS232 shifter is not a great device. It relies on whatever it's connected to (on the 9-pin port) providing the negative rail for the EIA-232 voltage levels.

That's fine when you connect to something that *has* those voltages available, such as a computer, but many "devices" don't - they will themselves have a similar shifter inside and will rely on whatever *they* are plugged in to for providing the needed negative voltage.

Put the two together and *no-one* will provide that negative voltage.

Instead you should use a MAX232 (or MAX3232 for 3.3V operation) based converter. This has a built-in voltage doubler and voltage inverter to convert the 5V into +/-10V to give a proper EIA-232 compliant signal which the device should then be happy with.
> 3 votes

---
Tags: serial, communication, teensy
---


# Question
Title: HC-05 Stuck in slave loop mode (loopback)
got my HC-05 today and accidently set the AT+ROLE=2(slave loop) and now I can't get out of it! Anything I send it just resends it back to me, even commands like AT+RESET and AT+ORGL, they just get returned. I can't figure out how to put the device back in slave mode, your help would be highly appreciated!

# Answer
> 1 votes
H., you have to connect the module in the natural configuration mode to receive AT commands by default, which it is at 38400 Baud. Try sending AT with the arduino console (with carreturn and new line control). If this works then send AT+MODE=0. Also, from here, you can send AT+ORGL to set original from factory. I usually use a CP2102 usb-serial interface with the hc-05 module, and the YAT serial terminal program from windows, because it is comfortable for me. Greetings. jvarl.

---
Tags: hardware, hc-05
---


# Question
Title: How do I check if my board is connected to the internet?
Let me get this straight, I'm trying to see my ESP32 is connected to the **internet** or not, not Wi-Fi, as at times the board is able to connect to Wi-Fi, but not able to contact any servers, due to router issues.

I want to check, if the board is connected the internet or not, how do I do this?

What I have so far:-

```
char ssid[] = "Youreally";
char pass[] = "WannaKnow";

void setup(){
WiFi.begin(ssid, pass);
Serial.begin(115200);
}

void loop(){
  if (WiFi.status() != WL_CONNECTED) {
  Serial.println("Connected");
  }
}

```

# Answer
As you would be having some sort of connectivity except WiFi you could check that on regular basis in your loop, for instance when using MQTT I would check:

```
if (!mqttClient->connected())

```

and then based on the result I would test:

```
if (WiFi.status() != WL_CONNECTED)

```

so I can handle the relevant layer.
> 0 votes

---
Tags: wifi, esp32
---


# Question
Title: How to avoid electromagnetic interference on ESP32 input
I've realized a simple circuit like the following, in order to implement a rain gauge that I can access via HTTP:

With the following sketch:

```
#include <WebServer.h>
#include <WiFi.h>
#include <WiFiClient.h>

/**
 * This constant is calculated with the following procedure:
 * - Area of pluviometer is 55 cm^2
 * - Volume of test water is 100 cm^2
 * Resulting height of water is 1.82 cm. Using this water quantity, generates 40 ticks of the pluviometer. So every tick is 0.455 mm of rain.
 */
const double millimetersPerTick = 0.455;
const char* ssid = "*********";
const char* password = "*********";

WebServer server(80);

/* LED pin */
byte ledPin = 2;
/* pin that is attached to interrupt */
byte interruptPin = 14;
/* hold the state of LED when toggling */
volatile byte state = LOW;
volatile int interruptCounter = 0;
int numberOfInterrupts = 0;
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;

void IRAM_ATTR handleInterrupt() {
  portENTER_CRITICAL_ISR(&mux);
  interruptCounter++;
  portEXIT_CRITICAL_ISR(&mux);
}

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

  // WIFI initialization
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  pinMode(ledPin, OUTPUT);
  /* set the interrupt pin as input pullup*/
  pinMode(interruptPin, INPUT_PULLUP);
  /* attach interrupt to the pin
  function blink will be invoked when interrupt occurs
  interrupt occurs whenever the pin change value */

   // Notify wifi connection
  digitalWrite(ledPin, HIGH);
  delay(2000);
  digitalWrite(ledPin, LOW);

  attachInterrupt(digitalPinToInterrupt(interruptPin), handleInterrupt, RISING);

  server.on("/", []() {
    server.send(200, "text/plain", String(millimetersPerTick * numberOfInterrupts));
    numberOfInterrupts = 0;
  });

  server.onNotFound([]() {
    server.send(404, "text/plain", "Not found");
  });

  server.begin();
}

void loop() {
  server.handleClient();

  if(interruptCounter>0) {
    portENTER_CRITICAL(&mux);
    interruptCounter--;
    portEXIT_CRITICAL(&mux);

    numberOfInterrupts++;
    Serial.print("An interrupt has occurred. Total: ");
    Serial.println(numberOfInterrupts);
    state = !state;
    digitalWrite(ledPin, state);
    delay(100);
    state = !state;
    digitalWrite(ledPin, state);
  }
}

```

The main issue of this circuit is that if I connect the AC plug it suffers from interferences from the household electricity. For example if I turn on the light, the interrupt is called. I tried also to buy an EMI filter like this but it doesn't reduce the problem. What can I do to avoid this?

# Answer
I researched the power supply shown in your photo and found this comment:

esp8266 hilink
> 1 votes

---
Tags: esp8266, interrupt, input, esp32
---


# Question
Title: which is the best way to declare Serial while creating Arduino library?
Well, I am trying make a library for HMI display. display and Arduino comminicate with Serial. So I will so many times Serial port. Generally I will use **Serial.write** commend. if I examine other libraries, there are lots way to declare serial. Why and which is the best I want to learn.

there I have seen declaring Serial methods.

**Method 1**

in library .h file

```
nothing

```

in library .cpp file

```
#include <SoftwareSerial.h>

SoftwareSerial SIM(RX_PIN,TX_PIN);

void KapadokyaGSM::basla(){
    SIM.begin(9600);
  _tampon.reserve(255);
}

```

**Method 2**

in library .h file

```
public:
EasyNex(HardwareSerial& serial);
...
private:
HardwareSerial* _serial;
...

```

in library .cpp file

```
EasyNex::EasyNex(HardwareSerial& serial){  // Constructor's parameter is the Serial we want to use
_serial = &serial;
}

void EasyNex::begin(unsigned long baud){
_serial->begin(baud);  // We pass the initialization data to the objects (baud rate) default: 9600
delay(100);            // Wait for the Serial to initialize

```

Also I have seen declaring with Stream but now i didnt find example codes. So finally **Can anyone tell me what is the best for declearing Serial in library.** it can be for only hardware serial or both

# Answer
> 4 votes
As regards the use of `Stream`:

I usually use `Stream` instead of `HardwareSerial` because:

* It allows the use of other serial devices, like `SoftwareSerial` or `USBSerial` that aren't "Hardware" UARTs.
* It even allows the use of non-serial systems, like sending data over networks or wireless devices

However it means:

* The user has to manually initialize their serial object / device as `Stream` has no facility for setting things like baud rates.

# Answer
> 1 votes
There is no best way, the first is using a global variable, being static. The second is dynamically (or at least to pass a serial instance).

It depends on your use

* If you want your code always to work with the same declared serial (hardware or serial) instance, you can use the first method, as it is the easiest.
* If you want your serial hardware port to be flexible (your code to work e.g. with a selectable hardware serial port on an Arduino Mega), you need the second.
* If you want to your serial port to be either software or hardware, you can use the second method, but you need another type (not the mentioned `HardwareSerial` class. I don't know by head the parent class of `SoftwareSerial` and `HardwareSerial` (The `Stream` class you mentioned could be a common parent class).

---
Tags: arduino-uno, serial, library, softwareserial, serial-data
---


# Question
Title: How can i reduce my global variable use? Attiny85
I'm trying to compile my code but i keep exceeding my global variable memory by 12%. Is there anything i can do in my code to further reduce RAM usage? Or do i have to do modifications to the libraries I'm using? Here is my main program:

```
    #include <MIDI.h>
#include <FastLED.h>
#include <SoftwareSerial.h>

#define LED_PIN 3
#define NUM_LEDS 60
#define LEDMAP 0xAB5AB5AB5AB5AB5
#define OFFSET 36
#define RANGECHECK if (pitch > 35 && pitch < 96)

SoftwareSerial softSerial(2, 4);
CRGB leds[NUM_LEDS];

MIDI_CREATE_INSTANCE(SoftwareSerial, softSerial, midiB);

void setup() {
  FastLED.addLeds<WS2811, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.clear(true);
  midiB.begin(MIDI_CHANNEL_OMNI);
  midiB.setHandleNoteOn(HandleOn);
  midiB.setHandleNoteOff(HandleOff);
}

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

void HandleOn(byte channel, byte pitch, byte velocity)
{
  RANGECHECK
  {
    leds[pitch - OFFSET] = bitRead(LEDMAP, (pitch - OFFSET)) ? CRGB::NavajoWhite : CRGB::Salmon;
    FastLED.show();
  }
}

void HandleOff(byte channel, byte pitch, byte velocity)
{
  RANGECHECK
  {
    leds[pitch - OFFSET] = CRGB::Black;
    FastLED.show();
  }
}

```

I've reached my limit in optimizing my RAM usage here. Any suggestions for optimizing my code would be appreciated.

# Answer
Since i don't use sysex messages, i got my RAM usage down to 84% by setting the `SysExMaxSize`

in `midi_settings.h` to 0.
> 1 votes

# Answer
FastLED needs to keep the colors of all the pixel in RAM, so that is using a lot of RAM.

To get around this, you could use a strategy that generates the pixel data on the fly as you send it out to the strings. Here is an example of a project that does that...

https://wp.josh.com/2021/04/21/build-a-live-scrolling-tickertape/

Also, SoftSerial keeps a buffer (looks like 64 bytes?) which also uses some RAM. You could use a different approach to serial communications that does not allocate such a large buffer. It would take work, but you could even process the midi bytes as they were received and not need any byte buffer.
> 3 votes

---
Tags: c++, attiny, memory-usage, attiny85, sram
---


# Question
Title: ESP8266 spend 10mA, even though It is in the deep sleep mode
I am using Nodemcu ESP8266. I want to know how much my ESP board consume the battery during sleep mode. as the Mannual said it spend about micro-ampere, but my multi meter said it spend 10 mili-ampere, I cannot believe the result.

so please see My arrangement is right and give some advice

arrangement image

red line is for vin, black line is for GND. black pin is COM, red pin is mA.

I set multimeter on 20mA, 200mA, it said it is 10mA. when I change multimeter to 10mA, 1mA, microAmpere, number was overflowed.

I already connected to RST - D0, so It is properly sleep & wake up automatically. and here is my running code in the board

```
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>

void setup() {

}

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

ESP.deepSleep(60e6);

}

```

# Answer
`ESP.deepSleep(60e6, WAKE_RF_DEFAULT);` Try this code, it should decrease it a bit.
> 1 votes

# Answer
The Board you are using contains an ESP-12F Module, along with other chips that make it easy/possible to connect to UART over USB and thus flash the chip. This USB-to-UART converter chip isn't related to the ESP-12F Module, so is unaffected when the ESP goes to sleep, so the converter continues to draw about 10mA. You can't do anything about this unless you desolder it, or use a pure ESP-12F Module.
> 1 votes

---
Tags: esp8266, nodemcu, sleep
---


# Question
Title: WiFi.h library, Issues with client.print()
I have an esp32 development board that I am trying to use to get Bitcoin price data using the Coinbase api.

On the Coinbase developers website, they give this example Curl command to get Bitcoin price data:

```
curl https://api.coinbase.com/v2/prices/spot?currency=USD

```

I put this into a command prompt on my computer and it works as expected. So I used this as a template for my HTTP get statement in my Arduino sketch.

```
if (!client.connect("api.coinbase.com",80)) {
  Serial.println("Connection failed.");
}
delay(100);
client.print("GET /v2/prices/spot?currency=USD HTTP/1.1\r\nHost: api.coinbase.com\r\n\n");

```

However, when sent from my esp32, I get a "301 Moved Permanently" error. But the new Location specified in the response is exactly where I was accessing in the first place!

```
HTTP/1.1 301 Moved Permanently
Date: Sun, 22 Aug 2021 22:15:50 GMT
Transfer-Encoding: chunked
Connection: keep-alive
Cache-Control: max-age=3600
Expires: Sun, 22 Aug 2021 23:15:50 GMT
Location: https://api.coinbase.com/v2/prices/spot?currency=USD
Set-Cookie: __cf_bm=ea2a2031c3fa42b910632c627d2ed4c48824323d-1629670550-1800-ARKBVsdI9BWVOOTWmKXp+cMv0hcxMU4YAOR1JyHtH2Q49TEBkGuGNXLxSMIanzC7W8Ga9uXBCtdo+Th7Fgir8Jc=; path=/; expires=Sun, 22-Aug-21 22:45:50 GMT; domain=.coinbase.com; HttpOnly
X-Content-Type-Options: nosniff
Server: cloudflare
CF-RAY: 682f764a88f3a3eb-PIT

```

Why does this HTTP request work with Curl, but not when sent from the esp32?

# Answer
> 1 votes
It's not an error, it's an HTTP redirect.

The HTTP request worked as expected on the ESP32. Curl automatically handles the redirect. Your homegrown HTTP implementation does not.

The Coinbase API requires you to use HTTPS and does not allow HTTP. This protects private information, like API keys and information the API may return. It also verifies that you're talking to the real Coinbase API server and not an impersonator.

You'll need to use port 443 and the `WiFiClientSecure` library instead of `WiFiClient` library. Or even better, you could use an HTTP client that already implements the HTTP protocol, like `HTTPClient`.

---
Tags: wifi, esp32, http
---


# Question
Title: Stopping / starting DC motor with Limit Switches and on/off button
I have an Arduino UNO with 3 switches attached (2 limit switches, 1 activation switch). I'm trying to make the activation switch turn the motor forwards once hit, then wait for any of the limit switches to be hit and stop the motor. The next step is to wait for the activation switch to be hit again and turn the motor in the opposite direction and wait for the limit switch to be hit and stop the motor.

But the issue I'm facing right now is when i press the activation switch the arduino board and H bridge board restart. The LED's turn on and off and the code restarts. And nothing happens. I know all the switches and motor is working because i have tested them by simplifying the code with just the functions.

(edit) Here is a picture of the schematic:

Can someone please review my code below to see if my logic is correct.

```
const byte  frontButtonPin = 2;
const byte  backButtonPin = 4;
const byte  onOffButtonPin = 11;
const int   motorPin =  8;
const int   motorPin2 =  7;

boolean  frontButtonState = 0;
boolean  backButtonState = 0;
boolean  onOffButtonState = 0;

/**
    setup inputs for switches and outs for motor pins
    serial begin to read the switches to test for errors
*/
void setup() {
  // initialize the pin as an inputs:
  pinMode(motorPin, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(frontButtonPin, INPUT);
  pinMode(backButtonPin, INPUT);
  pinMode(onOffButtonPin, INPUT);
  Serial.begin(9600);
}

/**
   this function turns motor foward
*/
void drawMovesForward() {
  // turn motor foward:
  digitalWrite(motorPin, LOW);
  digitalWrite(motorPin2, HIGH);
}

/**
   this function turns motor backwards
*/
void drawMovesBackward() {
  // turn motor in other direction:
  digitalWrite(motorPin, HIGH);
  digitalWrite(motorPin2, LOW);
}

/**
   Stop the motor form moving
*/
void stopDrawFromMoving() {
  digitalWrite(motorPin, LOW);
  digitalWrite(motorPin2, LOW);

}

/**

*/
void loop() {

  frontButtonState = digitalRead(frontButtonPin);
  backButtonState  = digitalRead(backButtonPin);
  onOffButtonState = digitalRead(onOffButtonPin);

  if (onOffButtonState == HIGH) {
    if ( frontButtonState == LOW ) {
      drawMovesForward();

    }

    else if (backButtonState == LOW ) {
      drawMovesBackward();
    }

  }
  else {
    if ( frontButtonState == HIGH ) {
      stopDrawFromMoving();
    }

    else if (backButtonState == HIGH ) {
      stopDrawFromMoving();
    }
  }
}

```

# Answer
> 4 votes
I know this was opened years ago now but I just wanted to add some clarification. When I started this project and created this question I had 0 understanding of software development and didn't understand the code I was writing at the time. Now 3 years later I have revised this project multiple times.

The logic for a project like this is pretty simple, but if you're new to programming and trying to get into the STEM field with Arduino school projects and such, here is what my code now looks like for this same project: https://github.com/LeehamElectronics/Automated-Cabinet

I have tried to comment it as best I could to help other students understand it. The project is simply a timber cabinet that has an electrically automated draw inside that can be opened and closed at will.

If you are stuck with a similar problem with your own project, I would suggest that you watch a free YouTube video course for C++ programing or even a Arduino programming video course. Even just a few hours of doing that will be enough to get started. That's the one thing I wish someone told me to do when I was starting off 3 years ago, I was wasting hours and hours debugging code that I didn't understand because I just jumped straight into Arduino with little understanding of coding.

I hope this comment helps someone else out there in a similar situation to mine 3 years ago.

Cheers

edit: the answers given about debouncing and pull-up resistors are also important in these types of projects.

# Answer
> 5 votes
**Check your switches have pull-up resistors**

It would be helpful if your question included a schematic. Do you have pullup resistors in line with your activation and limit switches? If not, you might find the input is "floating" - that is, it will randomly return either HIGH or LOW. This would possibly cause the motor to go forwards and backwards, but because the loop is possibly occurring hundreds of times per second, you might not see anything moving. You need pull-up or pull-down resistors in the circuit so the Arduino can see a definite LOW or HIGH. See https://www.arduino.cc/en/Tutorial/Button for a tutorial with a resistor, or even better, use https://www.arduino.cc/en/Tutorial/InputPullupSerial and use the existing onboard pullup resistors on the Arduino, as suggested by Juraj below.

**Potential Logic Error**

There might be a logic error in this part of the code:

```
  if (onOffButtonState == HIGH) {
    if ( frontButtonState == LOW ) {
      drawMovesForward();
    }
    else if (backButtonState == LOW ) {
      drawMovesBackward();
    }
  }
  else {
    if ( frontButtonState == HIGH ) {
      stopDrawFromMoving();
    }
    else if (backButtonState == HIGH ) {
      stopDrawFromMoving();
    }
  }

```

Loop #1: Let's say the *onOffButtonState* is HIGH (someone has pressed the switch to ON). The drawer is closed, so the front limit switch is depressed, so *frontButtonState* is HIGH. So the program will execute **stopDrawFromMoving**, and do nothing. Currently you are saying nothing is happening, so this might be your issue.

What you will probably need to do is use flags and while loops. For example:

At the start of the loop() declare this

```
drawerMovingOutFlag = 1;

```

Then change the loop to contain:

```
if (onOffButtonState == HIGH) {
    if ( frontButtonState == HIGH ) {
        while(drawerMovingOutFlag == 1)
            drawMovesForward();
            if ( backButtonState == HIGH ) {
                drawerMovingOutFlag = 0;
                stopDrawFromMoving()
            }
        }
    }
    else ...

```

I'll let you do the rest!

# Answer
> 3 votes
I actually had the right code all along but I just had to add delays when reading the limit switches and detecting the activation switches. Here is one of the original programs i wrote that i threw out thinking it doesnt work, but once the delays were added it works fine.

```
// constants won't change. They're used here to set pin numbers:
const int buttonPin = 4;     // the number of the pushbutton pin
const int buttonPin3 = 11;     // the number of the pushbutton pin
const int buttonPin2 = 2;     // the number of the pushbutton pin
const int motorPin =  8;      // the number of the LED pin
const int motorPin2 =  7;      // the number of the LED pin

// variables will change:
boolean buttonState = 0;         // variable for reading the pushbutton status
boolean buttonState2 = 0;         // variable for reading the pushbutton status
boolean buttonState3 = 0;   // variable for reading the pushbutton status

int drawPosition = 2;  // Tells progam what position the draw is in

/**
 *  setup inputs for switches and outs for motor pins
 *  serial begin to read the switches to test for errors
 */
void setup() {
    // initialize the pin as an inputs:
    pinMode(motorPin, OUTPUT);
    pinMode(motorPin2, OUTPUT);
    // initialize the pushbutton pin as an input:
    pinMode(buttonPin, INPUT);
    pinMode(buttonPin2, INPUT);
    pinMode(buttonPin3, INPUT);
    Serial.begin(9600);
}

/**
 * this function turns motor foward
 */
void drawForward() {
     // turn motor foward:
     digitalWrite(motorPin, LOW);
     digitalWrite(motorPin2, HIGH);
}

/**
 * this function turns motor backwards
 */
void drawBackward() {
     // turn motor in other direction:
     digitalWrite(motorPin, HIGH);
     digitalWrite(motorPin2, LOW);
}

/**
 * Stop the motor form moving
 */
void stopDrawFromMoving() {
  digitalWrite(motorPin, LOW);
  digitalWrite(motorPin2, LOW);

}

/**
 *
 */
void loop() {
   // read the state of the pushbutton value:
   buttonState = digitalRead(buttonPin);
   buttonState2 = digitalRead(buttonPin2);
   buttonState3 = digitalRead(buttonPin3);

   // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
   if (buttonState == HIGH) {
      drawPosition = 2;
      Serial.println(F("Front button state is high draw is open"));
      stopDrawFromMoving();
   }else if (buttonState2 == HIGH) {
      drawPosition = 1;
      stopDrawFromMoving();
  }

  if (buttonState3 == HIGH) {
    if( drawPosition  == 1 ){
      drawBackward();
      delay(100);
      drawPosition = 2;
      delay(100);
    }else if (drawPosition == 2 ) {
      delay(100);
      drawForward();
      delay(100);
      drawPosition = 1;
    }

  }
}

```

# Answer
> 3 votes
That is an excellent project. Great work.

Some suggestions for improvement. You could use a `enum class byte` instead of a `String` for the drawer position and the drawer moving direction:

```
/* Allows the program to keep track of the last known position of the drawer */
enum class DrawerPositions : byte
{
  Closed,
  Open
} drawerPosition = DrawerPositions::Closed;

/* Keep track of what direction the drawer is moving, can one of the following:  Null | Closing | Opening */
enum class DrawerMovingDirections : byte
{
  Null,
  Closing,
  Opening
} drawerMovingDirection = DrawerMovingDirections::Null;
...
if (drawerPosition == DrawerPositions::Closed)
...
else if (drawerPosition == DrawerPositions::Open)
...
if (drawerMovingDirection == DrawerMovingDirections::Opening)
...

```

It would also be a good idea to add debouncing for all the switch inputs. There are many debouncing algorithms on the internet, but here is a very simple debouncer I put on GitHub which could be implemented something like this:

```
#include "Debouncer.h"
...
void loop()
{
  static Debouncer limitSwitch0(limitSwitchPin0);
  static Debouncer limitSwitch1(limitSwitchPin1);
  static Debouncer manualToggleButton(manualToggleButtonPin);

  limitSwitch0.Update();
  limitSwitch1.Update();
  manualToggleButton.Update();

  if (drawerIsMoving == true)
  {
    if (drawerMovingDirection == DrawerMovingDirections::Opening)
    {
      if (limitSwitch0.Output() == LOW)  // Get the debounced output of the switch.
      {
        drawerPosition = DrawerPositions::Open;
  ...
  if(manualToggleButton.Rise())   // For rising edge trigger.
  //if(manualToggleButton.Fall())  // For falling edge trigger.
  {
    ...
  }
  ...
}

```

Here is a debounce demo I put on Wokwi.

---
Tags: motor
---


# Question
Title: How or why is the Arduino keeping a LED on when the input putton is no longer pressed?
I'm trying to follow lesson 6 of the Adafruit Arduino lessons on digital inputs found here.

I have the same code and the board setup the exact same and the code it **is working** exactly as it should. I just can't figure out ***WHY***.

Board:

Code:

```
    /*
Adafruit Arduino - Lesson 6. Inputs
*/

int ledPin = 5;
int buttonApin = 9;
int buttonBpin = 8;

byte leds = 0;

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(buttonApin, INPUT_PULLUP);
  pinMode(buttonBpin, INPUT_PULLUP);
}

void loop()
{
  if (digitalRead(buttonApin) == LOW)
  {
    digitalWrite(ledPin, HIGH);
  }
  if (digitalRead(buttonBpin) == LOW)
  {
    digitalWrite(ledPin, LOW);
  }
}

```

Why does the light turn on when one of he buttons is pressed once and turn off when the other button is pressed once. I don't understand the mechanism of how the press is being remembered.

There doesn't seem to be anything in the code that can explain why the button stays on even when no longer pressed, so it should be some component? But what?

Can anyone help explain why this is working?

# Answer
I would like to add two more cents. It is a wonderful explanation already from @chrisl Here is the simulation screenshot for your example:

if you consider mechanical switches, they really cut the connection so that the light will be OFF. When you want the light to be on, you will move the switch to the ON position(in this example, hold the button)

In the case of Microcontrollers, and in the given example, it is more like two people communicating.

1. The 1st person is looking at the switches. The 2nd person is controlling the LED
2. 1st person is instructed to notify the second person about anybody pressing the switches
3. whenever the ON switch is pressed, the 1st person will immediately tell the second person to turn on the LED
4. Whenever the OFF switch is pressed, the 1st person will tell the 2nd person to turn off the LED

The behaviour of the program much depends on the requirement.

---

if you would love to see the LED turn OFF when you want to, you can try this example

Code:

```
/*
  Adafruit Arduino - Lesson 6. Inputs
*/

int ledPin = 5;
int buttonApin = 9;
//int buttonBpin = 8;

byte leds = 0;

void setup()
{
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
  pinMode(buttonApin, INPUT_PULLUP);
  pinMode(buttonBpin, INPUT_PULLUP);
}

void loop()
{
  digitalWrite(ledPin, !digitalRead(buttonApin));
}

```
> 2 votes

# Answer
If you read the lesson below the first picture and above parts it states: "Pressing the button nearer the top of the breadboard will turn the LED on, pressing the other button will turn the LED off." Try pressing and expect the LED to turn off.
> 1 votes

# Answer
The press is not being remembered. Instead, the output pin "remembers" its state: `digitalWrite(HIGH)` sets the pin to high and the pin will remain high until you call `digitalWrite(LOW)`.
> 1 votes

# Answer
It might be interesting to look at the reasons why the pin remembers its state (as described in other answers).

Every digital pin has dedicated digital output hardware, which can drive the pin to HIGH (Vcc, supply voltage) or LOW (ground). This output hardware is internally tied to a SFR (Special Function Register). A register is a piece of specific memory hardware in the microcontroller of the Arduino. The digital output hardware is electrically hardwired to some of those special function registers. Thus its state depends on what is saved in those registers. Since the registers hold their state during the running time of the Arduino (they are memory after all), the digital output hardware will also not change, until you change the corresponding registers (through executing `digitalWrite()`).

You can even manipulate the SFRs directly. This can help with programming time sensitive code or setting/reading multiple pins at once. All the digital pins are sorted into so called ports, which can hold up to 8 pins. For each port there are the following SFRs (the `x` stands for the character of the corresponding port, like `PORTA`, `PORTB`, ...), where the bits in these (1 byte big) registers correspond to one pin each:

* `DDRx`: This register is the Data Direction Register. It controls if the corresponding pins are set as digital output or input.
* `PORTx`: This register sets the output state. `digitalWrite(pin, HIGH)` will write a 1 to the corresponding bit of this register, which then sets the pin to HIGH. If the corresponding pin is set as input, setting a 1 in the corresponding bit of the PORT register will enable the interal pullup resistor of that pin.
* `PINx`: This register holds the current state of the corresponding pins, so you can use it to read a digital pin.

You can also read this reference article. Also the datasheet of the used microcontroller also contains all information about what SFRs exist and how they are used to perform specific actions.
> 1 votes

---
Tags: programming
---


title: 5-bit communication method?

text:
# Question
Title: 5-bit communication method?
OK, I'm working on a project where I want to have multiple toggle switches create a "code" to determine further actions. This is essentially 5-bit communication process that will create output with a 32-bit range of outcomes from 00000 to 11111.

I'm testing the method with three switches, so if the first and third switch are HIGH/on it will read 101. Second and third, 011 etc. I'm not versed enough to know if there is a better method here, but is there a better way to do this?

```
    // Define the pins being used
int pin_switch = 10;
int pin_switch2 = 11;
int pin_switch3 = 12;

// create int for 3-digit code
int code = 000;

void setup()
{
    Serial.begin(9600);
    pinMode(pin_switch, INPUT);
    pinMode(pin_switch2, INPUT);
    pinMode(pin_switch3, INPUT);
}

void loop()
{

if pin_switch == HIGH;
    {code += 100;}

if pin_switch2 == HIGH;
    {code += 10;}

if pin_switch3 == HIGH;
    {code += 1;}

Serial.print(code);

// operate based on code output
if code == 101;
    {do 101 stuff}

if code == 001
    {do 001 stuff}

// reset code for next loop so numbers don't keep rising
code = 000;
}

```

# Answer
> 2 votes
It would be more convenient and less typing if you put all your switch pins in an array. That way you can loop over it to configure the ports and read them rather than copy/pasting the "same" code over and over.

The calculation of the resulting code is a classic "shift and add" loop. I put both the decimal version you seem to want and the more "usual" binary version in the snippet below.

The idea behind that sort of loop is:

1. start with an empty (zero) code
2. multiply the code by 10 (or left-shift once for binary)
3. read a switch, add 1 to the code if it is HIGH
4. go back to step 2 if there are more switches.

The value of the switches already read get "pushed" one slot to the left before reading the next switch, resulting in the code you want.

The order in which you list the ports in the array is important: the first port in the array will change the leftmost (most significant) digit/bit in the code.

```
const uint8_t switch_pin[] = { 10, 11, 12 };
const uint8_t num_switches = sizeof(switch_pin)/sizeof(switch_pin[0]);

void setup() {
  // Set all switch pins to input mode
  for (uint8_t i = 0; i < num_switches; ++i) {
    pinMode(switch_pin[i], INPUT);
  }
  Serial.begin(9600);
}

void loop() {
  int code = 0;
  // Read each switch and compute the code
  for (uint8_t i = 0; i < num_switches; ++i) {
    // If the code is supposed to be in decimal
    code = code * 10;
    code += digitalRead(switch_pin[i]);
    /* For a binary version, code only needs to be 8 bits long:
    code <<= 1;
    code |= digitalRead(switch_pin[i]);
    */
  }

  // Do stuff with the code
  Serial.println(code);
  delay(200);
}

```

# Answer
> 2 votes
Unfortunately your code is all over the place. You have to use C/C++ syntax, which you don't. Also you don't actually read any input.

* if statements look like this:

```
  if(condition){
      my_code();
  }

```
* `if(pin_switch == HIGH)` (corrected syntax) will always be false, since `pin_switch` is of value `10`. Its just the pin number. To actually read the pin, you need to use `digitalRead()` like this:

```
  if(digitalRead(pin_switch) == HIGH)

```

or even simpler

```
  if(digitalRead(pin_switch))

```
* It seems that you want to manipulate the bits with `code += 100;`, but the compiler takes numbers as decimal. So you are adding 100 to `code`. Please look into the bitwise operators. Also: You can actually write numbers in binary or hex by using `0b101` or `0xF3` respectively (the values here are just examples). This also means, that `int code = 000;` is the same as `int code = 0;`.

---

To build the 3 digit code from input you could put them together via bitwise operators:

```
code = (digitalRead(pin_switch3) << 2) | (digitalRead(pin_switch2) << 1) | digitalRead(pin_switch);

```

Depending on your used Arduino and the used pins you can get this even easier. The pins are sorted into ports. Each port has a Special Function register, which holds the current state of the pins. You can mask away any unwanted pins and shift the number to be right justified. For example: On the Uno and Nano pins 2 to 7 belong to PORTD. So, if you use pins 2 to 4 for your 3 switches, you could get the code like:

```
code = (PIND & 0b00011100) >> 2;

```

This is a bit more difficult to understand, but it will help you later on, when pursuing Arduino more.

---

For deciding what action to do based on the code, it is normally easier to use a switch case statement:

```
switch(code){
    case 0b101:
        do_something();
        break;
    case 0b011:
        do_something_else();
        break;
}

```

---
Tags: bit
---


# Question
Title: Why are transistors necessary before LEDs?
Below is the small RGB LED circuit I'm trying to build. My question is why are the 3 transistors necessary, and can I not link the LEDs directly?

# Answer
> 3 votes
The port pins of your Nano can deliver current in a quite limited range, and six LEDs need a lot more to shine brightly. The transistors are amplifying the available current.

However, 4k7 resistors in series with each LED will not allow enough current to let them shine well. Reduce the resistors by a factor of at least 10. Read the LEDs' data sheet and apply Ohm's law.

# Answer
> 2 votes
The transistors are connected as an emitter follower, not as a switch. The transistors are acting as current amplifiers. The emitter voltage will rise to approximately the voltage on its base - about 0.7V. That places the voltage at about (5 - 0.7 = 4.3V) at the emitter. Since the collectors of transistors are powered by Vin I would guess you have at least 6 volts available assuming a 5V Nano so the extra voltage drop across the transistors will be dissipated as heat. The base resistors are not needed but should not affect performance much. The available current at the emitter would be the Hfe of the transistor times the base current. Each LED will consume about 2 milliamps making the load on each of the transistor around 12 milliamps. It should work fine. You can divide the 12 milliamps of the LEDs by the Hfe of the transistor to get the base load.

# Answer
> 0 votes
Each LED consumes up to 20mA and You are using three LEDs at each I/O port in Arduino Nano. In other word, each part consumes 120mA.

The important thing is Arduino Nano I/O provides 20mA at maximum. So if you want to control 120mA by I/O ports, you must use transistor to support huge current.

Transistor can afford current up to 500mA.

---
Tags: led, rgb-led, transistor
---


title: Servo jitter with Arduino

text:
# Question
Title: Servo jitter with Arduino
We're complete beginners with Arduino and we're working on a project that moves a pointer based on a color sensor reading.

We used two servo motors each: one performs a specific task, the small servo works pretty fine. The problem is with the larger one.

We used this servo motor model: (towardpro MG996R), Arduino Uno and a color sensor. Because the motor is large we connect it to a 9 V power supply.

But when we run the code it just vibrates in place and the arm won't move :(

Is there anything else we need to add to the circuit like a resistor or some thing?

```
#include <Servo.h>
Servo largeServo;

void setup() {
  largeServo.attach(6);
  largeServo.write(0);
}

void loop() {
  largeServo.write(0);
  delay (2000);
  largeServo.write(30);
  delay (2000);
  largeServo.write(60);
  delay (2000);
  largeServo.write(90);
  delay (2000);
}

```

# Answer
> 3 votes
According to (MG996R)'s datasheet You must connect a 6 volts - 2.5 amps power supply for it's best performance (max. Torque) Maximum voltage of this servomotor is 6 volts And be careful, exceeding that voltage can be cause of some damage to it's control board Try 6 volts 2.5 amps power supply and if doesn't work maybe your servomotor's control-board is damaged by over-voltage.

# Answer
> 2 votes
As already suggested in the comments you need a more powerful current source than your battery.

No device work purely on Voltage, they all operate on Power (watts) or, if you prefer, on a combination of Voltage and Current (ampere).

You are feeding 9V into your beefy motor, but the amount of current your battery can provide is pretty limited due to the battery internal resistance and limited capacity.

Replace the battery with a proper power source capable to deliver 10W or more (1+ ampere at 9 volts equals 9+ watts) and your motor will start to operate and it will also get warm while operating.

# Answer
> 1 votes
To complement the other answers, also make sure that the Arduino itself is being powered properly!

I was attaching Arduino Uno to a nearly out of battery laptop via USB cable, resulting in a jittering servo. As soon as I've put the laptop on charge, the servo started working smoothly!

---
Tags: arduino-uno, servo
---


title: Timer2 and INT1 in Arduino UNO

text:
# Question
Title: Timer2 and INT1 in Arduino UNO
In my project Pin 3 of Arduino UNO is as External interrupt (INT1) and at the same time, I have to run Timer2. INT1 dosen't work When Timer2 is run. Timer2 is run just as timer. Is it my mistake or it is logical?

I connect a key to pin 3 as external interrupt and also run timer. Every time INT1 on pin 3 senses rising edge Button\_ISR() is called. but because of running timer2, Button\_ISR() is not called.

THis is my code:

```
int buttonPin = 3;
void setup()
{
  pinMode(buttonPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(3), button_ISR, RISING);
  Serial.begin(9600);
  TCCR2B = 0x07; // clock frequency / 1024
  //OCR2B = 0x00;  // Output compare
  TCNT2 = 0;     // Set counter 2 to zero
  TIMSK2 = 0x01; // Enable overflow interrupt

}

void loop()
{

}

void button_ISR()
{
  Serial.print("button_ISR()");
  Serial.print("\n");
}

```

# Answer
Here are my 2 cents:

Your code is missing the `handler` for the timer. You have enabled the Timer overflow interrupt, but you have ISR prepared for it. So, the control is ending up reaching unhandled interrupt ISR which is a `Restart`

Arduino is restarting all the time.

Adding one line should fix it temporarily.

```
ISR(TIMER2_OVF_vect) {}

```

Here is the updated code. I can see that the code is now running (not restarting at least)

https://wokwi.com/arduino/projects/307835582788141632

```
    int buttonPin = 3;
    void setup()
    {
      pinMode(buttonPin, INPUT_PULLUP);
      Serial.begin(9600);
      Serial.println("ready!");
      TCCR2B = 0x07; // clock frequency / 1024
      //OCR2B = 0x00;  // Output compare
      TCNT2 = 0;     // Set counter 2 to zero
      TIMSK2 = 0x01; // Enable overflow interrupt
      attachInterrupt(digitalPinToInterrupt(3), button_ISR, RISING);

    }

    void loop()
    {

    }

void button_ISR()
{
  Serial.print("button_ISR()");
  Serial.print("\n");
}

ISR(TIMER2_OVF_vect) {}

```

---

Here is the disassembly code found on the Wokwi Arduino simulator for your sketch

and if you see the location  `0xf6`:

you will see that the code is doing a soft reset ( `JMP 0`). I hope this is helpful to you. Please feel free to ask if you have any questions.
> 4 votes

---
Tags: arduino-uno
---


# Question
Title: Seeeduino XIAO write and read PWM duration (period) using timers
I am trying to communicate between two Seeeduino XIAO (chip: ATSAMD21G18A-MU) by way of **TCC capture** using register timers.

Square wave pulse duration varies from 200ns to 4us.

I found these two code samples, and I am now trying to change them up to make them work the way I intend to read and write these short pulses.

---

**1) XIAO writing square wave (generate output)**

This code works, but it is changing the pulse width and not the pulse period. Output is on pin `D2` and `D3`. How can I make it change the polse period instead of the polse width? Source

```
// Output 300kHz dual slope PWM on TCC0 with complementary outputs and dead time insertion
void setup()
{
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |        // Enable GCLK0
                      GCLK_CLKCTRL_GEN_GCLK0 |    // Select GCLK0 at 48MHz
                      GCLK_CLKCTRL_ID_TCC0_TCC1;  // Route GCLK0 to TCC0 and TCC1

  PORT->Group[PORTA].PINCFG[10].bit.PMUXEN = 1;   // Enable the port multiplexer for port pins PA10 and PA11
  PORT->Group[PORTA].PINCFG[11].bit.PMUXEN = 1;

  // Select the port pin multiplexer switch to option F for TCC0/WO[2] and TCC0/WO[3] on
  // port pins PA10 and PA11 respectively
  PORT->Group[PORTA].PMUX[10 >> 1].reg = PORT_PMUX_PMUXO_F | PORT_PMUX_PMUXE_F;

  TCC0->WAVE.reg = TCC_WAVE_POL2 |                // Reverse the signal polarity on channel 2
                   TCC_WAVE_WAVEGEN_DSBOTTOM;     // Dual slope PWM on TCC0
  while (TCC0->SYNCBUSY.bit.WAVE);                // Wait for synchronization

  //  48,000,000 / 300,000 = 160
  TCC0->PER.reg = 79;                             // Set the frequency of the PWM on TCC0 to 300kHz
  while(TCC0->SYNCBUSY.bit.PER);                  // Wait for synchronization

  TCC0->CC[2].reg = 40;                           // Output a 50% duty-cycle
  while(TCC0->SYNCBUSY.bit.CC2);                  // Wait for synchronization

  TCC0->CC[3].reg = 35;                           // Output a 43% duty-cycle
  while(TCC0->SYNCBUSY.bit.CC3);                  // Wait for synchronization

  TCC0->CTRLA.bit.ENABLE = 1;                     // Enable TCC0
  while (TCC0->SYNCBUSY.bit.ENABLE);              // Wait for synchronization
}

void loop(){
  TCC0->CTRLBSET.reg = TCC_CTRLBSET_LUPD;         // Set the Lock Update (LUPD) bit
  while (TCC0->SYNCBUSY.bit.CTRLB);               // Wait for synchroniztion
  TCC0->CCB[2].reg = 40;                          // Output a 50% duty-cycle
  while(TCC0->SYNCBUSY.bit.CCB2);                 // Wait for synchronization
  TCC0->CCB[3].reg = 35;                          // Output a 43% duty-cycle
  while(TCC0->SYNCBUSY.bit.CCB3);                 // Wait for synchronization
  TCC0->CTRLBCLR.reg = TCC_CTRLBCLR_LUPD;         // Clear the Lock Update (LUPD) bit
  while (TCC0->SYNCBUSY.bit.CTRLB);               // Wait for synchroniztion
  delay(1000);                                    // Wait for 1 second

  TCC0->CTRLBSET.reg = TCC_CTRLBSET_LUPD;         // Set the Lock Update (LUPD) bit
  while (TCC0->SYNCBUSY.bit.CTRLB);               // Wait for synchroniztion
  TCC0->CCB[2].reg = 20;                          // Output a 25% duty-cycle
  while(TCC0->SYNCBUSY.bit.CCB2);                 // Wait for synchronization
  TCC0->CCB[3].reg = 15;                          // Output a 18% duty-cycle
  while(TCC0->SYNCBUSY.bit.CCB3);                 // Wait for synchronization
  TCC0->CTRLBCLR.reg = TCC_CTRLBCLR_LUPD;         // Clear the Lock Update (LUPD) bit
  while (TCC0->SYNCBUSY.bit.CTRLB);               // Wait for synchroniztion
  delay(1000);
}

```

---

**2) XIAO reading square wave (input capture); Period and Pulse-Width (PPW) Capture**

This code works, but it reads the frequency over a period of 1 second, and not just the duration of a polse period. Input is on `D6`. How can I make these changes to the code for it to work? Source

```
// Count the number of pulses on pin D6 (PB08) over a 1 second period
void setup()
{
  SerialUSB.begin(115200);                  // Initialise the native serial port
  while(!SerialUSB);                        // Wait for the console to open

  PM->APBCMASK.reg |= PM_APBCMASK_EVSYS;    // Switch on the event system peripheral

  ////////////////////////////////////////////////////////////////////////////////////////
  // Generic Clock Initialisation

  GCLK->GENDIV.reg =  GCLK_GENDIV_DIV(1) |          // Select clock divisor to 1
                      GCLK_GENDIV_ID(4);            // Select GLCK4

  GCLK->GENCTRL.reg = GCLK_GENCTRL_IDC |            // Set the duty cycle to 50/50 HIGH/LOW
                      GCLK_GENCTRL_GENEN |          // Enable GCLK
                      GCLK_GENCTRL_SRC_XOSC32K |    // Select GCLK source as
                                                    //    external 32.768kHz crystal (XOSC32K)
                      GCLK_GENCTRL_ID(4);           // Select GCLK4
  while (GCLK->STATUS.bit.SYNCBUSY);                // Wait for synchronization

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |          // Enable generic clock
                      GCLK_CLKCTRL_GEN_GCLK0 |      // GCLK0 at 48MHz
                      GCLK_CLKCTRL_ID_TCC0_TCC1;    // As a clock source for TCC0 and TCC1

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |          // Enable generic clock
                      GCLK_CLKCTRL_GEN_GCLK4 |      // GCLK4 at 32.768kHz
                      GCLK_CLKCTRL_ID_TCC2_TC3;     // As a clock source for TCC2 and TC3

  //////////////////////////////////////////////////////////////////////////////////////////////
  // TCC2 Initialisation - reference timer: measures a 1s period

  TCC2->PER.reg = 32767;                             // Set the period (PER) register for a
                                                     // PWM period of 1s
  while (TCC2->SYNCBUSY.bit.PER);                    // Wait for synchronization

  TCC2->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM;            // Set timer to Normal PWM mode (NPWM)
  while (TCC2->SYNCBUSY.bit.WAVE);                   // Wait for synchronization

  TCC2->CTRLBSET.reg = TCC_CTRLBSET_ONESHOT;         // Enable oneshot operation
  while(TCC2->SYNCBUSY.bit.CTRLB);                   // Wait for synchronization

  NVIC_SetPriority(TCC2_IRQn, 0);    // Set the Nested Vector Interrupt Controller
                                     //   (NVIC) priority for TCC2 to 0 (highest)
  NVIC_EnableIRQ(TCC2_IRQn);         // Connect TCC2 to Nested Vector Interrupt
                                     //   Controller (NVIC)

  TCC2->INTENSET.reg = TCC_INTENSET_OVF;   // Enable overflow (OVF) interrupts on TCC2

  TCC2->CTRLA.bit.ENABLE = 1;              // Enable TCC2
  while (TCC2->SYNCBUSY.bit.ENABLE);       // Wait for synchronization

  ////////////////////////////////////////////////////////////////////////////////////////
  // TCC0 Initialisation - measurement counter: counts the number of incoming of pulses

  PORT->Group[PORTB].PINCFG[8].bit.PMUXEN = 1;               // Enable the port multiplexer
                                                             //   on port pin PB08 (D6)
  PORT->Group[PORTB].PMUX[8 >> 1].reg |= PORT_PMUX_PMUXE_A;  // Set-up PB08 (D6) as an
                                                             //   EIC (interrupt)

  EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO8;       // Enable event output on external interrupt 8
  EIC->CONFIG[1].reg |= EIC_CONFIG_SENSE0_HIGH;  // Set interrupt to detect a HIGH level
  EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT8;      // Clear the interrupt flag on channel 8
  EIC->CTRL.bit.ENABLE = 1;                      // Enable EIC peripheral
  while (EIC->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  EVSYS->USER.reg = EVSYS_USER_CHANNEL(1) |      // Attach the event user (receiver) to
                                                 //   channel 0 (n + 1)
                    EVSYS_USER_USER(EVSYS_ID_USER_TCC0_EV_0);  // Set the event user (receiver)
                                                               //   as timer TCC0, event 0

  EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT |    // No event edge detection
                       EVSYS_CHANNEL_PATH_ASYNCHRONOUS |       // Set event path as asynchronous
                       EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_8) |  // Set event generator
                       //   (sender) as external interrupt 8
                       EVSYS_CHANNEL_CHANNEL(0);               // Attach the generator (sender)
                                                               //   to channel 0

  TCC0->EVCTRL.reg = TCC_EVCTRL_TCEI0 |       // Enable TCC0 event 0 inputs
                     TCC_EVCTRL_EVACT0_INC;   // Increment the TCC0 counter on receiving an event 0

  TCC0->CTRLA.bit.ENABLE = 1;          // Enable TCC0
  while (TCC0->SYNCBUSY.bit.ENABLE);   // Wait for synchronization
}

void loop()
{
  startConversion();     // Start a conversion over the 1 second integration window
  delay(3500);           // Wait for 1 second
}

void startConversion()
{
  TCC2->CTRLBSET.reg = TCC_CTRLBSET_CMD_RETRIGGER;   // Retrigger the timer TCC2 to
                                                     //   start the integration window
  while (TCC2->SYNCBUSY.bit.CTRLB);                  // Wait for synchronization
  TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_RETRIGGER;   // Retrigger the timer TCC0 to
                                                     //   start the count
  while (TCC0->SYNCBUSY.bit.CTRLB);                  // Wait for synchronization
}

void TCC2_Handler()
{
  TCC2->INTFLAG.bit.OVF = 1;                         // Clear the TCC2 overflow interrupt flag
  TCC0->CTRLBSET.reg = TCC_CTRLBSET_CMD_READSYNC;    // Trigger a read synchronization
                                                     //   on the COUNT register
  while (TCC0->SYNCBUSY.bit.CTRLB);                  // Wait for the CTRLB register write synchronization
  while (TCC0->SYNCBUSY.bit.COUNT);                  // Wait for the COUNT register read sychronization
  SerialUSB.println(TCC0->COUNT.reg);                // Print the result
}

```

Some helpful page explaining these timers

https://www.picotech.com/support/topic24051.html

https://shawnhymel.com/1710/arduino-zero-samd21-raw-pwm-using-cmsis/

# Answer
> 0 votes
**1) Writing short square wave pulses to pin `D3` using Seeeduino XIAO**

Timer setup derived from this github post and includes update suggestion by MartinL.

```
void setup()  //TCC1 Timer-Setup AT-SAMD21-G18 ARM Cortex M0
{
  setupTimers();
  changePer(125);
}
void loop() {
  // testing
  changePer(20);
  delay(3000);
  for (byte i = 0; i < 15; i++) {
    changePer(40 + (i+1)*4);
    delay(1000);
  }
  delay(2000);
}

// Change Pulse Period
void changePer(uint16_t myPer) {
  TCC1->CTRLBSET.reg = TCC_CTRLBSET_LUPD;     // Set the Lock Update bit
  while (TCC1->SYNCBUSY.bit.CTRLB);           // Wait for synchronization
  TCC1->PERB.reg = myPer;                     // Set period
  while(TCC1->SYNCBUSY.bit.PERB);             // Wait for synchronization
  TCC1->CCB[1].reg = myPer/2;                 // Set duty-cycle to 50%
  while(TCC1->SYNCBUSY.bit.CCB0);             // Wait for synchronization
  TCC1->CTRLBCLR.reg = TCC_CTRLBCLR_LUPD;     // Clear the Lock Update bit
  while (TCC1->SYNCBUSY.bit.CTRLB);           // Wait for synchronization
}

// Output PWM on digital pin D3 using timer TCC1 (10-bit resolution)
void setupTimers() {
  REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) |        // Divide the 48MHz clock source by divisor N=1: 48MHz/1=48MHz
                    GCLK_GENDIV_ID(4);          // Select Generic Clock (GCLK) 4
  while (GCLK->STATUS.bit.SYNCBUSY) ;           // Wait for synchronization

  REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC |         // Set the duty cycle to 50/50 HIGH/LOW
                     GCLK_GENCTRL_GENEN |       // Enable GCLK4
                     GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source
                     GCLK_GENCTRL_ID(4);        // Select GCLK4
  while (GCLK->STATUS.bit.SYNCBUSY) ;           // Wait for synchronization

  // Enable the port multiplexer for the digital pin D3 and D11  **** g_APinDescription() converts Arduino Pin to SAMD21 pin
  PORT->Group[g_APinDescription[3].ulPort].PINCFG[g_APinDescription[3].ulPin].bit.PMUXEN = 1;

  // Connect the TCC1 timer to digital output D3 - port pins are paired odd PMUO and even PMUXE
  // F & E specify the timers: TCC0, TCC1 and TCC2
  // D2 is on PA10 = even, use Device E for TCC1
  PORT->Group[g_APinDescription[2].ulPort].PMUX[g_APinDescription[2].ulPin >> 1].reg |= PORT_PMUX_PMUXO_E;

  // Feed GCLK4 to TCC0 and TCC1
  REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |       // Enable GCLK4 to TCC0 and TCC1
                     GCLK_CLKCTRL_GEN_GCLK4 |   // Select GCLK4
                     GCLK_CLKCTRL_ID_TCC0_TCC1; // Feed GCLK4 to TCC0 and TCC1
  while (GCLK->STATUS.bit.SYNCBUSY) ;           // Wait for synchronization

  // Dual slope PWM operation: timers countinuously count up to PER register value then down 0
  REG_TCC1_WAVE |= TCC_WAVE_POL(0xF) |          // Reverse the output polarity on all TCC0 outputs
                   TCC_WAVE_WAVEGEN_DSBOTH;     // Setup dual slope PWM on TCC0
  while (TCC1->SYNCBUSY.bit.WAVE) ;             // Wait for synchronization

  // Each timer counts up to a maximum or TOP value set by the PER register,
  // this determines the frequency of the PWM operation: Freq = 48Mhz/(2*N*PER)
  REG_TCC1_PER = 256;               // Set the FreqTcc of the PWM on TCC1 to 24Khz
  while (TCC1->SYNCBUSY.bit.PER) ;  // Wait for synchronization

  // Divide the GCLOCK signal by 1 giving  in this case 48MHz (20.83ns) TCC1 timer tick and enable the outputs
  REG_TCC1_CTRLA |= TCC_CTRLA_PRESCALER_DIV1 | // Divide GCLK4 by 1
                    TCC_CTRLA_ENABLE;          // Enable the TCC0 output
  while (TCC1->SYNCBUSY.bit.ENABLE) ; // Wait for synchronization
}

```

**2) Reading short square waves with Seeeduino XIAO pin `D2`**

It is thanks to MartinL that I got this to work. Source

```
// Setup TC4 to capture pulse-width and period on digital pin D2 on Seeeduino Xiao
volatile boolean periodComplete;
volatile uint32_t isrPeriod;
volatile uint32_t isrPulsewidth;
uint32_t period;
uint32_t pulsewidth;

void setup()   {
  SerialUSB.begin(115200);                         // Initialise the native serial port
  while(!SerialUSB);                               // Wait for the console to open

  PM->APBCMASK.reg |= PM_APBCMASK_EVSYS;           // Switch on the event system peripheral

  GCLK->GENDIV.reg = GCLK_GENDIV_DIV(1) |          // Divide the 48MHz system clock by 1 = 48MHz
                     GCLK_GENDIV_ID(4);            // Set division on Generic Clock Generator (GCLK) 4

  GCLK->GENCTRL.reg = GCLK_GENCTRL_IDC |           // Set the duty cycle to 50/50 HIGH/LOW
                      GCLK_GENCTRL_GENEN |         // Enable GCLK 4
                      GCLK_GENCTRL_SRC_DFLL48M |   // Set the clock source to 48MHz
                      GCLK_GENCTRL_ID(4);          // Set clock source on GCLK 4
  while (GCLK->STATUS.bit.SYNCBUSY);               // Wait for synchronization

  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |         // Route GCLK4 to TC4 and TC5
                      GCLK_CLKCTRL_GEN_GCLK4 |
                      GCLK_CLKCTRL_ID_TC4_TC5;

  // Enable the port multiplexer on port pin PA10
  PORT->Group[PORTA].PINCFG[10].bit.PMUXEN = 1;
  // Set-up the pin as an EIC (interrupt) on port pin PA10
  PORT->Group[PORTA].PMUX[10 >> 1].reg |= PORT_PMUX_PMUXE_A;

  EIC->EVCTRL.reg |= EIC_EVCTRL_EXTINTEO10;                                // Enable event output on external interrupt 10
  EIC->CONFIG[1].reg |= EIC_CONFIG_SENSE2_HIGH;                            // Set event detecting a HIGH level
  EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT10;                               // Disable interrupts on external interrupt 10
  EIC->CTRL.reg |= EIC_CTRL_ENABLE;                                        // Enable EIC peripheral
  while (EIC->STATUS.bit.SYNCBUSY);                                        // Wait for synchronization

  EVSYS->USER.reg = EVSYS_USER_CHANNEL(1) |                                // Attach the event user (receiver) to channel 0 (n + 1)
                    EVSYS_USER_USER(EVSYS_ID_USER_TC4_EVU);                // Set the event user (receiver) as timer TC4

  EVSYS->CHANNEL.reg = EVSYS_CHANNEL_EDGSEL_NO_EVT_OUTPUT |                // No event edge detection
                       EVSYS_CHANNEL_PATH_ASYNCHRONOUS |                   // Set event path as asynchronous
                       EVSYS_CHANNEL_EVGEN(EVSYS_ID_GEN_EIC_EXTINT_10) |   // Set event generator (sender) as external interrupt 10
                       EVSYS_CHANNEL_CHANNEL(0);                           // Attach the generator (sender) to channel 0

  TC4->COUNT32.EVCTRL.reg = TC_EVCTRL_TCEI |               // Enable the TC event input
                            //TC_EVCTRL_TCINV |              // Invert the event input
                            TC_EVCTRL_EVACT_PPW;           // Set up the timer for capture: CC0 period, CC1 pulsewidth

  TC4->COUNT32.CTRLC.reg = TC_CTRLC_CPTEN1 |               // Enable capture on CC1
                           TC_CTRLC_CPTEN0;                // Enable capture on CC0
  while (TC4->COUNT32.STATUS.bit.SYNCBUSY);                // Wait for synchronization

  NVIC_SetPriority(TC4_IRQn, 0);      // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest)
  NVIC_EnableIRQ(TC4_IRQn);           // Connect the TC4 timer to the Nested Vector Interrupt Controller (NVIC)

  TC4->COUNT32.INTENSET.reg = TC_INTENSET_MC1 |            // Enable compare channel 1 (CC1) interrupts
                              TC_INTENSET_MC0;             // Enable compare channel 0 (CC0) interrupts

  TC4->COUNT32.CTRLA.reg = //TC_CTRLA_PRESCSYNC_PRESC |      // Overflow on precaler clock, (rather than the GCLK)
                           TC_CTRLA_PRESCALER_DIV1  |      // Set prescaler to 1, 48MHz/1 = 48MHz
                           TC_CTRLA_MODE_COUNT32;          // Set TC4/TC5 to 32-bit timer mode

  TC4->COUNT32.CTRLA.bit.ENABLE = 1;                       // Enable TC4
  while (TC4->COUNT32.STATUS.bit.SYNCBUSY);                // Wait for synchronization
}

void loop() {
  if (periodComplete)                             // Check if the period is complete
  {
    noInterrupts();                               // Read the new period and pulse-width
    period = isrPeriod;
    pulsewidth = isrPulsewidth;
    interrupts();
    SerialUSB.print("PW: ");
    SerialUSB.print(pulsewidth);
    SerialUSB.print(F("   "));
    SerialUSB.print("P: ");
    SerialUSB.println(period);
    periodComplete = false;                       // Start a new period
  }
}

void TC4_Handler()                                // Interrupt Service Routine (ISR) for timer TC4
{
  // Check for match counter 0 (MC0) interrupt
  if (TC4->COUNT32.INTFLAG.bit.MC0)
  {
    TC4->COUNT32.READREQ.reg = TC_READREQ_RREQ |           // Enable a read request
                               TC_READREQ_ADDR(0x18);      // Offset address of the CC0 register
    while (TC4->COUNT32.STATUS.bit.SYNCBUSY);              // Wait for (read) synchronization
    isrPeriod = TC4->COUNT32.CC[0].reg;                    // Copy the period
    periodComplete = true;                                 // Indicate that the period is complete
  }

  // Check for match counter 1 (MC1) interrupt
  if (TC4->COUNT32.INTFLAG.bit.MC1)
  {
    TC4->COUNT32.READREQ.reg = TC_READREQ_RREQ |           // Enable a read request
                               TC_READREQ_ADDR(0x1A);      // Offset address of the CC1 register
    while (TC4->COUNT32.STATUS.bit.SYNCBUSY);              // Wait for (read) synchronization
    isrPulsewidth = TC4->COUNT32.CC[1].reg;                // Copy the pulse-width
  }
}

```

---
Tags: pwm, communication, timers, samd21g, seeeduino-xiao
---


title: Use 5V pH sensor with 3.3V NodeMCU

text:
# Question
Title: Use 5V pH sensor with 3.3V NodeMCU
I'm trying to use a pH probe with NodeMCU, the problem is that NodeMCU is 3.3V and the pH analog sensor requires 5V, at first I thought using the VIN pin but didn't work, then I used the VU pin from NodeMCU V3 (by Lolin) but it didn't give me the right values, like if it missed more power. Is there any other way? Or any esp8266 board which supports 5V into it's analog input?

# Answer
Depending on your specific sensor and power supply setup you have following options:

1. **Change supply voltage**
Most resistive sensors don't have to power anything and will function just fine when supplied with less than 5V. Study the datasheet and make test measurements to find out whether this is suitable.
2. **Use a voltage divider**
Supply the sensor with 5V and use a simple voltage divider before connecting to your MCU and therefore measure 0-3.3V.
3. **Interface another IC**
Get a small external ADC that can handle 5V readings and may be interfaced by any serial protocol supported by your esp8266 (namely UART and I2C).
> 4 votes

# Answer
The simplest method is just a voltage divider - just as if you were interfacing a 5V logic signal output with a 3.3V input. However it may not work.

A voltage divider will only really be of use if the output of the pH sensor is low impedance. If it's not then you will need a very high impedance voltage divider, and the analog input of the ESP8266 isn't high enough impedance to support a very high impedance voltage divider - it will skew the results horribly.

So you may need to buffer the output of the pH sensor through an op-amp first.

If you use a unity gain non-inverting buffer you can then use a voltage divider to reduce the output voltage.

simulate this circuit – Schematic created using CircuitLab

Alternatively, as others have suggested, use an external 5V ADC chip and logic level conversion to communicate with the ESP8266.
> 5 votes

# Answer
Old topic, but in case it shows up in searches, like the one I was just doing ... I run a 5v ultrasonic SR04 off a Lolin nodemcu, and if you connect to "VU" on the Lolin nodemcu, you will get 5v.
> 3 votes

# Answer
Have you guys checked the specification of the AiThinker's ESP-12s? There's a piece of description in its Chinese edition document that says if you are hooking up other devices which work in 5v, you have to use the Level converter circuit in between.
> 0 votes

---
Tags: nodemcu
---


# Question
Title: Can I just use one Arduino in a receiver/transmitter circuit?
I am trying to build a system to control lights remotely, but I am a student and am operating on a tight budget. Is there any way I can have just one Arduino along with a receiver and transmitter (I am using the 433Mhz RF Wireless Transmitter Module and Receiver Kit 5V DC 433MHZ) to do a simple on/off command for lights? I don't want to unnecessarily spend money on another Arduino (especially since I am not going to be transmitting complicated data). If this were possible, what are the other things I would need and what would the code look like?

# Answer
It depends on your hardware. You are not transmitting complicated data, but you need to transmit some data. Just wiring a switch to a standard RF transmitter is not enough. Though there are RF modules, which support exactly this (by having corresponding electronic components on the board). If you haven't already bought the modules, you could buy these.

If you already have bought the RF modules, you can buy a standard 433MHz key fob. They are normally rather cheap. Then you can record the key fobs signal with your receiver and write code to check for this signal in the received data.

If you plan to keep on building with Arduino, you might wanna buy directly a bunch of Arduinos (also for future projects). You can get Arduino clones directly from china for very cheap (a Nano clone for example costs normally between 1 and 2$ each in packs of maybe 10).
> 1 votes

---
Tags: arduino-uno, rf
---


title: Where to store AES key on Arduino board

text:
# Question
Title: Where to store AES key on Arduino board
I'm working with this library AES lib so everything works I can encrypt/decrypt data. But now I'd like to know what is the best way to store my `aes private key` ? My boars is a personnal board build with an `samd21 cortex M0+` my board doesn't have the possibility to connect with the extern world, like ethernet or ble, wifi.

I've only one possibility is to store the key in my program but what is the best way? Obfuscate my key? I know there is no perfect and secure solution if my key is store in my program, but what is the best solution ? Maybe is it possible to put my key when I upload my sketch in compiler option and store it in emulate eeprom?

# Answer
All you can really do with your key is to just store it in your code. It makes no difference if that is as a `const` variable or stashed in emulated EEPROM.

The real question is not how to store it but how to stop someone reading it. Most microcontrollers (and the SAMD21 is no exception) have "code protection" facilities - settings you can enable in the chip's configuration (or "fuse") bits to prevent the flash being read by any external debugger or programmer. By enabling these bits (check the datasheet for your chip) you will prevent people being able to read the flash containing your key no matter *how* you store it.
> 1 votes

---
Tags: c++
---


title: nRF24L01 programming issue

text:
# Question
Title: nRF24L01 programming issue
I'm new to nrf24l01 . I have a two nrf24l01 they both works very well ,I tested them with a simple LED blinking program. Now I write a program for both transmitter and receiver to just send message and get a response for the message. Both the transmitter and receiver programs are given bellow (program works but not as I'm expected)

Transmitter

```
#include<RF24.h>
#include <nRF24L01.h>
#include<SPI.h>

const byte CEpin=9;
const byte CSNpin=10;
RF24 radio(CEpin,CSNpin);
const byte address[][6]={"000001","000002"};
char ack[30],buf[]="hi....How are you?";
bool x;

void setup() {

  Serial.begin(9600);
  radio.begin();
  radio.openWritingPipe(address[1]);
  radio.openReadingPipe(1,address[0]);
  radio.setPayloadSize(30);
  radio.setChannel(83);
  radio.setDataRate(RF24_1MBPS);
  radio.setPALevel(RF24_PA_HIGH);

}

void loop() {
  delay(4);

  radio.stopListening();

  if(radio.write(buf,sizeof(buf)))
      Serial.println("MSG sent successfully");

  delay(6);

 radio.startListening();

 if(radio.available())
 {
  radio.read(ack,sizeof(ack));
  Serial.println(ack);
 }

 }

```

Receiver

```
#include<SPI.h>
#include<RF24.h>
#include<nRF24L01.h>

const byte cepin=9;
const byte cspin=10;
RF24 mynrf(cepin,cspin);
const byte address[][6]={"000001","000002"};
char buf[50];
char response[]={"I'm fine"};

void setup() {

Serial.begin(9600);
mynrf.begin();
mynrf.openReadingPipe(1,address[0]);
mynrf.openWritingPipe(address[1]);
mynrf.setPayloadSize(30);
mynrf.setChannel(83);

}

void loop() {

  delay(4);

  mynrf.startListening();

  if(mynrf.available())
  {
      mynrf.read(buf,sizeof(buf));
      Serial.println(buf);
  }

  delay(6);

  mynrf.stopListening();

  if(mynrf.write(response,sizeof(response)))
      Serial.println("response sent successfully\n\n\n");

}

```

I faced a lot of troubles

1.Without delay() \[delay(4);delay(6);\] it doesn't work

2.With setPayloadSize() and setChannel() it doesn't work

3.I can't set data rate at 250Kbps and 2Mbps which means setDataRate(RF24\_1MBPS) only works

4.setPALevel(RF24\_PA\_HIGH) and setPALevel(RF24\_PA\_LOW) only works

5.It also doesn't give output as I'm expected. I attached a screenshot of my output bellow ( COM5 is Transmitter and COM4 is Receiver)

Transmitter and Receiver serial monitor output

These are the issues what I'm faced. Can any one explain it .

Please any one can suggest me a best tutorials and examples for nrf24lo1 .

# Answer
Two things:

1. nRF24L01 is only half duplex. You can't send and receive at the same time. You must send only briefly and then spend some time listening for the response. With no delays there is no time to listen. It's like it's sat there with its fingers in its ears going "la la la la la" all the time.
2. You're spamming out a "response" all the time. The same situation occurs. You have two transmitters that rarely listen for anything. You should only send your response if you have received an original request.
> 1 votes

---
Tags: nrf24l01+
---


# Question
Title: What resistor should I use when using a photo-resistor?
So I'm trying to use a photo-resistor and I learned that you should have a "fixed" resistor in the circuit. So my question is, what resistor should I have be the fixed resistor? My photo-resistor has a resistance of 18-50 KΩ at 10lux and a darkness resistance of 2.0 MΩ at 0lux.

# Answer
> 2 votes
What part of the “light curve” are you interested in and what will you be connecting the LDR output / voltage divider to?

A photoresistor (LDR) that has a resistance of, say, 20k Ohms at 10 lux (which is a very low “candlelight” light level\*) can have a resistance of only 100 Ohms in daylight (10.000 lux or more). Your voltage divider (input to an ADC i presume?) should be matched with the values you are interested in.

That said, if I make the assumption that you want to distinguish between daylight and darkness and you want to connect the LDR voltage divider to an ADC input on your Arduino that has the same range as your power supply (usually 5V or 3.3V), you could build the following voltage divider using your LDR and a 10k Ohm resistor (R1, your "fixed" resistor):

simulate this circuit – Schematic created using CircuitLab

This will give you a fairly wide range of values (with higher values being brighter) and allows you (by experiment) to determine when it's time to turn the lights on, for example.

\*Actually, the definition of 1 lux is the amount of light one candle generates at a meter distance, so 10 lux is the light of 10 candles.

---
Tags: resistor, photoresistor, voltage-divider
---


# Question
Title: Pull more than 250 mA from powerbank-powered Teensy 3.6
I'm using a powerbank speced 5V at 2.4A to power my Teensy 3.6 via the USB port. However, Teensy recommends to not pull more than 250 mA from its 3.3V pin.

Is there any way I can pull more current, at either 3.3V or 5V, without splicing the USB cable? I will use it to control WS2812(b?) LEDs.

# Answer
> 2 votes
The Teensy 3.6 breaks out the USB input power on the VUSB pin (labeled on on the back).

This is the raw 5V in from the USB connector before it feeds the 3.3V voltage regulator.

See the schematics at the bottom of this page

---
Tags: current, teensy
---


# Question
Title: How can I get the source files for Arduino libraries?
I've been looking for a while inside Arduino's files to find the core library. However, I haven't found them yet. **Where on my hard drive can I obtain the core library files (.cpp and .h) necessary for all Arduino code?**

Looking around on Google, I couldn't find a way to find the above files. I did see something about getting an .a file while Arduino is compiling, however, that isn't what I want. I want to browse the code and look at functions such as delay to see how they would react when given the values not expected. (i.e. Will my code stall if I use `delay(-200);` by not being to exit the loop, or will it create a black hole and disrupt the space-time continuum?)

# Answer
> 10 votes
The base Arduino source files are in the Arduino installation, under `cores/arduino/`. Source for additional libraries included are in `libraries/`.

# Answer
> 13 votes
The code is also available online for those times you don't have the IDE installed:

https://github.com/arduino/Arduino

# Answer
> 9 votes
On a Mac, the path to the source code folder is:
`Arduino.app/Contents/Resources/Java/Hardware/Arduino/Cores/Arduino`. I'd expect it would be the same from `/Java/` on down in other OSes.

# Answer
> 4 votes
The arduino source files can be found on Github at https://github.com/arduino/Arduino, however the libraries have been moved to their own repositories:

# Answer
> 3 votes
There are multiple places where you can look. As at IDE 1.6.4 (Ubuntu version) some are in:

```
(install location)/libraries

```

But these are the high-level libraries, in particular:

```
Bridge
Esplora
Ethernet
Firmata
GSM
LiquidCrystal
Robot_Control
RobotIRremote
Robot_Motor
SD
Servo
SpacebrewYun
Stepper
Temboo
TFT
WiFi

```

---

That does not cover the low-level libraries like Tone, Print, main, etc. These are in:

```
(install location)/hardware/arduino/avr/cores/arduino

```

There you would find the Arduino core libraries like:

```
abi.cpp
Arduino.h
binary.h
CDC.cpp
Client.h
HardwareSerial0.cpp
HardwareSerial1.cpp
HardwareSerial2.cpp
HardwareSerial3.cpp
HardwareSerial.cpp
HardwareSerial.h
HardwareSerial_private.h
HID.cpp
hooks.c
IPAddress.cpp
IPAddress.h
main.cpp
new.cpp
new.h
Printable.h
Print.cpp
Print.h
Server.h
Stream.cpp
Stream.h
Tone.cpp
Udp.h
USBAPI.h
USBCore.cpp
USBCore.h
USBDesc.h
WCharacter.h
WInterrupts.c
wiring_analog.c
wiring.c
wiring_digital.c
wiring_private.h
wiring_pulse.c
wiring_shift.c
WMath.cpp
WString.cpp
WString.h

```

---

However even that does not locate things like strcpy. The **header** files for them can be found at:

```
(install location)/hardware/tools/avr/avr/include/

```

There you will find:

```
alloca.h
assert.h
ctype.h
errno.h
inttypes.h
math.h
setjmp.h
stdfix-avrlibc.h
stdint.h
stdio.h
stdlib.h
string.h

```

---

Even that is not the full story. In a subdirectory (avr) you will find the avr-related things, with files for different processors, such as (in part):

```
boot.h
builtins.h
common.h
cpufunc.h
crc16.h
delay.h
eeprom.h
fuse.h
interrupt.h
io1200.h
io2313.h
...
iox64d4.h
iox8e5.h
lock.h
parity.h
pgmspace.h
portpins.h
power.h
sfr_defs.h
signal.h
signature.h
sleep.h
version.h
wdt.h
xmega.h

```

---

As for the source of strcpy, I don't think it is in the distribution. They include the standard libraries, pre-compiled. For example, if you look in:

```
(install location)/hardware/tools/avr/avr/lib

```

You will see various pre-compiled libraries, for example:

```
libc.a
libm.a
libprintf_flt.a
libprintf_min.a
libscanf_flt.a
libscanf_min.a

```

To find the source you would need to find where the AVR source of libc is (possibly at http://www.nongnu.org/avr-libc/).

---

As for the Mac, all this stuff is a few levels down in the "Application Package" which you can view by right-clicking and selecting "Show Package Contents". Look in the `Contents/Resources/Java` folder.

---

**None** of these places are where you should put your **own** libraries (ones you write or download). They should go into the `libraries` folder which is a subdirectory of your `sketchbook` folder. Create the `libraries` folder if it does not exist. That way user-installed libraries persist from one version of the IDE to the next.

# Answer
> 1 votes
I think this may have changed in newer versions. On my Mac Big Sur, Arduino 1.8.15 they are here: `/Applications/Arduino.app/Contents/Java/libraries`

---
Tags: library, core-libraries
---