# Question
Title: Arduino Nano 33 BLE getting the current time using RTC
I have a an arduino NANO 33 BLE and I'm trying to get the current time and date. Based on the documentation, the arduino has nRF52840 microcontroller which comes with a 24 RTC timer It is listed in the nordic documentation as well. However, I'm not sure exactly how to use it to get the current time; Based on the MbedOS documentation for Time I wrote out the code to print out the current time and date in conjunction with reading the data:

```
#include "mbed.h"
#include <Time.h>
#include <RTClib.h>

time_t rawtime;
struct tm *info;

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

//resistor val = 100K

void loop() {
  rawtime = time(NULL);
  time(&rawtime);
  info = localtime(&rawtime);
  int val = analogRead(A1);
  Serial.print(val);
  Serial.print('-');
  Serial.print(asctime(info) );
  delay(5);
  }

```

However it just prints out this:

> XX-Thu Jan 1 00:08:30 1970

Where the XX is the correct sensor data. Why is the time not the current time but the beginning unix epoch ? This code was run in the Desktop Arduino IDE in Win10

# Answer
I was going to write something more elaborate, but in short the RTC in the NRF52840 is not a "clock" so much as an asynchronous timer/counter. As in, you can run it from a clock source that isn't related to the system clock that times your code and it may (or may not) continue to count when you're in a sleep mode. So, you may be able to use this async. timer/counter as a building block in constructing what amounts to an approximation of a real-time clock (like a DS3231). That you might use it that way isn't assumed by Nordic, or mbed, or Arduino, or libc/`time.h`, and `RTCLib.h` concerns itself with accessing specific models external realtime clock chips with no direct connection to `time.h`. So there's nothing to support your specific use case in each of these things.

So you can try to build a real-time clock functionality out of it. But if you're like most Arduino users you're probably better off getting a DS3231 or something like it. You will probably end up with more accurate time keeping and battery backup, etc than you would if you build this functionality yourself out of the NRF52's counter.

If you have a need or strong desire to use `<time.h>`, that can usually be done by completing its implementation in some implementation specific documented way. Basically you'd retrieve the time fields out of something like the DS3231 an then use that to set what amounts to a `time_t` variable that backs `time()` and then to call regularly call some kind of time advance function from an interrupt routine based on the square wave output from the DS3231 (or whatever). If you really want to make use of the async. counter yourself, all of that applies there as well.
> 0 votes

---
Tags: arduino-ide, time, arduino-nano-ble
---


title: 6-pin BME280 not giving I2C signal

text:
# Question
Title: 6-pin BME280 not giving I2C signal
I'm creating a telemetry package for my my mom's model rocket with a MPU6050, a BME280, and a SD reader/writer. The code I found for the BME does not read any information. When I upload an I2C scanner, the MPU gives a signal, but the I2C gives "No i2c signal found". The wiring schematics are the same. I've tried different boards, and I've tried different code. Nothing works.

# Answer
@ModelRocketeer - I appreciate your frustration and I hope this will be of some help.

First of all, you have to make sure the board is wired correctly and it is anyone's guess whether it is wired correctly because you have not shown that to us and that frustrates us because we would like to help.

Here is a *very* similar board attached to a D1 mini.

If I flip it over to show the signal names, AND line it up correctly, one can see how it is hooked up....or it is just confusing because it is flipped over.

* BUT why not just tell us, like this:

> ```
> D1 mini<->280
> 3.3v   <-> Vcc
> GND    <-> GND
> D1     <-> SCL
> D2     <-> SDA
>
> ```

AND show us a clear picture because many eyes on it can increase the likelihood of solving the problem.

BTW: using colored leads helps with checking.

I have several of these generic 280 boards - they are cheap and when I bought mine, they were sold as BME280, but it turns out (after hours of frustration) that they were in fact BMP280. Apparently, the board can hold either. Be forewarned.

I tested my board with a D1, like yours at 3.3v, and an UNO at 5.0V and they both worked.

I then tested a known-to-be BME280 and it worked fine with the D1 mini.

In ALL cases, I was able to use a port scanner and see the I2C address (0x76).

Because you have not been able to detect any connection over I2C for the board but can detect a port for the MPU6050, I think you need to do the following:

Make sure you have the proper connections.

Remove the MPU6050 and have only the BMP/BME connected and run the scanner.

If you *still* see nothing, I would say the board is bricked. Because you said you tested several boards, I suspect (as have others) that you do not have it connected properly.

When you get it connected properly and can see a port when scanning - try running BME software but if you use the Adafruit programs you might need to force I2C since this is not an Adafruit board. The latter is able to use both I2C and SPI.

If you still don't get results, consider that it may, in fact be a BMP280 and try software for that.

In either event, please let us know what happens.
> 1 votes

---
Tags: esp8266, c++, i2c
---


# Question
Title: Why can't my four batteries (6V) can't power this circuit while usb 5v from arduino can?
I have this circuit

And I want it to power all the led rgb (100 in total), I want to make a independent portable circuit, so I don't have to use the usb power. The thing is when I use this circuit it only power to 44 led.

WHile when I use the usb 5V it can full lights all led .

This is my code

```
#include <Adafruit_NeoPixel.h>

#define NUM_LEDS 100
#define LED_PIN 2
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, LED_PIN, NEO_RGB+NEO_KHZ800);
void setup()
{

  strip.begin();
  strip.show();

}

void loop()
{

  for (int i = 0; i < NUM_LEDS; i = i+1)
  {
    strip.setPixelColor(i, strip.Color(255, 240, 255));

    strip.show();
    delay(1000);
  }

}

```

What may I be missing?

# Answer
> 1 votes
The current available from a computer's USB port is 500 mA; some ports can supply more if the device negotiates for it.

You show AA cells in your diagram. Even assuming they're Alkaline cells, batteries differ in their capacity vs. discharge rates, and presumably in their internal resistances. Most any power-supply's voltage will sag as you draw more current from it. The likely answer is that as you add LED's the battery voltage falls below either what is needed to light the LEDs; or 2) the dropout voltage of Arduino's voltage regulator, which shuts down the Arduino (assuming you're connected to 'V\_in', not '5v', which neither diagram shows). Less-than-fresh batteries will exhibit this voltage drop sooner and to a greater degree.

This study of AA battery capacity vs. current draw might help understand the apparent loss of capacity at greater currents. But even without that phenomenon, the battery voltage will fall as (I * R\_battery); capacity loss just makes it worse.

---
Tags: arduino-uno, power, led
---


# Question
Title: Arduino relay module working in a wrong way
I have an Arduino Mega and a 4-channel relay module.

This is the relay module.

When the Arduino digital output is LOW, the relay is energized. When the Arduino output is HIGH, the relay coil is de-energized.

How can I fix this?

# Answer
That's how they're designed to work energized is LOW de-energized is HIGH you just need to take this into account when writing your Arduino code
> 2 votes

# Answer
If you read the documentation or watch/read any tutorials on the mechanical relay you are using you will learn that LOW is active and HIGH is inactive for these devices. There is no way to change that behavior, that is how they are built. (Well, you can, but it's not worth the effort)

This design is intentional to prevent relay activation on power-up or system reset. And be sure to put this code in your setup routine to ensure proper system initialization.

```
digitalWrite(Relay, HIGH);
pinMode(Relay, OUTPUT);

```

Where Relay is the pin variable you defined for your relay.

Just code your routine using LOW to activate the relay when necessary.

Try this tutorial 4 channel relay tutorial
> 1 votes

# Answer
Yes. some boards are working in wrong way. I suggest you to build the relay board your self. . Its better to plan your project according to your requirement.
> -1 votes

# Answer
You can purchase relay boards that are active high or active low or selectable, your choice. You need to read the description to determine what type it is. Here is a link for one that is selectable high or low active: "https://www.rajguruelectronics.com/Product/1730/1%20channel%20relay%20board%20with%20high%20low%20level%20trigger.pdf" This is an example not a recommendation. These are very popular with the Arduino crowd.
> -2 votes

---
Tags: relay
---


# Question
Title: How to declare PB3 reset pin of ATtiny44 in program (using arduino IDE platform)
As follow-up of my former question:

Hi, I want to know how I can access PB3 reset pin of ATtiny44 IC. I ran out of pins so I am using it as I/O pin, but I am unable to declare it in the code.

This picture above says that PB3 is pin 11. But if I declare it as pin 11, the reset pin does not function at all.

```
// in setup():
    DDRB |= (uint8_t)(1U << 3);

// in loop():
    PORTB |= (uint8_t)(1U << 3);    // set PB3 to "high"
    PORTB &= ~((uint8_t)(1U << 3)); // set PB3 to "low"

```

This code works with only direct declaration.

In my code I just need to add pin number to the command like `#define CSN 2`.

---

**EDIT**

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

const int led = 0;

#define led1 11

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(led, OUTPUT);

  pinMode(led1, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
    digitalWrite(led, HIGH);
    digitalWrite(led1, HIGH);

    delay(1000);                       // wait for a second

    digitalWrite(led1, LOW);

    digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
    delay(1000);                       // wait for a second
}

```

This is the code that does not work (led1 is reset pin as GPIO). Even if I change the led1 declaration to PB3 of PCINT11, it still does not work.

# Answer
> 0 votes
i resolved my issue by installing spenceKonde ATtinyCore library, The RESET pin is pin 11 of attiny44 IC and in order to access it inside the code we need attinyCore library not Damellis( damellis does not have RESET programming access).

---
Tags: attiny, reset
---


# Question
Title: Reading constant battery voltage and using the obtained value in sensor formula
there i am working on a project in which my system is connected to 3.7v~4.2V lithium battery, I have to read constant battery voltage irrespective of the current battery voltage and to do that I am using internal voltage reference (1.1V). My issue is that before adding sensor code my program was reading constant voltage irrespective of any battery level but the moment I add sensor code to it, the battery voltage readings fluctuate.

# Answer
If you set the Vref with the internal reference of 1.1v, then the voltage presented at analog pin A1 is simply as:

```
const float Vref = 1.1; // according to datasheet there is a +/-10% variance, need calibration to confirm the actual value

analogReference(INTERNAL);
float VA1 = Vref / 1023.0 * analogRead(A1); // voltage at analog pin A1
float Vbat = VA1 * 5.7;                     // battery voltage

```
> 2 votes

---
Tags: arduino-uno, analogread, attiny, voltage-level, digital-analog-conversion
---


# Question
Title: How to deep sleep ATtiny/ATmega (to run for years with batteries) but still detect a button press?
**Question (TL;DR): what is the optimal method to deep sleep (to run an ATtiny45 or ATmega on batteries for 1+ year) but still be able to detect a button press?** Is it possible to deep sleep *until* a button is pressed?

I'm using a classic "debounce" method to detect a button press:

```
int buttonState;
int lastButtonState = LOW;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;

void setup() {
  pinMode(2, INPUT);
}

void loop() {
  int reading = digitalRead(2);
  if (reading != lastButtonState) { lastDebounceTime = millis(); }
  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != buttonState) {
      buttonState = reading;
      if (buttonState == HIGH) {
         // Button pressed, do something here!
         // In my actual code, it sends a packet via RF 433 Mhz
      }
    }
  }
  lastButtonState = reading;
  // snore(20);          // TinySnore here
}

```

My ATtiny45 should run during 1 year on 3 AA batteries, so I added a deep sleep using TinySnore. It works, and made the consumption go from more than 1mA to 0.2mA (@1 Mhz).

I know it's possible to go down to 5 µA if I `snore(1000);` but then obviously it won't be able to detect a button press.

I tried various sleep values: `snore(10);`, `snore(20);`, `snore(50);`, etc. but I didn't get consistent results.

Thus the question: **how to deep sleep *until* a button is pressed?**

---

I was thinking about using `attachInterrupt()` but then what kind of sleep should we use? `snore()`? `delay()`?

# Answer
> 7 votes
ATTINY's are designed to easily do this since they can wake from `power down` sleep mode by a pin change...

Basically you want to...

1. Connect a normally-open push button between an IO pin and ground.
2. Enable the pull-up on the IO.
3. Enable the pin change interrupt on the IO pin.
4. Enable interrupts.
5. Enter "power down" sleep mode.

When the button is pushed, it will connect the IO pin to ground, which will cause a pin change interrupt, which will wake the chip from sleep.

Note that you do not need to do anything in the pin change ISR (you can use the `EMPTY_INTERRUPT` compiler macro). If the ISR is empty, execution will pick up on the line after the sleep upon waking.

While in deep sleep, the chip will use an astonishingly small amount of power. For example, an ATTINY25/45/85 running off of a 3V coin cell at room temp will use less than 0.2uA...

A typical CR2032 coin cell is rated for 235mAh to 2V, so at this rate we'd expect to be able to wait for a button press like this for 100+ years.

IRL the battery will likely self discharge and physically deteriorate long before then (rated at 1% per year), but still not too shabby.

# Answer
> 2 votes
First I was unable to make the intterupt work for multiple pins, but finally here is a working code:

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

ISR(PCINT0_vect) {
  if (digitalRead(0) == LOW)           // # PB0 = pin 5 pressed => LED on
    digitalWrite(4, HIGH);
  else if (digitalRead(1) == LOW)      // # PB1 = pin 6 pressed => LED off
    digitalWrite(4, LOW);
  else if (digitalRead(2) == LOW)      // # PB2 = pin 6 pressed => LED on
    digitalWrite(4, HIGH);
}

void setup() {
  pinMode(4,OUTPUT); // LED
  pinMode(0,INPUT_PULLUP);
  pinMode(1,INPUT_PULLUP);
  pinMode(2,INPUT_PULLUP);
  ADCSRA = 0; // ADC disabled
  GIMSK = 0b00100000;  // General Interrupt Mask Register, / Bit 5 – PCIE: Pin Change Interrupt Enable / When the PCIE bit is set (one) and the I-bit in the Status Register (SREG) is set (one), pin change interrupt is enabled. Any change on any enabled PCINT[5:0] pin will cause an interrupt. The corresponding interrupt of Pin Change Interrupt Request is executed from the PCI Interrupt Vector. PCINT[5:0] pins are enabled individually by the PCMSK0 Register. / see https://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf
  PCMSK = 0b00000111;
}

void loop() {
  sleep_enable();
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_cpu();
}

```

Note: PCINTs are handled by a single PCINT\_vect here.

PS: as mentioned by Maximilian in a comment, this post gives nice solutions: Detecting key presses on a keypad whilst asleep.

# Answer
> 2 votes
I would put the MCU in deep sleep and then use the reset button.

---
Tags: power, atmega328, attiny, sleep
---


# Question
Title: Combined code to run a 2-zone radiant floor system. Cannot get 'RadiantMain' to work. Better description in beginning of code
Trying to combine code to run a 2-zone radiant floor heating system. The menu code works perfectly. When I select MenuC 'Run main' it executes to RadiantMain prints test and then returns to menu options again. Been working on this for weeks and don't how to fix it. The RadiantMain code works ok as a stand-alone.

The second sketch starts where it says //START RUN RADIANT MAIN CODE. The menu sketch and the Radiant Main are 2 separate sketches written by 2 different developers. They do run as stand-alone sketches. I modified the menu sketch to operate my relays (MenuA and MenuB) for the manual mode it works fine. I need to be able to use the menu sketch to run 3 different functions. MenuA & MenuB to manually run the system in manual mode and a third menu item (MenuC) to run the 2nd sketch in auto mode.

I need to combine the 2 sketches together into one code

I am using a D1 ROBOT LCD KEYPAD shield. A1 through A5 are connected to temp sensors. 4 relay shield controls 2 water valves and a pump, 4th relay is unused. the menu sketch controls the 2 water valves with MenuA and MenuB. I need MenuC to run the second sketch which reads sensors sets temps and controls 2 water valves and a pump.

```

//MENU CODE STARTS HERE

#include <LiquidCrystal.h>
LiquidCrystal lcd(8,9,4,5,6,7);

int keypad_pin = A0;
int keypad_value = 0;
int keypad_value_old = 0;

int pinCount = 4;
int relay_1 = 12;//zone 1
int relay_2 = 11;//zone 2
int relay_3 = 3;//pump
//int relay_4 = 2;//open

char btn_push;

byte mainMenuPage = 1;
byte mainMenuPageOld = 1;
byte mainMenuTotal = 3;

void setup() {
  Serial.begin(9600);
  pinMode(relay_1, OUTPUT);//zone 1
  pinMode(relay_2, OUTPUT);//zone 2
  pinMode(relay_3, OUTPUT);//pump
  //pinMode(relay_4, OUTPUT);
    lcd.begin(16,2);  //Initialize a 2x16 type LCD

    MainMenuDisplay();
    delay(1000);
}
void loop()

{
    btn_push = ReadKeypad();

    MainMenuBtn();

    if(btn_push == 'S')//enter selected menu
    {
        WaitBtnRelease();
        switch (mainMenuPage)
        {
            case 1:
              Zone1();
              break;
            case 2:
              Zone2();
              break;
            case 3:
              Radiant();
              break;
            /*case 4:
              MenuD();
              */break;
        }

          MainMenuDisplay();
          WaitBtnRelease();
    }

    delay(10);

}//--------------- End of loop() loop ---------------------

void MainMenuDisplay()
{
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Choose function");
    lcd.setCursor(1,1);
    switch (mainMenuPage)
    {
        case 1:
          lcd.print("Run zone 1");
          break;
        case 2:
          lcd.print("Run zone 2");
          break;
        case 3:
          lcd.print("Run main");
          break;
        case 4:
          lcd.print("4. Menu D");
          break;
    }
}

void Zone1()

{
    {
    digitalWrite(relay_1, HIGH);
    digitalWrite(relay_3, HIGH);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" Running zone 1");
    lcd.setCursor(0,1);
    lcd.print(" Left to end");
    while(ReadKeypad()!= 'L');
    digitalWrite(relay_1, LOW);
    digitalWrite(relay_3, LOW);
    }
}
void Zone2()
{
    digitalWrite(relay_2, HIGH);
    digitalWrite(relay_3, HIGH);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(" Running zone 2");
    lcd.setCursor(0,1);
    lcd.print(" Left to end");
    while(ReadKeypad()!= 'L');
    digitalWrite(relay_2, LOW);
    digitalWrite(relay_3, LOW);
}

void Radiant()

    {
    RadiantMain();
    }

void MenuD()
{
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Inside Menu D");

    while(ReadKeypad()!= 'L')
    {
        //Insert Task for Menu D here

    }
}

void MainMenuBtn()
{
    WaitBtnRelease();
    if(btn_push == 'U')
    {
        mainMenuPage++;
        if(mainMenuPage > mainMenuTotal)
          mainMenuPage = 1;
    }
    else if(btn_push == 'D')
    {
        mainMenuPage--;
        if(mainMenuPage == 0)
          mainMenuPage = mainMenuTotal;
    }

    if(mainMenuPage != mainMenuPageOld) //only update display when page change
    {
        MainMenuDisplay();
        mainMenuPageOld = mainMenuPage;
    }
}

char ReadKeypad()
{
  /* Keypad button analog Value
  no button pressed 1023
  select  741
  left    503
  up      326
  down    142
  right   0
  */
  keypad_value = analogRead(keypad_pin);

  if(keypad_value < 100)
    return 'R';
  else if(keypad_value < 200)
    return 'D';
  else if(keypad_value < 400)
    return 'U';
  else if(keypad_value < 600)
    return 'L';
  else if(keypad_value < 800)
    return 'S';
  else
    return 'N';

}

void WaitBtnRelease()
{
    while( analogRead(keypad_pin) < 800){}
}
//END MENU CODE

// Title: 2 zone Radiant Heat Controller
// Date:12/01/14
// Author: Chris Biblis (My First Adruino Project )

//RADIANT MAIN CODE STRTS HERE_________________________________________________________

// #include <LiquidCrystal.h>

// LiquidC//rystal lcd(8, 9, 4, 5, 6, 7);
// define some values used by the panel and buttons
int lcd_key     = 0;
int adc_key_in  = 0;
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5
// read the buttons
int read_LCD_buttons(){
 adc_key_in = analogRead(0);
 // buttons when read are centered at these valies: 0, 144, 329, 504, 741
 // we add approx 50 to those values and check to see if we are close
 if (adc_key_in > 1000) return btnNONE;
 if (adc_key_in < 50)   return btnRIGHT;
 if (adc_key_in < 250)  return btnUP;
 if (adc_key_in < 450)  return btnDOWN;
 if (adc_key_in < 625)  return btnLEFT; //Changed value to 625 do to double read from select button Default is 650.
 if (adc_key_in < 850)  return btnSELECT;
 return btnNONE;
}
// Setup relay shield pin array.
int relayPin[] = {2, 3, 11, 12};
//int pinCount = 4;

// Set On/Off Differentials for collector/tank temperatures.
const int diffON = 5;
const int diffOFF = 2;

// Set Default Thermostat temperature
int setTemp = 60;
int setTemp2 = 60;

//Used for calibration
int offSet[] = {-2, -1, 0, 1, 2};

//Button Variables.
int select = 0;
int up = 0;
int down= 0;
int backLight = 10;
boolean BLbutton = false;

//void RadiantMain()//RadiantMain setup
{
 lcd.begin(16, 2);
 lcd.setCursor(0,0);
 //Introduction Screen
 lcd.print("2 zone");
 lcd.setCursor(0,1);
 lcd.print("Radiant floor");
 delay(2000);

  for (int thisPin = 0; thisPin < pinCount; thisPin++)
   { pinMode(relayPin[thisPin], OUTPUT);}

 }
// Read average voltage from sensors
int ReadSens(int x)
{
  int i;
  int sval = 0;
    for (i = 0; i < 10; i++)
    { sval = sval + analogRead(x); }
  sval = sval / 10;
  return sval;
}
// Calculate temperature in F from voltage of sensors.
int getTemp(int y)
{
  //Convert to Celcius
  float a = (((y / 1024.0) * 5000)/10)-273.15;
  //Convert Celcius to Fahrenheit
  float b = a * 9.0 / 5.0 + 32.0;
  return b;
}

void RadiantRun()//need RadiantRun loop
{
 // Get average Voltage
 int z1flr = ReadSens(1);//zone  1 floor temp
 int z2flr = ReadSens(2);//zone2 floor temp
 int z1line = ReadSens(3);//zone 1 return line temp
 int z2line = ReadSens(4);//zone 2 return line temp
 int pmp = ReadSens(5);
 // Get Temperatures & Apply OffSet { -2, -1 , 0, 1, 2 }
 int zone1floortemp = (getTemp(z1flr) + offSet[0]);
 int zone2floortemp = (getTemp(z2flr) + offSet[0]);
 int zone1linetemp = (getTemp(z1line) + offSet[0]);
 int zone2linetemp = (getTemp(z2line) + offSet[0]);
 int pump = (getTemp(pmp) + offSet[0]);

  //Backlight button selection...
  if (BLbutton == true){pinMode(backLight, INPUT);} //turn backlight off
    else{pinMode(backLight,OUTPUT);} //turn backlight on
 // Display screens
  if (select == 3){select = 0;}
  if (select == 0){
    lcd.clear(); lcd.setCursor(0,0);
    lcd.print("  Ambient Temp ");
    lcd.setCursor(6,1);
    lcd.print(zone1floortemp);
    lcd.print(" F");
}
  if (select == 1)
{
    lcd.clear(); lcd.setCursor(0,0);
    lcd.print("Set Ambient To:");
    lcd.setCursor(6,1);
    lcd.print(setTemp);
    lcd.print(" F");
}
  if (select == 2)
{
    lcd.clear(); lcd.setCursor(0,0);
    lcd.print("Z1F ");
    lcd.print(zone1floortemp);
    lcd.print("F");

    lcd.setCursor(9,0);
    lcd.print("Z2F ");
    lcd.print(zone1floortemp);
    lcd.print("F");

    lcd.setCursor(9,1);
    lcd.print("Z2L ");
    lcd.print(zone2linetemp);
    lcd.print("F");

    lcd.setCursor(0,1);
    lcd.print("Z1L ");
    lcd.print(zone1linetemp);
    lcd.print("F");

}

lcd_key = read_LCD_buttons();  // read the buttons
 switch (lcd_key)
 {
   case btnSELECT:{ BLbutton = !BLbutton; delay(100); break; }
   case btnUP:    { setTemp++; select = 1; delay(100); break; }
   case btnDOWN:  { setTemp--; select = 1; delay(100); break; }
   case btnRIGHT: { select++; delay(100); break; }
   case btnLEFT:  { select--; delay(100); break; }
 }

// only 1 zone at a time_____________NOT IMPLEMENTED YET____________

// zone 1
// if floor temp zone 1 = less then set temp then open valve zone 1 turn on pump
  // if(z1flr <= (setTemp + diffOFF))
  // {digitalWrite(relayPin[3], HIGH);} // pump on
  // {digitalWrite(relayPin[12], HIGH);} // valve 1 on
  // {digitalWrite(relayPin[11], LOW);} // valve 2 off

// if floor temp zone 1 = set temp then close valve zone 1 turn off pump
  // if(z1flr = (setTemp + diffOFF))
  // {digitalWrite(relayPin[3], LOW);} // pump off
  // {digitalWrite(relayPin[12], LOW);} // valve 1 off

// // if floor temp zone 2 = less then set temp and  zone 1  = less then set temp zone 2 valve off
//   if(z1flr <= (setTemp + diffOFF) && (z1flr < (setTemp)))
//   {digitalWrite(relayPin[11], LOW);} // valve 2 off

// zone 2
// if floor temp zone 1 = less then set temp then open valve zone 1 turn on pump
  // if(z1flr <= (setTemp + diffOFF))
  // {digitalWrite(relayPin[3], HIGH);} // pump on
  // {digitalWrite(relayPin[11], HIGH);} // valve 2 on
  // {digitalWrite(relayPin[12], LOW);} // valve 1 off

// if floor temp zone 1 = set temp then close valve zone 1 turn off pump
  // if(z1flr = (setTemp + diffOFF))
  // {digitalWrite(relayPin[3], LOW);} // pump off
  // {digitalWrite(relayPin[11], LOW);} // valve 2 off

// if floor temp zone 1 = less then set temp and  zone 2  = less then set temp zone 1 valve off
  // if(z1flr <= (setTemp + diffOFF) && (z1flr < (setTemp)))
  // {digitalWrite(relayPin[12], LOW);} // valve 1 off

  delay(500);

}
//RADIANT MAIN CODE ENDS HERE___________________________________________________

//relay pinouts
//Digital 12 – controls RELAY 1 COM1 pin zone 1 valve
//Digital 11 – controls RELAY 2 COM2 pin zone 2 valve
//Digital 3 – controls RELAY 3 COM3 pump
//Digital 2 – controls RELAY 4 COM4 open

//sensors:
//flr1 = floor temp zone 1 sensor
//flr2 = floor temp zone 2 sensor
//pmp = pump OFF/ON
//z1= zone 1 line temp sensor
//z2 = zone 2 line temp sensor

```

# Answer
Your code for RadiantMain is:

```
void RadiantMain()

{
 //Serial.println("test");

 lcd.begin(16,2);
 lcd.setCursor(0,0);
 //Introduction Screen
 lcd.print("Solar Collection");
 lcd.setCursor(0,1);
 lcd.print("& Radiant Heater");
 delay(2000);

   Serial.println("test");
   //CODE STOPS HERE LOOPS BACK TO 'void MainMenuDisplay()'

  for (int thisPin = 0; thisPin < pinCount; thisPin++)
   { pinMode(relayPin[thisPin], OUTPUT);}
 }

```

You say "CODE STOPS HERE" in a comment, but all it does after printing "test" is set some pins to output mode. Is that not happening? Are you expecting something else?

If you want some of the other functions (like RadiantRun) to do something then they must be called from RadiantMain or elsewhere.

---

> I need to be able to use the menu sketch to run 3 different functions. MenuA &MenuB to manually run the system in manual mode and a third menu item (MenuC) to run the 2nd sketch in auto mode.

You need to make that happen by calling the appropriate functions in "the second sketch" when the appropriate menu button is pressed.

Merely putting the code into the same file doesn't accomplish this.

Exactly what you want to happen "in auto mode" isn't clear to me. You need to be clear in your own mind what that is. For example, taking a reading, adjusting the water valves, waiting a minute, and doing it again.

Once you are clear what you want to happen in that mode, you call the appropriate functions to achieve that.

You haven't answered the questions in the comments under your main question. Without those answers no-one can help you.
> 0 votes

---
Tags: code-review
---


# Question
Title: Why a Arduino UNO R3 board can use in Windows 10 but can't be used in My Macbook Air(M1)?
In Windows 10, everything is well. But when I use it in my macbook, it even can't recognize the port.

This is official description about driver.

# Answer
No driver necessary on MacOS which is essentially derived from UNIX/Linux. It should be plug & play.
It looks like the Air is not recognizing the Uno. Try opening a Terminal console and type `ls /dev/tty.*` You should get a list of 'Serial Devices' connected, try the 'ls /dev/tty.\* with the Uno plugged and unplugged, any difference should reveal the name of Uno port. If no difference I would suspect the cable you are using to connect the Uno. If you are able to identify the Uno port that same name should be selectable in the Arduino IDE when you open it.

Just realized Stack Exchange is not showning my answer correctly 'ls /dev/tty.' should have an asterisk after the 'dot'.
> 1 votes

---
Tags: arduino-uno, mac-os
---


# Question
Title: Using internal voltage reference for sensor
i am using 3.7~4.2V lithium battery. I am using internal voltage reference to read constant battery voltage as we know that the battery voltage level depletes overtime. The problem is that my sensor (mini solar panel) reads max value under little light and does not go beyond that level no matter how much light falls onto it in the later stage.

# Answer
> The problem is that my sensor (mini solar panel) reads max value under little light and does not go beyond that level no matter how much light falls onto it in the later stage.

Open voltage is not a good way to read the light level hitting a solar panel in this situation. Much better is to measure the current generated by the solar cell by adding a resistor across it here...

The value of the resistor can be found using...

`V=IR`

... where ...

`V`=1.1 volts

`I`=the maximum current the solar cell can generate in full light

If you do this, then you can read the `A1` pin using the 1.1V ref and you will be able to measure the full range of light conditions using the solar cell with simple Arduino code like this..

```
analogReference(INTERNAL);  // a built-in reference, equal to 1.1 volts
int v=analogRead(A1);       // Returns value 0-1023 representing light level

```

PS: Note if you measure the battery voltage with a divider as shown, you will be drawing current (about 0.8 milliamps when the battery reaches its minimum voltage) ALL THE TIME - even when the circuit is off. You do not want to do this with a lithium battery since under-voltaging it can potentially cause permanent damage to it. You really should heed my answer to your other question here.

PPS: It is usually best to ask your real question directly rather than asking a bunch of questions that are synthetic and reflect problems you *think* you have rather than the problems you actually do have. Your supplied code and drawings should match the thing you are asking and the thing you are actually working on (and each other!). It is often the case that the problem is not where you think it is, and so showing code and drawings that do not reflect what is really going on just wastes people's effort and does not ultimately help you solve your real problem. :)
> 2 votes

---
Tags: arduino-uno, programming, attiny, analog-sampling, solar
---


# Question
Title: MQTT subscribe callback fails to be called in ESP8266 deepsleep mode
Refer to

I executed the code in the given link. However i am not able to receive the subscribe message that are send from MQTT test broker(MQTT Lens) on the serial console.

Please help. I am receiving successful call to both publish methods

```
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
const char* ssid = "honored";
const char* ss_pswd = "12345678";
const char* mqtt_server = "iot.eclipse.org";

void callback(char* topic, byte* payload, unsigned int length);
WiFiClient EspClient;

PubSubClient client(EspClient);

void wifi_setup() {
  Serial.print("Connecting to: ");
  Serial.println(ssid);
  WiFi.begin(ssid, ss_pswd);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.println(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}
void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    String ClientId = "ESP8266";
    ClientId += String(random(0xffff), HEX);
    if (client.connect(ClientId.c_str())) {
      Serial.println("connected");
      client.publish("outtopic", "hello world, finally");
      client.subscribe("/room/test");
    } else {
      Serial.print("failed, rc=");
      Serial.println(client.state());
      Serial.println("Try again...");
      delay(5000);
    }
  }
}
void sendMQTTMessage() {
  Serial.println("sending your message");
  if (!client.connected()) {
    reconnect();
  }
  client.publish("/sensor/pir", "on");
}
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived: ");
  Serial.println(topic);
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
}

void setup() {
  Serial.begin(115200);
  wifi_setup();
  client.setServer(mqtt_server, 1883);
  sendMQTTMessage();
  client.setCallback(callback);
  delay(2000);
  Serial.println("going into deep sleep");
  ESP.deepSleep(10 * 1000000);
}

void loop() {

}

```

# Answer
My solution: update\_mqtt() is called before deepSleep

```
PubSubClient mqtt_client(client);
boolean cb = false;

void callback_mqtt_switch(char* topic, byte* payload, unsigned int length) {
  String lowerstr = "";
  for (uint8_t i = 0; i < length; i++) {
    lowerstr += (char)payload[i];
  }
  lowerstr.toLowerCase();
  DebugOut("Sleep payload: " + lowerstr);
  if (!back_to_sleep) {
    sleep_on = lowerstr == "ein";
  }
  cb = true;
}

void update_mqtt() {
  int i = 0;
  while (!cb && i++ < 30) {
    mqtt_client.loop();
    delay(10);
  }
  #ifdef TEST
    Serial.print("Warte ");
    Serial.println(i * 10); // max. 300ms gewartet
  #endif
  cb = false;
}

```
> 1 votes

---
Tags: esp8266, iot, mqtt
---


# Question
Title: Will an Arduino Nano work instead of Teensy 3.2?
I hope this is ok to post here and I appreciate any suggestions or help and opinions/facts to make this work.

First off I’ve **Never** programmed an Arduino device!

I was looking at this project: https://learn.adafruit.com/pinball-controll-ipad/duo-pinball-teardown

I would like to use the cheaper **Arduino nano** type board, and use the provided code to program it.

I have the same device (pinball Duo controller as in the project) just wanted to know if I attempt this will the **atmega328P Nano** achieve the same results?

Thank you,

Shlade

# Answer
> 3 votes
No, you can't use Adruino Nano, because in this project the Teensy board has been used as an USB Keayboard and Nano has separate communication chip (FTDI or CH430) that can't emulate USB keyboard.

However you don't have to use Teensy boards, you can use any board that has native USB support. For example Arduino Micro, Arduino Pro Micro, Arduino Leonardo. All are using Atmega32u4.

You can probably find many more boards with different MCUs (usually they don't have any dedicated communication chip). I think for example RPi Pico, Seeed studio xiao BLE (on this one you might be able to pull even bluetooth mouse emulation), ...

If you want further infos here is the pinmap for you :

---
Tags: programming, adafruit, serial-data, keyboard, components
---


# Question
Title: Arduino code working via IDE, not via PlatformIO Arduino code
I have a working Arduino code. The code works as intended when I upload it to an Arduino Nano using the old bootloader via the Arduino IDE. However, when I upload the same code via PlatformIO, the code uploads successfully but does not work as intended. There are no errors or warnings during the upload process, and I am having trouble figuring out what could be causing the issue.

Now for troubleshooting I am using simple blink example.

```
#include <Arduino.h>
// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on (HIGH is the voltage level)
  delay(1000);                      // wait for a second
  digitalWrite(LED_BUILTIN, LOW);   // turn the LED off by making the voltage LOW
  delay(1000);                      // wait for a second
}

```

*1st PlatformIO configuration .ini*

```
[env:nanoatmega328]
platform = atmelavr
board = nanoatmega328
framework = arduino
debug_port = COM3
monitor_speed = 115200

```

I have also tried following but no luck.

*2nd PlatformIO configuration .ini*

```
[env:nanoatmega328]
platform = atmelavr
board = nanoatmega328
framework = arduino
board_oldbootloader = true
debug_port = COM3
monitor_speed = 115200

```

Any suggestions on how to debug this problem or what might be causing the issue? Thank you.

# Answer
> 2 votes
I had a similar behavior for a while and nothing I would change in the PlatformIO .ini configuration file seemed to help. I tried to re-init and clean the project, but also didn't seem to help.

Eventually, what worked for me was to start a new fresh PlatformIO project and migrate the files over.

I suspect that under certain conditions (that may be related to the project settings), PlatformIO fails to upload the script, yet it claims that the upload was successful.

---
Tags: arduino-ide, arduino-nano, ide, platformio
---


# Question
Title: Timer 1 "Set on Compare Match" in Normal Mode - Not working
I'm using the hardware timers on the 328 for phase angle control of a triac with zero-crossing detection. I am encountering some strange behavior with the "Set on Compare Match" feature not working as expected on Timer1. I am attempting to replicate the red "gate" trace here: https://playground.arduino.cc/Main/ACPhaseControl/, but with my own implementation in code.

Before building the triac and zero-cross detection circuit, I am using another timer (Timer0) to simulate a 120Hz AC square wave (2x the 60Hz frequency because the double crossing pulse will arrive twice a cycle).

The output of the synthesized AC square wave is fed into an external interrupt pin (INT0) with a jumper. The correct functionality of the program is a short pulse to fire the triac at some phase delay relative to the zero crossing interrupt event (another example: https://www.homemade-circuits.com/wp-content/uploads/2020/07/half-phase-control.jpg)

I configure Timer 1 in normal mode, and define compare levels for both OCR1A and OCR1B. OCR1A is the "phase delay" from zero crossing at which to fire the triac, and OCR1B sets the duration of the pulse used to fire the triac. In my code, Method 1 is working and producing the intended output, while Method 2 is not working (output is always ON). For brevity, I am highlighting the differences between the two methods below, and the rest of the code is the same.

Method 1:

* Set OC1A to do nothing on compare (normal port operation) `TCCR1A=0;`
* "Manually" turn on the pin inside of the interrupt handler for output compare A. It will later be turned off in the interrupt handler for output compare B: `PORTB=(1<<PORTB1);`

This produces the following (correct) output. In the oscilloscope screenshot, the yellow trace is the simulated AC square wave, and the green trace is to be the gate voltage on the triac. https://i.stack.imgur.com/tpSAw.png

Method 2:

* Enable the OC1A "Set at compare match" bit in the TCCR1A register: `TCCR1A |= (1 << COM1A1) | (1 << COM1A0);`
* In theory, this means that I don't have to manually turn on the pin inside the interrupt handler for compare A, because it's already been turned on for us by the Compare Match Output Unit.

https://i.stack.imgur.com/45tFA.png

Note that in both methods, I still need to "manually" turn off the pin inside the output compare B interrupt handler because OC1A and OC1B are not the same physical pin: `PORTB=0;`

In Method 2, the pin is held ON, with no indication that the interrupt handler for output compare B is doing anything. My mental model of the port is that *as long as the bit in the data direction register is set for that port, both the output compare unit and CPU can write to the pin*. It appears that the pin is always being held ON, even after it is turned OFF by the CPU. Does the compare unit lock/latch the pin until the next clock cycle, or am I missing something else? Some tips here would be much appreciated.

I can prove that the output is indeed connected to OC1A because OC1A is PB1 which is connected to the oscilloscope and is being toggled in Method 1. I have vertically scaled OC1A (green) for readability against OC0A.

I have been referencing Section 13 of https://www.sparkfun.com/datasheets/Components/SMD/ATMega328.pdf for most of this task.

My code below for Method 1 is presented. To get Method 2, toggle the comments on the indicated lines.

```

#define F_CPU 16000000L

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

/*
For reference:
OCR1A = turn_on_timer_level
OCR1B = turn_on_timer_level + pulse_width

*/

int timer0_ac_sim_val = 64;    // Measured in clock ticks with prescale=1024
int turn_on_timer_level = 500;    // Measured in clock ticks with prescale=64
int pulse_width = 200;    // Measured in clock ticks with prescale=64

ISR(INT0_vect){
    // ISR at output compare A of timer 0 turns on timer 1 - simulates what happens when a zero crossing rising edge is detected on a 120Hz AC sine wave
    TCCR1B |= (1<<CS11) | (1<<CS10);
    TCNT1 = 0;
}

ISR(TIMER1_COMPA_vect){
    // ISR at output compare A of timer 1 turns on the pin
    PORTB = (1<<PORTB1);   // Turn on the pin COMMENT FOR METHOD 2
}

ISR(TIMER1_COMPB_vect){
    TCCR1B = 0; // Turn off the timer
    PORTB = 0;  // Turn off the pin
}

int main(){

    // Timer 0 setup for a 120Hz square wave on OC0A
    DDRD |= (1<<PD6);

    TCCR0A = 0x0;
    TCCR0A |= (1<<COM0A0) | (1<<WGM01);  // Set the output to toggle on compare

    TCCR0B = 0x0;
    TCCR0B |= (1<<CS02) | (1<<CS00);     // Configure with a prescale of 1024 and start clock

    OCR0A = timer0_ac_sim_val;  // Calculate this value for a 120Hz square wave, doesn't change.

    // Enable external interrupt 0 to trigger on a rising edge - set the External Interrupt Control Register
    EICRA |= (1<<ISC01) | (1<<ISC00);
    EIMSK |= (1<<INT0);

    // Global interrupt enable
    sei();

    // Timer 1 setup
    DDRB |= (1<<PORTB1);

    TCCR1A = 0x0;   // No pin action on output compare
    // TCCR1A |= (1 << COM1A1) | (1 << COM1A0);    // Set OC1A on compare match UNCOMMENT FOR METHOD 2

    TCCR1B = 0x0;   // Disable clock

    OCR1A = turn_on_timer_level;  // Delay between OC0A rise and OCR1A trigger
    OCR1B = turn_on_timer_level + pulse_width;   // Delay between OC0A rise and OCR1B trigger

    // Enable timer 1 interrupts
    TIMSK1 |= (1<<OCIE1A) | (1<<OCIE1B);

    while(1){
    };
}

```

# Answer
> My mental model of the port is that as long as the bit in the data direction register is set for that port, both the output compare unit and CPU can write to the pin.

Your assumption is incorrect. See section 13.11.1 of the datasheet you linked.

> If one or both of the COM1A1:0 bits are written to one, the OC1A output overrides the normal port functionality of the I/O pin it is connected to.

Thus, the "normal" functionality being overridden precludes your changing the pin yourself. You would need to set those bits to zero in the ISR to reclaim the use of the port, and set them back to one when required.
> 0 votes

# Answer
For those who might be interested, after fixing the problem I decided to implement the same functionality using Fast PWM mode instead of CTC mode. In trying to debug my original issue, I came across a similar post, to which one of the answers was:

https://arduino.stackexchange.com/a/30529/89096

> The PWM modes manage pin at both ends of the cycle.
>
> The point of the CTC modes is that they manage the pin only at one end of the \>count, but allow you to manage the other end explicitly.
>
> To manage both ends explicitly, you use normal mode.

I didn't fully realize what that meant until now, but it clicked. In PWM mode, the hardware timer takes care of the pin toggling for us, on both sides of the waveform. We would use Normal or CTC modes if we wanted to do manage one or both sides of the waveform differently. But my application fits perfectly in the Fast PWM category, so I decided to implement that as well. This saves an ISR by not making the CPU "manually" toggle the pin on and off each time. The only difference is that the output is on OC1B (PORTB2) now instead of OC1A (PORTB1).

```
#define F_CPU 16000000L

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

int timer0_ac_sim_val = 64;    // Measured in clock ticks with prescale=1024
int turn_on_timer_level = 400;    // Measured in clock ticks with prescale=64
int pulse_width = 100;    // Measured in clock ticks with prescale=64

ISR(INT0_vect){
    // ISR at output compare A of timer 0 turns on timer 1 - simulates what happens when a pulse is received from the zero crossing detector
    TCCR1B |= (1<<CS11) | (1<<CS10) | (1<<WGM13) | (1<<WGM12);
    TCNT1 = 0;
}

ISR(TIMER1_COMPA_vect){
    // ISR at output compare A of timer 1 turns on the pin
    TCCR1B = 0; // Turn off the timer
}

int main(){
    // Timer 0 setup for a 120Hz square wave on OC0A
    DDRD |= (1<<PD6);

    TCCR0A = 0x0;
    TCCR0A |= (1<<COM0A0) | (1<<WGM01);  // Toggle mode - non-PWM

    TCCR0B = 0x0;
    TCCR0B |= (1<<CS02) | (1<<CS00);     // Configure with a prescale of 1024, start clock

    OCR0A = timer0_ac_sim_val;

    // Enable external interrupt 0 to trigger on a rising edge - set the External Interrupt Control Register
    EICRA |= (1<<ISC01) | (1<<ISC00);
    EIMSK |= (1<<INT0);

    // Enable interrupts
    sei();

    // Timer 1 setup - 16 bit resolution with a prescale of 8 gives a max period of 1/(16e6/8/65536) = 32.78ms
    DDRB |= (1<<PORTB2);

    // Set WGM12 (CTC) to 1 and start the timer with a prescaler of 1024   -> This starts the timer in CTC mode
    TCCR1A = (1<<COM1B1) | (1<<COM1B0) | (1<<WGM11) | (1<<WGM10);  // Set COM1B1 and COM1B0 to 1 for inverting mode. For fast PWM set WGM11 and WGM10
    TCCR1B = 0x0;   // Start with clock disabled

    OCR1A = turn_on_timer_level + pulse_width;
    OCR1B = turn_on_timer_level;

    // Enable timer 1 interrupts
    TIMSK1 |= (1<<OCIE1A);

    while(1){

    }

```
> 0 votes

---
Tags: atmega328, timers, avr
---


# Question
Title: 1MHZ Attiny85 RF with MANCHESTER library
I'm trying to set up a transmitter made by the following components :

* **Attiny85 (I need 1MHZ speed)**
* **Cheap 433mhz transmitter (FS1000A)**

The library I am using is the Manchester library GitHub. The attiny85 and the transmitter are powered with **regulated 5V**. I set up **1MHZ when burning the bootloader** for the tiny.

I am **successful at transmitting with 8 AND 16MHZ with my Attiny85**, however, 1MHZ seems to malfunction. For 1MHZ on the tiny, this line need to be added in order to adjust timings :

```
man.workAround1MhzTinyCore();

```

Here is the complete code :

```
#include <Manchester.h>
/*
  Manchester Transmitter example
  In this example transmitter will send one 16 bit number
  per transmission.
  Try different speeds using these constants, your maximum
  possible speed will depend on various factors like transmitter
  type, distance, microcontroller speed, ...
  MAN_300 0
  MAN_600 1
  MAN_1200 2
  MAN_2400 3
  MAN_4800 4
  MAN_9600 5
  MAN_19200 6
  MAN_38400 7
*/
#define TX 2 //pin where your transmitter is connected

uint8_t transmit_data = 11;
void setup() {
  man.workAround1MhzTinyCore();
  //pinMode(RX, OUTPUT);
  man.setupTransmit(TX, MAN_300);
  pinMode(1, OUTPUT);
}
void loop() {
  digitalWrite(1, HIGH);
  man.transmit(transmit_data);
  delay(100);
  digitalWrite(1, LOW);

  delay(200);
}

```

**Someone else has/had this issue** Can't transmit on @1MHZ attiny85, and i don't know if it has been fixed or not. I am unsure if the library is still updated, and if this issue isn't with the library itself.

Does anyone have any leads or fix for that issue ? That would greatly help, Thanks

# Answer
Ok funny story, I think I found a solution, not sure why, but : My setup (the same) :

* Attiny85 (1MHZ (set on bootloader))
* Cheap 433mhz transmitter (FS1000A)
* Attiny microcontrollers library

When burning the bootloader with 1MHZ, and uploading sketch, it would seem that **removing the line `man.workAround1MhzTinyCore();` makes it work.**

**Without the line it's working, and with the work around it is NOT**

Voila !
> 0 votes

---
Tags: library, rf, attiny85
---


title: Change Interrupts on the ATTiny 88

text:
# Question
Title: Change Interrupts on the ATTiny 88
I am working on a project that requires a number of I/O pins for various purposes. I chose the ATTiny88 because it has plenty of GPIO pins, and is relatively inexpensive.

Here is the updated code per timemage, with many thanks!

```
#include <Arduino.h>
#include <TM1637Display.h>
#include "PinChangeInterrupt.h"

int counter = 0;
bool Update = false;
int currentStatePhase_B;
int lastStatePhase_B;

// Shutdown Output
#define SW 11

// Rotary Encoder Inputs
#define Phase_A 13
#define Phase_B 12
#define DIO 3
#define CLK 4

TM1637Display display(CLK, DIO);

void setup() {

  // Set encoder pins as inputs
  pinMode(Phase_A,INPUT);
  pinMode(Phase_B,INPUT);
  pinMode(SW, OUTPUT);

    // Read the initial state of Phase_B
    lastStatePhase_B = digitalRead(Phase_B);

    // Call updateEncoder() when any high/low changed seen
    // on interrupt 0 (pin 2), or interrupt 1 (pin 3)
    attachPCINT(digitalPinToPCINT(Phase_A), updateEncoder, CHANGE);
    attachPCINT(digitalPinToPCINT(Phase_B), updateEncoder, CHANGE);

  display.setBrightness(0x0f);
  display.clear();
}

void loop() {
  delay(100);
    if (Update){
        // Show decimal numbers with/without leading zeros
    display.showNumberDec(counter, false);
    // Expect: ___0
        Update = false;
    }
}

void updateEncoder(){
  delay (4);
    // Read the current state of Phase_B
    currentStatePhase_B = digitalRead(Phase_B);

    // If last and current state of Phase_B are different, then pulse occurred
    // React to only 1 state change to avoid double count
    if (currentStatePhase_B != lastStatePhase_B  && currentStatePhase_B == 1){

        // If the Phase_A state is different than the Phase_B state then
        // the encoder is rotating CCW so decrement
        if (digitalRead(Phase_A) != currentStatePhase_B) {
            counter --;
        } else {
            // Encoder is rotating CW so increment
            counter ++;
        }

    if (counter > 1023){
      counter = 1023;
    }
    if (counter < 0){
      counter = 0;
    }
    delay(15);
    }

    // Remember last CLK state
    lastStatePhase_B = currentStatePhase_B;
    Update = true;
}

```

It is now capturing most, but not by any means all, interrupts, but the direction is highly unreliable. More often than not, it counts up regardless of which way the encoder is turned,and often counts down when the encoder is turned clockwise.

Here is what seems to be a good reference: ATtiny88 8-bit Microcontroller

# Answer
> 3 votes
### Interrupt types

> One source says there are only two interrupt pins, ...

There are two "*external* interrupt" pins; that is the term you'll find in the chip's datasheet. This is the term that refers to the kind of pins that `attachInterupt` uses. These are the ones in the pinout labeled INT0,INT1,INTn. The "external" term may be confusing for a couple of reasons. Lots of external things cause interrupts, but this name is applied to when you're not talking about events tied to particular peripherals, like USART (serial peripheral) receiving a character. The special function of "external interrupt" is *dedicated* to dispatching interrupts based on signals on these INT0/INT1/INT# pins. There's one interrupt vector for each of these signals (two in your case). As you've probably seen in the documentation they can be configured to trigger on rising or falling edges, both edges, and low levels. So, they're right about that to the extent that they're talking about the "external interrupt" pins.

The "external" name is also confusing because of what else you've found:

> Another source says there are quite a few Change Interrupt pins

This is also true. These are the "PCINT#" signal names listed in the chip pinout. These "*pin change* interrupts" are newer; not new, but new*er*. There exist(ed) AVR that had/have "external interrupts" but no "pin change interrupts". I'd like to think that if they were created at the same time they wouldn't have simply called the former ones "external", because these are no less external although they're less dedicated. There's only a single ISR/interrupt for each group of 8 PCINT pins. And unlike the others they only naturally detect that a pin has changed and nothing about the nature of that change (rising vs falling). But a lot of AVR support them and those that do have a significant number of them. In the case of your ATTiny88, all of the GPIO (Arduino "digital") pins are capable of dispatching a pin change interrupt. However, the Arduino AVR core doesn't provide a function for using them.

### Modifying NicoHood's PinChangeInterrupt library

One of the people that used to be in my circle was NicoHood, who created this PinChangeInterrupt library. I have a foggy memory of helping with bits of it.

What he did was model it after the normal `attachInterrupt` function. So, you can use it almost as though you have the `RISING`/`FALLING`/`CHANGE` "external interrupt" capability on all of your PCINT# pins; in your case all of your pins. Underneath it is tracking the state of each port pin to determine what has changed and in what direction. In other words, using an interrupt that fires given a change on any of 8 pins together with variables to synthesize per-pin callbacks for not just change but also specifically rising and falling if you want. This is not perfect it is possible to lose short lived events and it takes longer to dispatch your handler function. But it's probably fine for what you're doing.

It does not support your chip out of the box. However you can modify to support the ATTiny88; partially if you're not picky. You should find it in the library manager as "PinChangeInterrupt" by NicoHood, currently at version 1.2.9. If you install that it should show up under your sketchbook/libraries directory. You will need to edit the file at path:

\<sketchbook-directory\>`/libraries/PinChangeInterrupt/src/PinChangeInterruptBoards.h`

That's your local copy of this file.

Your ATTiny88's handling of PCINT is going to be nearly the same as the ATMega328P that's in the UNO. Or rather nearly a superset of it. The chips are closely related in a way. However, you have extra PCINT capable pins on the ATTiny88 that aren't available on the ATMega328P. So you can crudely hack in a line into this section to read:

```
#if defined(__AVR_ATmega328__) || defined(__AVR_ATmega328A__) || defined(__AVR_ATmega328PA__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) \
   || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168A__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega168PB__) \
   || defined(__AVR_ATmega88__) || defined(__AVR_ATmega88A__) || defined(__AVR_ATmega88PA__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PB__) \
   || defined(__AVR_ATtiny88__) \
   || defined(__AVR_ATmega48__) || defined(__AVR_ATmega48A__) || defined(__AVR_ATmega48PA__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega48PB__)

```

The addition of that second to last line above should make the library treat the ATTiny88 you have as though it were an ATMega328P. This compiles under ATTinyCore. I am not set up to test it on a real ATTiny88. But, I expect it will work if you try some examples.

Having done that, the library should be work on any of the pins that carry a PCINT0 through PCINT23 label. If you want it to work with PCINT24-PCINT27, that can be done, but requires more work. But given what you've said you probably don't need one of those four and they're not available on the DIP package which I'm guessing you have anyway.

### Updating your code

You would to `#include "PinChangeInterrupt.h"` at the top of your code, and then your current code:

```
    attachInterrupt(digitalPinToInterrupt(Phase_A), updateEncoder, CHANGE);
    attachInterrupt(digitalPinToInterrupt(Phase_B), updateEncoder, CHANGE);

```

then becomes:

```
    attachPCINT(digitalPinToPCINT(Phase_A), updateEncoder, CHANGE);
    attachPCINT(digitalPinToPCINT(Phase_B), updateEncoder, CHANGE);

```

With luck, that should do it provided `Phase_A` and `Phase_B` under your core (e.g. ATTinyCore) map to GPIO/Arduino "digital" pins that carry a PCINT# signal where the number less than 24.

As I said, I have no way of testing it on real hardware right now. But I expect it will work. If not, it is the sort of direction you need to go in.

### Doing PCINT yourself

You can also take a more direct approach with reading the datasheet and sorting out how to do what the library does for you, only manually. One of the examples NicoHood provided with the library is not really an example of using the library but rather an explanation as to what the library does in the form of code. Notice it doesn't actually include the library; it would operate stand alone. So if you want to understand the guts yourself by following the ATtiny88 datasheet, that's a place to start.

One reason you might want to do it yourself anyway is if your encoders are being operated quickly, to the point where you can't afford some of the extra effective dispatch time imposed by what the PinChangeInterrupt library is doing in sorting out which pin changed and how. If you handle PCINT yourself, you can make a point of putting your two encoder pins in completely different groups of 8 such that there is only one source of pin change interrupt for each ISR and so there is no need to check which pin caused the interrupt and to route that to another function.

---
Tags: arduino-nano, rotary-encoder
---


# Question
Title: How does the compiler/assembler work wrt bootloader?
I realized that on the atmega boards the bootloader is programmed into the chip.

I'm curious, when compiling a sketch how does the compiler/assembler differ from compiling a standard C program for a chip without a bootloader?

Is there still a main? Does the linker put the startup code in a different area? Obviously with the bootloader you're no longer compiling a program which places code at the reset address.

# Answer
On the Uno and similar AVR-based boards, the compiler and assembler are not aware of the bootloader. The compiled program starts at address zero. There you have the interrupt vector table, starting with the reset vector. That vector is a jump to the C runtime startup code, which does some low-level initialization, then calls `main()` from the Arduino core library, which calls `setup()` and `loop()` from your sketch.

The bootloader lives at the end of the flash. The AVR chip has a few bytes of non-volatile configuration memory called “fuses”. These bytes are configured by the Arduino board maker to dedicate the last 512 bytes of flash to the bootloader, and to start executing the code at the start of the bootloader on power up and on reset events. It is then the bootloader's responsibility to jump to address zero in order to start the user's program.
> 5 votes

---
Tags: arduino-uno, arduino-nano, c, bootloader, atmega
---


title: Setting float to two decimal places

text:
# Question
Title: Setting float to two decimal places
I'm trying to set my temperature measurements to two decimal places. Currently what I get are six decimal places. Here is my code:

```
#include "math.h"

...

(in loop)
temp1 = sensors.getTempCByIndex(0);
     temp1 = roundf(temp1*100)/100;

```

Once I push temp1 to Firebase realtime database there are sic decimals, such as 26.059999. I'm using dsb20 sensor for temperature measurements. What could be wrong?

Thanks for your help in advance!

# Answer
In addition to Majenkos answer:

A `float` cannot take any decimal number. It has a limited change and a limited resolution in that range you could say. So if often happens, that the flat (rounded) value is not a valid `float`. This is the case for `26.05`. There is no valid `float` value, that is exactly `26.05`. So the nearest valid `float` value is chosen. The following code would always print `26.059999`:

```
float i = 26.05;
Serial.println(i);

```

since the variable `i` contains the `float` number `26.059999` (nearest valid `float` value to `26.06`). That is the reason, why mostly the rounding of `float`s is only done directly with the outputting/printing. In that stage the number is not longer bound to the limitations of the `float` type (since it is internally not again saved in that type).
> 2 votes

# Answer
`float` variables don't have a number of decimal places: that's how they get their name: "floating point" - the decimal point floats around as needed.

It's only when you *output* the value that it's rendered with a fixed (or limited) number of decimal places. Using `Serial.print()` the second digit is the number of decimal points:

```
Serial.println(temp1, 6); // 26.059999
Serial.println(temp1, 2); // 26.06

```
> 1 votes

# Answer
one can convert to n decimals with the String Class

```
float num = 3.14159
String str1 = String(num, 1) // 3.1
String str2 = String(num, 2) // 3.14
String str3 = String(num, 3) // 3.141

```
> 1 votes

---
Tags: arduino-ide, esp32, ds18b20
---


# Question
Title: Cannot instantiate a parameterized object inside of another class
I'm having troubles understanding the inner workings of classes and such.

I have a class called `Attributes` that contains parameters. In my .ino, I can simply instantiate an object with `Attributes greenBark(1, 2);` and everything is hunkey dorey.

***Problem:*** Now I need to create a Attributes object in my other class, called Tree. I figured out if my constructor doesn't have parameters, I can create an object within another class just fine. However, my attributes class constructor has parameters. When I try to create an parameterized object within another class, the compiler tosses an error. **How can I create an attributes object within my tree class?** I'm sorry if I got some of these terms mixed up, I'm trying to keep up!

Here are my current files (made for this example:)

**The .ino file**

```
#include "attributes.h"
#include "tree.h"

Attributes greenBark(1, 2);

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

void loop()

{
  greenBark.printAttributes();
}

```

**attributes.cpp**

#include "attributes.h"

```
Attributes::Attributes(int size, int texture)

{
  _size = size;
  _texture = texture;
}

void Attributes::printAttributes()
{
  Serial.print("GreenBark Attributes: ");
  Serial.print("Size = ");
  Serial.print(_size);
  Serial.print(" Texure = ");
  Serial.print(_texture);
  Serial.println();
}

```

**attributes.h**

```
#pragma once
#include <Arduino.h>

class Attributes
{
  public:
    Attributes(int size, int texture); // constructor
    void printAttributes(); // method

  private:
    int _size = 0;
    int _texture = 0;
};

```

**tree.cpp**

```
#include "attributes.h"
#include "tree.h"

Tree::Tree()
{

}

```

**tree.h**

```
#pragma once
#include <Arduino.h>
#include "attributes.h"

class Tree
{
  public:

    Tree(); // constructor

    void makeTree(); // method

    // I want to create an attributes class object in my current class, so naturally I'd try to
    // create the object just like I did in my .ino sketch, but the below line doesn't work.

    //Attributes redBark(1, 2);

  private:
};

```

The error provided is this:

```
In file included from C:\Users\ajrob\Dropbox\Projects\Electronics\Arduino Sketchbook\ParameterizedConstructor\ParameterizedConstructor.ino:2:0:
C:\Users\ajrob\Dropbox\Projects\Electronics\Arduino Sketchbook\ParameterizedConstructor\tree.h:16:24: error: expected identifier before numeric constant
     Attributes redBark(1, 2);
                        ^
C:\Users\ajrob\Dropbox\Projects\Electronics\Arduino Sketchbook\ParameterizedConstructor\tree.h:16:24: error: expected ',' or '...' before numeric constant
In file included from C:\Users\ajrob\Dropbox\Projects\Electronics\Arduino Sketchbook\ParameterizedConstructor\tree.cpp:2:0:
C:\Users\ajrob\Dropbox\Projects\Electronics\Arduino Sketchbook\ParameterizedConstructor\tree.h:16:24: error: expected identifier before numeric constant
     Attributes redBark(1, 2);
                        ^
C:\Users\ajrob\Dropbox\Projects\Electronics\Arduino Sketchbook\ParameterizedConstructor\tree.h:16:24: error: expected ',' or '...' before numeric constant

exit status 1

Compilation error: expected identifier before numeric constant

```

# Answer
I see two options here:

You might follow jsotola's comment and initialize `redBark` with braces:

```
Attributes redBark{1, 2};

```

For some reason, the syntax with parentheses is not allowed when initializing an object in a class declaration, but the syntax with braces is OK.

The other option is to initialize redBark in the `Tree`'s constructor (and not in the class declaration) using an initializer list:

```
// In the class declaration:
Attributes redBark;

// The constructor:
Tree::Tree() : redBark(1, 2) {}

```
> 0 votes

---
Tags: class
---


# Question
Title: WS2812b - Interpolate pixels on neopixel matrix with mask
simplified my goal is to display a transitional Background and some shapes. This shapes are not moving hard rasterized by 1 pixel, more like .1 each cycle. So I need a way to interpolate the movement between the surrounding Neopixels.

Background works fine, so it's not relevant for now.

For the shapes the **first try** was to show a smooth movement of a square hardcoded. This works suitable, even its not bug free. I put the Code of the first attempt at the very end.

**After** that I wanted to implement an bitmap mask to show something more complex . That's where I am at currently. First of this attempt is to assume the whole mask is completly filled (again hardcoded).

The LEDs mostly keep completely on or off.

How do I get them fade them in an out at the outer sides?

I use an AI Thinker ESP 32 and 200 WS2812Bs.

Please ask any more infos that are required. Of course if you spot that my approach is unsuitable to begin with, pls tell me.

Infos for the Code: don't get lost on the "circle" variables. At the eary steps I showed a circle and soon realized its easier to step back to a Circle while working at the interpolation.

My Code with the bitmap

```
#include <Adafruit_NeoPixel.h>

#define PIN_NEO_PIXEL  13
#define NUM_PIXELS     400
#define num_row 20
#define num_col 20
#define circle_size_body 4
#define circle_size_border 5
#define circle_size_corona 7
#define DELAY_INTERVAL  100

float circle_PosX = 10;
float circle_PosY = 10;
int circle_direction = 1;
enum eIntersectingPart { None, Body, Border, Corona };

Adafruit_NeoPixel NeoPixel(NUM_PIXELS, PIN_NEO_PIXEL, NEO_GRB + NEO_KHZ800);

void setup()
{
  NeoPixel.setBrightness(100);
  NeoPixel.begin();
  Serial.begin(115200);           // set up Serial library at 9600 bps
}

float backgroundShift = 0;
float worldSpeed = .05;

void loop()
{
  if(circle_PosY <= 0 && circle_direction < 0
     || circle_PosY >= 10 && circle_direction > 0)
    circle_direction *= -1;
  circle_PosY += worldSpeed * circle_direction;
  circle_PosX += worldSpeed * circle_direction;
    Serial.print("circle_PosX ");
    Serial.print(circle_PosX);
    Serial.print(", circle_PosY ");
    Serial.print(circle_PosY);
    NeoPixel.clear();
    //Hintergrund setzen
    // setBackgroundColor();

    //Kreis malen
    drawCircle();

  // Serial.print("bgShift: ");
  // Serial.flush();
  NeoPixel.show(); // send the updated pixel colors to the NeoPixel hardware.
  // Serial.println(backgroundShift);
  backgroundShift += worldSpeed;
  delay(100);     // off time
}

uint32_t setBackgroundColor() {

  for(int led = 0; led < NUM_PIXELS; led++) {
    int coordinates[2];
    coordinateByLed(coordinates, led);

    byte ambientColors[3] = { 0, 0, 255 };
    int ambientCcolorS = (int)( sin( 0.3 * coordinates[0] + backgroundShift) * 127.0 );
    int ambientCcolorC = (int)( cos( 0.3 * coordinates[1] + backgroundShift) * 128.0);
    int amberC = (ambientCcolorS + ambientCcolorC + 255) / 2;

    NeoPixel.setPixelColor(
        led,
        NeoPixel.Color(amberC, amberC ,255));
  }
}

bool firstIteration = false;
void drawCircle() {
    //          x                   y                           Anteil
    byte bitmap[circle_size_corona + 1][circle_size_corona + 1];

    float startPositonX = circle_PosX - .5f * (float)circle_size_corona;
    float startPositonY = circle_PosY - .5f * (float)circle_size_corona;

    int lowerStartX = floor(startPositonX);
    int upperStartX = ceil(startPositonX);
    int lowerStartY = floor(startPositonY);
    int upperStartY = ceil(startPositonY);

    float proportionForLowerX = abs(upperStartX - startPositonX);
    float proportionForUpperX = 1 - proportionForLowerX;
    float proportionForLowerY = abs(upperStartY - startPositonY);
    float proportionForUpperY = 1 - proportionForLowerY;

    firstIteration = true;

    for(byte x = 0; x < circle_size_corona; x++) {
        for(byte y = 0; y < circle_size_corona; y++) {
            float proportion = 0;

            int lowerLedX = lowerStartX + x;
            int lowerLedY = lowerStartY + y;
            int upperLedX = upperStartX + x;
            int upperLedY = upperStartY + y;

            if(lowerLedX >= 0 || lowerLedX < num_col
                &&
                lowerLedY >= 0 || lowerLedY < num_row) {
                byte currentX = x;
                byte currentY = y;
                proportion = proportionForLowerX * proportionForLowerY;
                bitmap[currentX][currentY] += (byte)(proportion * 100);
                bitmap[currentX][currentY] = min(bitmap[currentX][currentY], (byte)100);

                if(lowerLedX == 6 && lowerLedY == 6) {
                    Serial.print(", x ");
                    Serial.print(x);
                    Serial.print(", y ");
                    Serial.print(y);
                    Serial.print(", partialProportion ");
                    Serial.print(proportion);
                    Serial.print(", newBitmapVal ");
                  byte newBitmapVal = bitmap[currentX][currentY];
                    Serial.print(newBitmapVal);
                    Serial.print(" || ");
                }
            }
            if(upperLedX >= 0 || upperLedX < num_col
                &&
                lowerLedY >= 0 || lowerLedY < num_row) {
                byte currentX = x + 1;
                byte currentY = y;
                proportion = proportionForUpperX * proportionForLowerY;
                bitmap[currentX][currentY] += (byte)(proportion * 100);
                bitmap[currentX][currentY] = min(bitmap[currentX][currentY], (byte)100);
                if(upperLedX == 6 && lowerLedY == 6) {
                    Serial.print(", x ");
                    Serial.print(x);
                    Serial.print(", y ");
                    Serial.print(y);
                    Serial.print(", partialProportion ");
                    Serial.print(proportion);
                    Serial.print(", newBitmapVal ");
                  byte newBitmapVal = bitmap[currentX][currentY];
                    Serial.print(newBitmapVal);
                    Serial.print(" || ");
                }
            }
            if(lowerLedX >= 0 || lowerLedX < num_col
                &&
                upperLedY >= 0 || upperLedY < num_row) {
                byte currentX = x;
                byte currentY = y + 1;
                proportion = proportionForLowerX * proportionForUpperY;
                bitmap[currentX][currentY] += (byte)(proportion * 100);
                bitmap[currentX][currentY] = min(bitmap[currentX][currentY], (byte)100);
                if(lowerLedX == 6 && upperLedY == 6) {
                    Serial.print(", x ");
                    Serial.print(x);
                    Serial.print(", y ");
                    Serial.print(y);
                    Serial.print(", partialProportion ");
                    Serial.print(proportion);
                    Serial.print(", newBitmapVal ");
                  byte newBitmapVal = bitmap[currentX][currentY];
                    Serial.print(newBitmapVal);
                    Serial.print(" || ");
                }
            }
            if(upperLedX >= 0 || upperLedX < num_col
                &&
                upperLedY >= 0 || upperLedY < num_row) {
                byte currentX = x + 1;
                byte currentY = y + 1;
                proportion = proportionForUpperX * proportionForUpperY;
                bitmap[currentX][currentY] += (byte)(proportion * 100);
                bitmap[currentX][currentY] = min(bitmap[currentX][currentY], (byte)100);
                bitmap[currentX][currentY] = min(bitmap[currentX][currentY], (byte)100);
                if(upperLedX == 6 && upperLedY == 6) {
                    Serial.print(", x ");
                    Serial.print(x);
                    Serial.print(", y ");
                    Serial.print(y);
                    Serial.print(", partialProportion ");
                    Serial.print(proportion);
                    Serial.print(", newBitmapVal ");
                  byte newBitmapVal = bitmap[currentX][currentY];
                    Serial.print(newBitmapVal);
                    Serial.print(" || ");
                }
            }

            firstIteration = false;
        }
    }

    firstIteration = true;
    for(int x = 0; x < circle_size_corona + 1; x++) {
        for(int y = 0; y < circle_size_corona + 1; y++) {
            int lowerLedX = lowerStartX + x;
            int lowerLedY = lowerStartY + y;
            int upperLedX = upperStartX + x;
            int upperLedY = upperStartY + y;

            if(
            // firstIteration
                lowerLedX == 6 && lowerLedY == 6
                  ||
                    upperLedX == 6 && lowerLedY == 6) {
                Serial.print(", startPositonX ");
                Serial.print(startPositonX);
                Serial.print(", x ");
                Serial.print(x);
                Serial.print(", y ");
                Serial.print(y);
                Serial.print(", lowerLedX ");
                Serial.print(lowerLedX);
                Serial.print(", lowerLedY ");
                Serial.print(lowerLedY);
            }

            if(lowerLedX >= 0 || lowerLedX < num_col
                &&
                lowerLedY >= 0 || lowerLedY < num_row) {
                setLedColorWithProportion(lowerLedX,lowerLedY, .01f * bitmap[x][y]);
            }

            firstIteration = false;
        }
    }

    Serial.print(" ");
    Serial.println();
}

void setLedColorWithProportion(
    int coordX, int coordY,
    float proportion)
{
    int led = ledByCoordinate(coordX, coordY);
    uint32_t ledColor = NeoPixel.getPixelColor(led);
    uint8_t partialColor = (uint8_t)((proportion ) * 255.0f );

    uint8_t white = (ledColor>>24) & 255;
    uint8_t red = (uint8_t)((1.0f - proportion) * ((ledColor>>16) & 255))
        + partialColor;
    uint8_t green = (ledColor>>8) & 255;
    uint8_t blue = ledColor & 255;

    if(
    // firstIteration
    coordX == 6 && coordY == 6
    ) {
        Serial.print(", prop ");
        Serial.print(proportion);
        Serial.print(", redValOld ");
        Serial.print(((ledColor>>16) & 255));
        Serial.print(", redValNew ");
        Serial.print(red);
    }

    ledColor = white;
    ledColor = (ledColor<<8) + red;
    ledColor = (ledColor<<8) + green;
    ledColor = (ledColor<<8) + blue;
    NeoPixel.setPixelColor(
        led,
        ledColor);
}

int ledByCoordinate(byte column, byte row) {
  return (row  * num_col) + (column);
}

void coordinateByLed(int coordinates[2], int led) {
  coordinates[0] = led % num_col;
  coordinates[1] = led / num_col;
}

```

---

First attempt without bitmap

```
#include <Adafruit_NeoPixel.h>

#define PIN_NEO_PIXEL  13
#define NUM_PIXELS     400
#define num_row 20
#define num_col 20
#define circle_size_body 4
#define circle_size_border 5
#define circle_size_corona 7
#define DELAY_INTERVAL  100

float circle_PosX = 10;
float circle_PosY = 10;
int circle_direction = 1;
enum eIntersectingPart { None, Body, Border, Corona };

Adafruit_NeoPixel NeoPixel(NUM_PIXELS, PIN_NEO_PIXEL, NEO_GRB + NEO_KHZ800);

void setup()
{
  NeoPixel.setBrightness(100);
  NeoPixel.begin();
  Serial.begin(9600);           // set up Serial library at 9600 bps
}

float backgroundShift = 0;
float worldSpeed = .01;

void loop()
{
  if(circle_PosY <= 0 && circle_direction < 0
     || circle_PosY >= 10 && circle_direction > 0)
    circle_direction *= -1;
  circle_PosY += worldSpeed * circle_direction;
  circle_PosX += worldSpeed * circle_direction;
    // Serial.print("circle_PosX ");
    // Serial.print(circle_PosX);
    // Serial.print(", circle_PosY ");
    // Serial.print(circle_PosY);
    NeoPixel.clear();
    //Hintergrund setzen
    // setBackgroundColor();

    //Kreis malen
    drawCircle();

  // Serial.print("bgShift: ");
  // Serial.flush();
  NeoPixel.show(); // send the updated pixel colors to the NeoPixel hardware.
  // Serial.println(backgroundShift);
  backgroundShift += worldSpeed;
  //delay(100);     // off time
}

uint32_t setBackgroundColor() {

  for(int led = 0; led < NUM_PIXELS; led++) {
    int coordinates[2];
    coordinateByLed(coordinates, led);

    byte ambientColors[3] = { 0, 0, 255 };
    int ambientCcolorS = (int)( sin( 0.3 * coordinates[0] + backgroundShift) * 127.0 );
    int ambientCcolorC = (int)( cos( 0.3 * coordinates[1] + backgroundShift) * 128.0);
    int amberC = (ambientCcolorS + ambientCcolorC + 255) / 2;

    NeoPixel.setPixelColor(
        led,
        NeoPixel.Color(amberC, amberC ,255));
  }
}

bool firstIteration = false;
void drawCircle() {
    float startPositonX = circle_PosX - .5f * (float)circle_size_corona;
    float startPositonY = circle_PosY - .5f * (float)circle_size_corona;

    int lowerStartX = floor(startPositonX);
    int upperStartX = ceil(startPositonX);
    int lowerStartY = floor(startPositonY);
    int upperStartY = ceil(startPositonY);

    float proportionForLowerX = abs(upperStartX - startPositonX);
    float proportionForUpperX = 1 - proportionForLowerX;
    float proportionForLowerY = abs(upperStartY - startPositonY);
    float proportionForUpperY = 1 - proportionForLowerY;

    // int endX = lowerStartX + circle_size_corona;
    // int endY = lowerStartY + circle_size_corona;

    firstIteration = true;

    for(int x = 0; x < circle_size_corona; x++) {
        for(int y = 0; y < circle_size_corona; y++) {
            int lowerLedX = lowerStartX + x;
            int lowerLedY = lowerStartY + y;
            int upperLedX = upperStartX + x;
            int upperLedY = upperStartY + y;

            /*if(firstIteration) {
                Serial.print(", startPositonX ");
                Serial.print(startPositonX);
                Serial.print(", x ");
                Serial.print(x);
                Serial.print(", y ");
                Serial.print(y);
                Serial.print(", lowerLedX ");
                Serial.print(lowerLedX);
                Serial.print(", lowerLedY ");
                Serial.print(lowerLedY);
            }*/

            if(lowerLedX >= 0 || lowerLedX < num_col
                &&
                lowerLedY >= 0 || lowerLedY < num_row) {
                    setLedColorWithProportion(lowerLedX,lowerLedY, proportionForLowerX * proportionForLowerY);
            }
            if(upperLedX >= 0 || upperLedX < num_col
                &&
                lowerLedY >= 0 || lowerLedY < num_row) {
                    setLedColorWithProportion(upperLedX,lowerLedY, proportionForUpperX * proportionForLowerY);
            }
            if(lowerLedX >= 0 || lowerLedX < num_col
                &&
                upperLedY >= 0 || upperLedY < num_row) {
                    setLedColorWithProportion(lowerLedX,upperLedY, proportionForLowerX * proportionForUpperY);
            }
            if(upperLedX >= 0 || upperLedX < num_col
                &&
                upperLedY >= 0 || upperLedY < num_row) {
                    setLedColorWithProportion(upperLedX,upperLedY, proportionForUpperX * proportionForUpperY);
            }

            firstIteration = false;
        }
    }
    // Serial.print(" ");
    // Serial.println();
}

void setLedColorWithProportion(
    int coordX, int coordY,
    float proportion)
{
    int led = ledByCoordinate(coordX, coordY);
    uint32_t ledColor = NeoPixel.getPixelColor(led);
    uint8_t partialColor = (uint8_t)((proportion ) * 255.0f );

    uint8_t white = (ledColor>>24) & 255;
    uint8_t red = (uint8_t)((1.0f - proportion) * ((ledColor>>16) & 255))
        + partialColor;
    uint8_t green = (ledColor>>8) & 255;
    uint8_t blue = ledColor & 255;

    ledColor = white;
    ledColor = (ledColor<<8) + red;
    ledColor = (ledColor<<8) + green;
    ledColor = (ledColor<<8) + blue;
    NeoPixel.setPixelColor(
        led,
        ledColor);
}

int ledByCoordinate(byte column, byte row) {

    /*if(firstIteration) {
        Serial.print(", column ");
        Serial.print(column);
        Serial.print(", row ");
        Serial.print(row);
        Serial.print(", ergebis ");
        Serial.print(((row  * num_col) + (column)));
    }*/
  return (row  * num_col) + (column);
}

void coordinateByLed(int coordinates[2], int led) {
  coordinates[0] = led % num_col;
  coordinates[1] = led / num_col;
}

```

# Answer
thanks for your advice. I stepped back to a 1D model, simplified, altered and it worked, with complex models (in 1D XD), a hard coded Array. So finally I went on for 2D and extended the code. Now it works.

Yes, it's kind of anti-aliasing.

For next I am thinking how to display multiple Elements with transparency (caused by anti aliasing or pregiven transparency).

Thats all for now.

For all who may be interested, heres my current Code.

```
#include <Adafruit_NeoPixel.h>

#define PIN_NEO_PIXEL  13
#define NUM_PIXELS     200
#define num_col 20
#define num_row 10
#define DELAY_INTERVAL  100

float circle_PosX = 6;
float circle_PosY = 6;
int circle_direction = 1;

Adafruit_NeoPixel NeoPixel(NUM_PIXELS, PIN_NEO_PIXEL, NEO_GRB + NEO_KHZ800);

void setup()
{
  NeoPixel.setBrightness(255);
  NeoPixel.begin();
  // Serial.begin(115200);           // set up Serial library at 9600 bps
}

float worldSpeed = .01;

void loop()
{
    if(circle_PosX <= 0 && circle_direction < 0
     || circle_PosX >= 20 && circle_direction > 0
     || circle_PosY <= 0 && circle_direction < 0
     || circle_PosY >= 10 && circle_direction > 0)
    circle_direction *= -1;
    circle_PosX += worldSpeed * circle_direction;
    circle_PosY += worldSpeed * circle_direction;

    NeoPixel.clear();

    //Kreis malen
    drawCircle();

    NeoPixel.show(); // send the updated pixel colors to the NeoPixel hardware.
    // delayMicroseconds(500);     // off time
    // readInput();
}
uint8_t bitmap[5][5] = {
    {0,0,1,0,0},
    {0,1,0,1,0},
    {1,0,0,0,1},
    {0,1,0,1,0},
    {0,0,1,0,0},
};

void drawCircle() {
    for(uint8_t pixelX = 0; pixelX < 5; pixelX++) {
        for(uint8_t pixelY = 0; pixelY < 5; pixelY++) {
            if(bitmap[pixelY][pixelX] == 1) {
                writeCircleToLEDs(
                    pixelX + circle_PosX,
                    pixelY + circle_PosY);
            }
        }
    }
}

uint8_t writeCircleToLEDs(float circlePosX, float circlePosY) {
    int lowerLedX = floor(circlePosX);
    int upperLedX = ceil(circlePosX);
    int lowerLedY = floor(circlePosY);
    int upperLedY = ceil(circlePosY);

    float upperLedXAmount = circlePosX - lowerLedX;
    float lowerLedXAmount = 1.0 - upperLedXAmount;
    float upperLedYAmount = circlePosY - lowerLedY;
    float lowerLedYAmount = 1.0 - upperLedYAmount;

    float amountLowerXLowerY = lowerLedXAmount * lowerLedYAmount;
    float amountUpperXLowerY = upperLedXAmount * lowerLedYAmount;
    float amountLowerXUpperY = lowerLedXAmount * upperLedYAmount;
    float amountUpperXUpperY = upperLedXAmount * upperLedYAmount;

    setColorOfLed(lowerLedX, lowerLedY, amountLowerXLowerY);

    // if(lowerLedX != upperLedX)
    {
        setColorOfLed(upperLedX, lowerLedY, amountUpperXLowerY);
    }
    // if(lowerLedY != lowerLedX )
    {
        setColorOfLed(lowerLedX, upperLedY, amountLowerXUpperY);
    }
    // if(lowerLedY != upperLedY )
    {
        setColorOfLed(upperLedX, upperLedY, amountUpperXUpperY);
    }
    /*
    Serial.print("circlePosX ");
    Serial.println(circlePosX);
    Serial.print("lowerLedX ");
    Serial.println(lowerLedX);
    Serial.print("lowerLedXAmount ");
    Serial.println(lowerLedXAmount);
    Serial.println("--------------------");*/

}

void setColorOfLed(uint8_t ledX, uint8_t ledY, float amount) {
    int ledNumber = ledByCoordinate(ledX, ledY);
    uint32_t  baseColor = NeoPixel.getPixelColor(ledNumber);
    uint8_t newRedColor = ((baseColor >> 16) & 255);
    newRedColor += (255 * amount);

    baseColor &= ~(255 << 16);
    baseColor |= (newRedColor << 16);

    NeoPixel.setPixelColor(
        ledNumber,
        baseColor);
}

uint8_t ledByCoordinate(uint8_t coordinateX, uint8_t coordinateY) {
    return coordinateX + num_col * coordinateY;
}

uint8_t rowReadPosY = 0;
void readInput() {
    bool changed = false;
    uint8_t rowReadPosX = 0;

    while(Serial.available() > 0) {
        char input = Serial.read();

        if(!isDigit(input)) continue;

        bitmap[rowReadPosY][rowReadPosX] = atoi(&input);

        rowReadPosX++;
        if(rowReadPosX >= 5) {
            rowReadPosY = ++rowReadPosY % 5;
            rowReadPosX = 0;
        }

        changed = true;
    }

    if(changed) {
        Serial.println("Ergebnis: ");

        for(uint8_t pixelX = 0; pixelX < 5; pixelX++) {
            for(uint8_t pixelY = 0; pixelY < 5; pixelY++) {
                Serial.print(bitmap[pixelY][pixelX]);
            }
            Serial.println();
        }

        Serial.print("Aktueller Cursor: (x,y) {");
        Serial.print(rowReadPosX);
        Serial.print(", ");
        Serial.print(rowReadPosY);
        Serial.println("}");
    }
}

```
> 1 votes

---
Tags: esp32, display, neopixel, ws2812, map
---


# Question
Title: Wemos C3 Mini (ESP32-C3) does not run firmware unless connected to pc
I've been using ESP32s and ESP8266 for a few years now and I thought I'd give these little boards a shot, they were cheaper for Bluetooth/WiFi combo, and I don't need all the bells and whistles of a full ESP32.

I have my firmware all debugged and working, it's been stable for a few months now. All it does is read a temperature from an Inkbird Bluetooth temperature sensor and log that info into a spreadsheet online for me via WiFi.

Up until this point I had the board connected via usb cable to my PC. Well I got a new PC and wanted to save a usb port so I moved it to a usb cable with an Apple AC wall adapter (5V 500mA). The board now never powers on.

Does anyone know what's happening here? It seems to not like booting unless it has a serial connection with the PC??? It doesn't like to power on if the PC is off either even though the usb port has power still.

I thought maybe this weird usb C port doesn't like 5V. So, I got it 3.3V via a breadboard power adapter rig. Nothing...

# Answer
Your program could be busy, waiting for the com port to open.
> 1 votes

---
Tags: power, esp32, bootloader
---


title: Read int from Serial

text:
# Question
Title: Read int from Serial
with the following sketch I should be able to read and store what is entered in the Serial monitor

```
void setup() {
  Serial.begin(115200);
  while(!Serial);
}

void loop() {

  Serial.println("Enter Zone Number: ");
  while(!Serial.available()){
  }
   int zone = Serial.parseInt();
   Serial.println(zone);

}

```

if I enter "1" I would except this:

```
Enter Zone Number:
1

```

but unfortunately I have this:

```
Enter Zone Number:
1
Enter Zone Number:
0

```

What am I missing?

# Answer
> 5 votes
`.parseInt()` reads incoming text up until either it times out or *until it reads something that isn't a number*.

You are sending a number, and most likely a line-ending. If that line-ending is a simple `\n` then that will trigger the "end of number" and will be discarded and the number returned. However, if you are sending `\r\n` (i.e., *CRLF*) then you effectively have two line endings there:

```
1\r\n

```

Parsed as:

```
1\r => return 1
\n => return 0

```

Relying on the (poorly written) Arduino stream parsing routines is not good. Not only are they blocking, but often they just don't work right.

Instead you should be reading the serial properly, taking account of line endings, and then converting the string you have read into a number using the likes of `atoi()`.

Tutorial on reading serial:

# Answer
> -1 votes
Here is a really nice and simple solution (More robust also concerning line breaks): https://stackoverflow.com/a/20962137/2714285

```
int x;
String str;

void loop() {
    if (Serial.available() > 0) {
        x = Serial.parseInt();
        str = Serial.readStringUntil('\n');
    }
}

```

---
Tags: serial, arduino-ide, input
---


# Question
Title: How to use arduino to run .exe file in a windows computer
Is there a way to run .exe file **on a windows computer that connected to arduino**? (I want to create some sort of stream deck, but it will be used for running Google Chrome and other .exe file on a windows computer)

Can someone explain how to run it using arduino uno by taking input from the user?

# Answer
> 1 votes
As mentioned in comments, one way to do this would be to bind a windows shortcut key to do the action you desire and then have the arduino send that as a keystroke. This would only be possible on devices (like the leonardo) that have native usb device support rather than a serial to usb converter chip.

An alternate (and more secure and reliable) approach would be to create a windows service that looks for the arduino and monitors it and runs actions when the arduino generates specific events.

The easiest way to get events would be to read incoming serial data from the arduino and parse it; this would work on all arduinos. A more complex approach (only available on arduinos with native usb device support) would be to create a special USB device profile that generated the events, and a corresponding windows service or driver to recognize and use that custom device.

I've done things like this with my own projects, although in linux, not in windows.

---
Tags: arduino-uno
---


# Question
Title: ESP32 failing to read from DHT11, MH-Z19C sensors
I got MH-Z19C (CO2 ppm) (datasheet), and DHT11 (temperature) sensors from Ebay and followed instructions online to set it up with my ESP32 board (ESP32).

I'm using a breadboard and 5V/3.3V power supply to power the sensors, while the ESP32 is linked to my PC with USB.

I'm struggling to understand the reason why I can't get a reading from my sensors. I tried countless guides online and double-checked everything multiple times.

I also tried connecting DHT11 to my board's 3.3V directly but it didn't change anything.

**How do you "debug" hardware? Is there no way to know what you're doing wrong?** **You have to get it exactly right or nothing works?**

Serial monitor logs:

```
0 ppm
Failed to read from DHT sensor

```

MH-Z19C connections:

* VIN/GND \<-\> Power Supply 5V +/- respectively
* TX \<-\> ESP32 RX2
* RX \<-\> ESP32 TX2

DHT11 connections:

* Pin 1 \<-\> Power supply 3.3V
* Pin 2 \<-\> 10k Ohm pull-up \<-\> ESP32 D2
* Pin 4 \<-\> GND

Reference:

Libraries installed:

```
// Example testing sketch for various DHT humidity/temperature sensors
// Written by ladyada, public domain

// REQUIRES the following Arduino libraries:
// - DHT Sensor Library: https://github.com/adafruit/DHT-sensor-library
// - Adafruit Unified Sensor Lib: https://github.com/adafruit/Adafruit_Sensor

#include "DHT.h"
#include <SoftwareSerial.h>
#include <MHZ19.h>
#include <Wire.h>

// pin for uart reading
#define RX_PIN 16  // Rx pin which the MHZ19 Tx pin is attached to.
#define TX_PIN 17 // Tx pin which the MHZ19 Rx pin is attached to.

#define DHTPIN 2     // Digital pin connected to the DHT sensor
// Feather HUZZAH ESP8266 note: use pins 3, 4, 5, 12, 13 or 14 --
// Pin 15 can work but DHT must be disconnected during program upload.

#define DHTTYPE DHT11   // DHT 11

// Initialize DHT sensor.
// Note that older versions of this library took an optional third parameter to
// tweak the timings for faster processors.  This parameter is no longer needed
// as the current DHT reading algorithm adjusts itself to work on faster procs.
DHT dht(DHTPIN, DHTTYPE);
MHZ19 myMHZ19;
SoftwareSerial mySerial(RX_PIN, TX_PIN);

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

  // Start Co2 sensor
  mySerial.begin(9600);                               // (Uno example) device to MH-Z19 serial start
  myMHZ19.begin(mySerial);                                // *Serial(Stream) refence must be passed to library begin().
  myMHZ19.autoCalibration();                              // Turn auto calibration ON (OFF autoCalibration(false))
}

void read_dht() {

  /////// DHT SENSOR \\\\\\
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  float f = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  // Compute heat index in Fahrenheit (the default)
  float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  float hic = dht.computeHeatIndex(t, h, false);

  Serial.print(F("Humidity: "));
  Serial.print(h);
  Serial.print(F("%  Temperature: "));
  Serial.print(t);
  Serial.print(F("C "));
  Serial.print(f);
  Serial.print(F("F  Heat index: "));
  Serial.print(hic);
  Serial.print(F("C "));
  Serial.print(hif);
  Serial.println(F("F"));

}

void loop() {
  // Wait a few seconds between measurements.
  delay(5000);

  int CO2;
  // Request CO2 (as ppm)
  CO2 = myMHZ19.getCO2();
  Serial.println(String(CO2) + " ppm");

  read_dht();
}

```

# Answer
> 1 votes
You did a good job of giving links. You could have improved your question by showing, not just telling us, how you connected the sensors.

***How do you "debug" hardware? Is there no way to know what you're doing wrong? You have to get it exactly right or nothing works?***

No, that is too hard. I like to **divide and conquer** and **test sequentially**.

As already mentioned, test one sensor at a time.

To illustrate, I broke out an old ESP32 and a DHT22 and went about hooking them up as per your example.

Here are the connections:

Then I dowload the library that you had mentioned and I load their simplest example, DHTtester. If I am relying heavily on Arduino Libraries, I am relying on someone else's code, so I need to look through it so I am sure I am using it correctly.

Looking through the code, I make sure it specifies:

```
#define DHTPIN 2     // Digital pin connected to the DHT sensor.
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321

```

and I double check that I have it connected correctly . As you can see, I have the pull-up resistor on the dataline....+3.3v to one side of the resistor and the other side goes to the DHT data pin and to the ESP GPIO2 pin (see the pics?).

I double check and then run the code and the serial monitor reveals...

```
Humidity: 32.40%  Temperature: 23.40°C 74.12°F  Heat index: 22.64°C 72.75°F
Humidity: 32.70%  Temperature: 23.30°C 73.94°F  Heat index: 22.54°C 72.57°F
Humidity: 33.30%  Temperature: 23.30°C 73.94°F  Heat index: 22.55°C 72.60°F
Humidity: 34.10%  Temperature: 23.30°C 73.94°F  Heat index: 22.58°C 72.64°F
Humidity: 34.30%  Temperature: 23.30°C 73.94°F  Heat index: 22.58°C 72.65°F

```

...and if I breathe on the sensor, the RH jumps up....looks good.

If it had not have worked AND I was sure I had connected things correctly, I would have started going backwards....Can I get any program to work on the ESP, like a simple blink, there are lots of configuration options and it is easy to mess it up.

If I can get something to run, then I have to start to suspect the DHT - do I have another to test?...and so on and so forth.

Then I would repeat the same process with the CO2 sensor.

Then I would try to use them both at the same time.

Hope it helps.

---
Tags: arduino-ide, sensors, power, esp32
---