text:
Microcontroller freezes when triggering the gate of an N-channel MOSFET
Disclaimer: I have asked questions about this project before but this is yet another issue I'm facing.
What I really want to do: Build a battery powered device with 6 colored buttons. When you press one of the buttons the gadget should play a sound saying the name of the color.
It should not need an ON/OFF toggle to save battery capacity but rather have a very low idle current draw so that the battery will lasts for weeks (or even months) when it's not used.
Something like this

Hardware: ATtiny85 (low draw in general, very low draw in sleep), DfPlayer, 3.7v Battery (probably 18650)
The 6 buttons are attached to a single input pin. The microcontroller can distinguish them by reading the ADC value. The buttons have different resistors attached to them
How I wanted to do it: My initial plan was to press a button that wakes the microcontroller up. The mcu then wakes the dfplayer, plays a sound and goes back to sleep. If that would not be responsive enough add a delay to the sleep like: if no button was pressed within the last 30s go to sleep. That worked after some initial problems but it turned out that the DfPlayer "sleep mode" doesn't mean it goes to sleep as in it draws less current but much rather that it's just idling, not playing any sound.
How I want to do it now: Pretty much the same as above but instead of sending the DfPlayer to sleep just turn it on and off:
Press a button that wakes the microcontroller up. The mcu then turns the DfPlayer on by setting the gate of an n-channel mosfet (IRF3708) HIGH, waits a short period of time, plays a sound, turns the dfplayer off and goes back to sleep. If that's not responsive enough add a sleep delay like explained above.
What I'm already able to do:

make the DfPlayer play a specific sound over serial communication
distinguish between the 6 input buttons
wake the microcontroller up with any of these buttons
turn the DfPlayer on/off by using an n-channel mosfet

The problem that I have: The microcontroller freezes when I set the output pin attached to the mosfet gate to HIGH. Freeze means it just won't execute any code after the digitalWrite(PIN_MOS, HIGH); call. I tested it by turning an LED on a different pin on and off like so
digitalWrite(PIN_LED, HIGH);
digitalWrite(PIN_MOS, HIGH);
digitalWrite(PIN_LED, LOW);

The LED turns on but won't ever turn off. When I use the external reset of the attiny the mosfet will turn off and code will execute again just fine. Until I try to set the mosfet pin to HIGH again.
The DfPlayer will turn on though, I can play sounds on it by shorting 2 pins on it. It doesn't seem to be unstable either. It's just that the attiny hangs up.
I use a cheap lab psu but it should be good enough to be not the problem. I've also tried a fully charged 18650 battery and a CR2032 battery. The 18650 worked the same as the psu and the CR2032 just couldn't handle the draw and the DfPlayer wouldn't properly turn on.
I tried it different voltages between 3.3v and 5v. In theory everything should work and in reality it didn't change anything either.
Here is the breadboard layout I use.
I also added an electrolytic and ceramic cap between Vcc/GND on the DfPlayer but that didn't help either

Here is the code I use
    #include <Arduino.h>
    #include <avr/sleep.h>
    #include <DFMiniMp3.h>
    #include <avr/interrupt.h>
    #include <avr/power.h>
    #include "LemonSerial.h"
    #include "mp3notify.h"

    #define PIN_TX PB0
    #define PIN_RX PB1
    #define PIN_MOS PB2
    #define PIN_LED PB3
    #define PIN_A PB4

    LemonSerial secondarySerial(PIN_RX, PIN_TX);
    DfMp3 dfmp3(secondarySerial);

    void sleep();

    void initADC()
    {
      ADMUX =
          (1 << ADLAR) | // left shift result
          (0 << REFS1) | // Sets ref. voltage to VCC, bit 1
          (0 << REFS0) | // Sets ref. voltage to VCC, bit 0
          (0 << MUX3) |  // use ADC2 for input (PB4), MUX bit 3
          (0 << MUX2) |  // use ADC2 for input (PB4), MUX bit 2
          (1 << MUX1) |  // use ADC2 for input (PB4), MUX bit 1
          (0 << MUX0);   // use ADC2 for input (PB4), MUX bit 0

      ADCSRA =
          (1 << ADEN) |  // Enable ADC
          (1 << ADPS2) | // set prescaler to 128, bit 2
          (1 << ADPS1) | // set prescaler to 128, bit 1
          (1 << ADPS0);  // set prescaler to 128, bit 0
    }

    void setup()
    {
      initADC();

      pinMode(PB5, INPUT_PULLUP);
      pinMode(PIN_A, INPUT);
      pinMode(PIN_LED, OUTPUT);
      digitalWrite(PIN_LED, LOW);
      pinMode(PIN_MOS, OUTPUT);
      digitalWrite(PIN_MOS, LOW);
    }

    void play(uint16_t track)
    {
      if (digitalRead(PIN_MOS) == LOW)
      {
        digitalWrite(PIN_LED, HIGH);
        delay(500);
        digitalWrite(PIN_MOS, HIGH);
        digitalWrite(PIN_LED, LOW);

        delay(500); // wait for DfPlayer to turn on

        dfmp3.begin();
        dfmp3.reset();
        dfmp3.disableDac();
        dfmp3.setVolume(30);
        dfmp3.setPlaybackSource(DfMp3_PlaySource_Sd);
      }

      dfmp3.playGlobalTrack(track);
    }

    void loop()
    {
      ADCSRA |= (1 << ADSC); // start ADC measurement
      while (ADCSRA & (1 << ADSC))
      {
          // wait till conversion complete
      }

      uint8_t adcValue = ADCH;
      // actually calculate the parameter based off adcValue here. omitted for readability
      play(1);
    }

    // Interrupt Serviceroutine (Pin-Change-Interrupt)
    ISR(PCINT0_vect)
    {
      LemonSerial::handle_interrupt();
    }

    // ADC interrupt service routine
    ISR(ADC_vect)
    {
      ; // noop
    }

Got a link to the datasheet of the MOSFET you are using?

@VE7JRO it’s an IRF3708. I’ve attached a link to my post

You should also have a decoupling capacitor (ceramic say 100nF) directly across the power rails of the ATtiny85 and as physically close as possible to the chip. It is possible that the inrush current to the smoothing capacitor on the SD card player when the mosfet switches on is causing the problem. You may try a 100nf capacitor directly between the mosfet gate and ground and a 10k to 100k resistor between the arduino pin and the gate to slow this switch on. Also search for "attiny85 brown out fuse" . This may be dependent on options provided by the arduino core you are using.

while (ADCSRA & (1 << ADSC)) {   sleepIfIdle(started) ; }.  I think it is going to hang in this loop continuously sleeping because the variable started is not refreshed. Try making started global and update it also at the end of your sleep code. If this is the problem then create an answer yourself showing the coding changes.

Please reduce your sketch to the absolute minimum that stills shows the behavior. Then [edit] your question and add that code, please.

"I update started at the beginning of the loop. shouldn't that work?" No. The started at the beginning of the loop will not be executed when it gets stuck in that inner loop. After waking from sleep, the flow of control returns back up the call chain sleep() -> sleepIfIdle() into that inner loop without touching started. However, it sounds like it is not the problem. Which Arduino core are you using? Please add that to the problem description.

You've made a whole lot of changes to the code, see edits. Does it still exhibit the same behaviour? The comments above now seem to refer to code that has been removed.

You've said you are using the Attiny85 for lower power drain. The Atmega328P has a lot more ports and still only draws 100 nA in sleep mode "power down" and can still be woken from a switch closure. That would mean a lot less resistors you have to fit into that enclosure.

@NickGammon fair point I guess but the 85 is a lot smaller than the 328p. Length is worse than quantity. My ultimate goal is to make a pcb with smd components out of it anyway. The dfplayer might be an issue though since it's rather big

@6v6gt you were right. the resistor between PB4 and Gate + the ceramic capacitor between GND and Gate made it work eventually.
Your comments about the sleep function were right and I was able to fix that too.

That's great. I leave you to present your revised code and component layout as an answer to close this. It may helps some one else and you should also get a few Brownie points.

@Rohit Gupta - You can do syntax colouring with <!-- language: lang-c++ --> as a comment (not indented) just before the code. That saves you changing the indentation and having to add the backticks before and after it. Now it is over-indented.

@boop The difference in size is only a couple of mm for the SMD devices, but whatever works for you. Glad you got it working!

@6v6gt was the one who figured out what was missing.
I had to increase the 1Ω resistor between the output pin and gate to 1kΩ and add a 100nF ceramic capacitor between GND and gate. Eventually it worked just as expected.
This is the full code I ended up using. I tried to add enough comments to make it clear what happens.
#include <Arduino.h>
#include <avr/sleep.h>
#include <DFMiniMp3.h>
#include <avr/interrupt.h>
#include <avr/power.h>
// this is just "SoftwareSerial" without blocking interrupts
// thus you have to call handle_interrupt() from here
#include "LemonSerial.h"
#include "mp3notify.h"

#define PIN_TX PB0
#define PIN_RX PB1
#define PIN_MOS PB2
#define PIN_LED PB3
#define PIN_A PB4
// turning the player on and initializing it takes quite a while
// thus do not go back to sleep immediately after each button press
uint32_t timeoutMs = 30000;
uint64_t started = 0;

// dfplayer api
LemonSerial secondarySerial(PIN_RX, PIN_TX);
DfMp3 dfmp3(secondarySerial);

void sleep();

uint8_t readADC()
{
  ADCSRA |= (1 << ADSC); // start ADC measurement
  while (ADCSRA & (1 << ADSC))
    ; // wait till conversion complete

  uint8_t adcValue = ADCH;
}

void initADC()
{
  ADMUX =
      (1 << ADLAR) | // left shift result
      (0 << REFS1) | // Sets ref. voltage to VCC, bit 1
      (0 << REFS0) | // Sets ref. voltage to VCC, bit 0
      (0 << MUX3) |  // use ADC2 for input (PB4), MUX bit 3
      (0 << MUX2) |  // use ADC2 for input (PB4), MUX bit 2
      (1 << MUX1) |  // use ADC2 for input (PB4), MUX bit 1
      (0 << MUX0);   // use ADC2 for input (PB4), MUX bit 0

  ADCSRA =
      (1 << ADEN) |  // Enable ADC
      (1 << ADPS2) | // set prescaler to 128, bit 2
      (1 << ADPS1) | // set prescaler to 128, bit 1
      (1 << ADPS0);  // set prescaler to 128, bit 0
}

void setup()
{
  initADC();

  // set INPUT_PULLUP to reduce current draw
  pinMode(PB5, INPUT_PULLUP); // PB5 is not assigned to any constant
  pinMode(PIN_LED, INPUT_PULLUP);

  pinMode(PIN_A, INPUT); // ADC pin is physically pulled low
  pinMode(PIN_MOS, OUTPUT);
  digitalWrite(PIN_MOS, LOW);

  started = millis();
}

/// @brief plays a track on the dfplayer. turns the player on if neccessary
/// @param track track number to play
void playTrack(uint16_t track)
{
  started = millis();

  if (digitalRead(PIN_MOS) == LOW)
  {
    digitalWrite(PIN_MOS, HIGH);
    delay(50); // wait 50ms for DfPlayer to turn on

    // baud 4800 because the attiny runs at 16mhz (8mhz -> 9600)
    dfmp3.begin(4800);
    dfmp3.setVolume(30);
  }

  dfmp3.playGlobalTrack(track);
}

void loop()
{
  uint8_t adcValue = readADC();

  if (adcValue >= 227 && adcValue <= 237)
  {
    // 10k ohm (3.0V -> adc 232)
    playTrack(1);
  }
  else if (adcValue >= 212 && adcValue <= 223)
  {
    // 18k ohm (2.8V -> adc 217)
    playTrack(2);
  }
  else if (adcValue >= 196 && adcValue <= 206)
  {
    // 27k ohm (2.6V -> adc 201)
    playTrack(3);
  }
  else if (adcValue >= 181 && adcValue <= 191)
  {
    // 38k ohm (2.4V -> adc 186)
    playTrack(4);
  }
  else if (adcValue >= 165 && adcValue <= 175)
  {
    // 50k ohm (2.2V -> adc 170)
    playTrack(5);
  }
  else if (adcValue >= 150 && adcValue <= 160)
  {
    // 65k ohm (2.0V -> adc 155)
    playTrack(6);
  }
  // ending up here every loop where no button was pressed. so basically 99.99% of the time
  else
  {
    // started gets set to millis() everytime a track is played
    if (millis() - started > timeoutMs)
    {
      // sleep if some time has passed without input (see timeoutMs)
      sleep();
    }
  }
}

// sets the device into POWER DOWN mode.you can probably tune it to be more efficient
void sleep()
{
  digitalWrite(PIN_MOS, LOW);

  // pin change interrupt
  PCMSK |= bit(PIN_A);
  GIFR |= bit(PCIF);  // clear any outstanding interrupts
  GIMSK |= bit(PCIE); // enable pin change interrupts

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  power_all_disable(); // power off ADC, Timer 0 and 1, serial interface
  sleep_enable();
  sleep_cpu();
  sleep_disable();
  power_all_enable(); // power everything back on
}

// Interrupt Serviceroutine (Pin-Change-Interrupt)
ISR(PCINT0_vect)
{
  // the SoftwareSerial does not block any interrupt pins anymore and thats why we have to call it from here
  LemonSerial::handle_interrupt();
}

// ADC interrupt service routine
ISR(ADC_vect)
{
  ; // noop
}

This is a schematic from how everything is set up now. This is the first time I drew a real schematic so I hope it's clear whats going on

The RC network consisting of a 100nF capacitor and a 1k ohm in the gate circuit of the mosfet has a time constant of 100ns. It seems that this is enough to "soften" the switch on of the mini DF player. However, I believe that the extra capacitors you've added (100uF and 100nF) currently between the Vcc and (switched) GND of the player should actually be between Vcc of the player and the main GND otherwise these  also have an inrush current when the mosfet is switched on. Why, incidentally, do you consider especially the 100uF capacitor to be necessary ?

@6v6gt good point. It was just something I found while googling around. Maybe I misunderstood it though. It works without these caps but my understanding was that it helps stabilizing the player. Stabilizing as in: less unwanted noise/crackling

I don't necessarily disagree with the capacitor, more how you have wired it. Have you measured the current when the device is sleeping ? It is more usual to switch modules, in this case the DFplayer, on the high side, that is at their Vcc rather than their Gnd and using an P channel mosfet. The risk of some sort of parasitic powering is higher if the ground side is switched because it is more likely to find an alternative path to ground resulting in some residual current consumption by the module. If the current consumption is small of course you can choose to ignore it.


text:
Arduino (Mega 2560) Ethernet Shield 2 (W5500) - Can't connect
I'm having issues connecting to my arduino mega via ethernet. Its a very basic start to the code just to get the network side up and running, them im going to add in what I actually want it to do. For some reason, even after changing the cables and ethernet ports used, I still get linkStatus() returning LinkOFF? The server starts, and listens for clients, but I can't connect to it from my PC. I'm on the same subnet.
    #include <SPI.h>
    #include <Ethernet.h>

    IPAddress ip(10,126,132,32);
    int baud = 9600;
    byte mac[] = {
                   0xA8, 0x61, 0x0A, 0xAE, 0x76, 0x17
                 };

    byte subnet[] = {255, 255, 254, 0};
    byte gateway[] = {10, 126, 132, 1};

    EthernetServer server(80);

    void setup(){
      Serial.begin(baud);
      Serial.print("\n-------------------------");
      Serial.print("\nSerial initialised: ");
      Serial.print(baud);
      Ethernet.begin(mac, ip, gateway, gateway, subnet);
      server.begin();
      Serial.print("\nServer initialised... ");
      Serial.print("\nLocal IP: \t");
      Serial.print(Ethernet.localIP());
      Serial.print("\nDNS Server IP: \t");
      Serial.print(Ethernet.dnsServerIP());
      Serial.print("\nGateway IP: \t");
      Serial.print(Ethernet.gatewayIP());
      Serial.print("\nSubnet Mask: \t");
      Serial.print(Ethernet.subnetMask());
      Serial.print("\nHardware status: ");
      if (Ethernet.hardwareStatus() == EthernetNoHardware){Serial.print("No Hardware Detected");}
      else if (Ethernet.hardwareStatus() == EthernetW5500){Serial.print("W5500 Board Detected");}
      else if (Ethernet.hardwareStatus() == EthernetW5200){Serial.print("W5200 Board Detected");}
      else if (Ethernet.hardwareStatus() == EthernetW5100){Serial.print("W5100 Board Detected");}
      Serial.print("\nLink status: \t");
      if (Ethernet.linkStatus() == LinkON){Serial.print("ON");}
      else if (Ethernet.linkStatus() == LinkOFF){Serial.print("OFF");}
      else if (Ethernet.linkStatus() == Unknown){Serial.print("Unknown");}
      Serial.print("\n-------------------------");
      if(server) { Serial.print("\nServer Available\nWaiting for client..."); }
      else {Serial.print("\nServer not available");}
    }

    void loop()
    {
      Ethernet.maintain();
      EthernetClient client = server.available();
      if (client)
        {
          Serial.println("Client found...");
          Serial.println(client.read());
      }
    }

When trying to connect via my browser, I get Error: Connection Refused.
Any help is appreciated!

the WebClient example works? does it work with DHCP assigned IP address? try to wait half a second and then again test the link status.

source: Stack Exchange

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

sort: votes


text:
PCA9685 servo shield not working
Im working on a project where I want to connect 32 servos together.
 I got:
-Arduino uno
-2 PCA9685 16-Channel 12-bit PWM/Servo Shield
-power supply 5v 10 A
-All wiring is to the right pins (I have checked that several times)
So I got the 2 PCA9685 16-Channel 12-bit PWM/Servo Shield from Adafruit I connected all the wires as its supposed to be and I connected the shield to an external power supply which is 5V 10A that should be sufficient for it to work but unfortunately servos are not moving at all although the serial monitor is giving numbers I don't know where is the problem coming from.
ps. Im using the Adafruit library
its not even moving one servo (although the servo moves when connected directly to the Arduino.
thank you in advance.
the code I'm using its one of the examples from the library:
/***************************************************
  This is an example for our Adafruit 16-channel PWM & Servo driver
  Servo test - this will drive 8 servos, one after the other on the
  first 8 pins of the PCA9685

  Pick one up today in the adafruit shop!
  ------> http://www.adafruit.com/products/815

  These drivers use I2C to communicate, 2 pins are required to
  interface.

  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!

  Written by Limor Fried/Ladyada for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ****************************************************/

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

// called this way, it uses the default address 0x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
// you can also call it with a different address you want
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);
// you can also call it with a different address and I2C interface
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(&Wire, 0x40);

// Depending on your servo make, the pulse width min and max may vary, you
// want these to be as small/large as possible without hitting the hard stop
// for max range. You'll have to tweak them as necessary to match the servos you
// have!
#define SERVOMIN  150 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX  600 // this is the 'maximum' pulse length count (out of 4096)

// our servo # counter
uint8_t servonum = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("8 channel Servo test!");

  pwm.begin();

  pwm.setPWMFreq(60);  // Analog servos run at ~60 Hz updates

  delay(10);
}

// you can use this function if you'd like to set the pulse length in seconds
// e.g. setServoPulse(0, 0.001) is a ~1 millisecond pulse width. its not precise!
void setServoPulse(uint8_t n, double pulse) {
  double pulselength;

  pulselength = 1000000;   // 1,000,000 us per second
  pulselength /= 60;   // 60 Hz
  Serial.print(pulselength); Serial.println(" us per period");
  pulselength /= 4096;  // 12 bits of resolution
  Serial.print(pulselength); Serial.println(" us per bit");
  pulse *= 1000000;  // convert to us
  pulse /= pulselength;
  Serial.println(pulse);
  pwm.setPWM(n, 0, pulse);
}

void loop() {
  // Drive each servo one at a time
  Serial.println(servonum);
  for (uint16_t pulselen = SERVOMIN; pulselen < SERVOMAX; pulselen++) {
    pwm.setPWM(servonum, 0, pulselen);
  }

  delay(500);
  for (uint16_t pulselen = SERVOMAX; pulselen > SERVOMIN; pulselen--) {
    pwm.setPWM(servonum, 0, pulselen);
  }

  delay(500);

  servonum ++;
  if (servonum > 7) servonum = 0;
}

You'll have to show us your wiring and your code if we are to help you.

I would suggest running the I2CScanner sketch to see if it can find the chip.

I tried now and it gives
Scanning...
No I2C devices found

Ah, I see the problem now...

OMG this actually worked but im afraid because it worked before and stoped for the same reason anyway thank you so much

You have your SDA and SCL pins connected backwards.

SDA is A4
SCL is A5

You have it the other way around.

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


text:
Print text at any Y-value on SSD1306?
I'm attempting to print several rows of text, at certain Y-values, on an SSD1306 128x64 LCD display.
I'm using the ssd1306 library by Alexey Dynda. I initially wanted to use the more common LCD libraries out there, such as the Adafruit SSD1306 LCD library, however it unfortunately does not appear I can set custom I2C pins for most such libraries out there, which is required as I'm using a custom board with an ESP32-WROOM-DA chip. The ssd1306 by Dynda appears to be able to do so.
I have the following example code, which prints 6 lines of text:
#include "ssd1306.h"
#include "nano_gfx.h"

const int PIN_I2C_SCL = 16;
const int PIN_I2C_SDA = 13;

void LCDTextDraw(int x, int y, const char* text)
{
  EFontStyle fontStyle;

  ssd1306_printFixed(x, y, text, fontStyle);
}

void LCDRectDraw(int x, int y, int w, int h)
{
  ssd1306_fillRect(x, y, x + w, y + h);
}

void LCDScreenClear(bool fill)
{
  ssd1306_clearScreen();

  if (fill)
    LCDRectDraw(0, 0, 128, 64);
}

void LCDInit()
{
  ssd1306_setFixedFont(ssd1306xled_font6x8);
  ssd1306_128x64_i2c_initEx(PIN_I2C_SCL, PIN_I2C_SDA, 0);
}

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

  pinMode(PIN_I2C_SCL, OUTPUT);
  pinMode(PIN_I2C_SDA, OUTPUT);

  LCDInit();
  LCDScreenClear(true);

  LCDTextDraw(30, 0, "TEST 1");
  LCDTextDraw(30, 10, "TEST 2");
  LCDTextDraw(30, 20, "TEST 3");
  LCDTextDraw(30, 30, "TEST 4");
  LCDTextDraw(30, 40, "TEST 5");
  LCDTextDraw(30, 50, "TEST 6");
}

void loop()
{}

With which I wish to print out 6 lines of text, each line evenly vertically spaced out by 10 pixels.
Which produces the following output on my LCD:

As you can see, the text rows are not evenly vertically spaced out as I wish them to be, with a large space between the TEST 4 and TEST 5 strings.
After looking at the definition of the ssd1306_printFixed function I'm using to print out my text in the example above, it turns out that it can only print rows of text at certain fixed Y-positions:

@warning ssd1306_printFixed() can output chars at fixed y positions: 0, 8, 16, 24, 32, etc.
If you specify [10,18], ssd1306_printFixed() will output text starting at [10,16] position.

Hence, I also tried using the ssd1306_print function (which uses a cursor to delineate its printing location on the screen), which doesn't have that warning in its header declaration. I replaced my LCDTextDraw function with:
void LCDTextDraw(int x, int y, const char* text)
{
  ssd1306_setCursor8(x, y);
  ssd1306_print(text);
}

However, that still produced the exact same output on my LCD, with the same spacing issues.
What is the proper way to print text rows at any Y-value on an LCD?
Thanks for reading my post, any guidance is appreciated.

https://wokwi.com/projects/341940000159433299

@jsotola, a quick look at your linked to Adafruit code and I think I see the same vertical numbers restrictions that Rohit was commenting on.

@Runsva, this is just a guess, but after writing code to interface w/a small Sharp display, there may be some difficulties addressing anomalies which can be avoided by placing images (characters) in constrained locations. Also, these characters may be part of the display programming and their placement is constrained by the display. I think you can do what you want. But you may have to write all the code from scratch.

Turns out using the Adafruit SSD1306 library is much easier than I first thought. One just must specify the I2C pins used with Wire, and pass it as reference to the Adafruit_SSD1306 constructor. Additionally, the Adafruit library doesn't appear to have the uneven vertical spacing issue.
The equivalent code below using the Adafruit library:
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

const int PIN_I2C_SCL = 16;
const int PIN_I2C_SDA = 13;

Adafruit_SSD1306 LCD(128, 64, &Wire);

void LCDTextDraw(int x, int y, const char* text, byte size)
{
  LCD.setCursor(x, y);
  LCD.setTextSize(size);
  LCD.print(text);
  LCD.display();
}

void LCDRectFill(int x, int y, int w, int h, int color)
{
  LCD.fillRect(x, y, w, h, color);
}

void LCDScreenClear(bool fill)
{
  LCD.clearDisplay();
  LCD.display();
  LCD.setTextColor(WHITE, BLACK);

  if (fill)
    LCDRectFill(0, 0, 128, 64, 1);
}

void LCDInit()
{
  LCD.begin(SSD1306_SWITCHCAPVCC, 0x3C);
}

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

  pinMode(PIN_I2C_SCL, OUTPUT);
  pinMode(PIN_I2C_SDA, OUTPUT);

  Wire.setPins(PIN_I2C_SDA, PIN_I2C_SCL);
  Wire.begin();

  LCDInit();
  LCDScreenClear(true);

  LCDTextDraw(30, 0, "TEST 1", 1);
  LCDTextDraw(30, 10, "TEST 2", 1);
  LCDTextDraw(30, 20, "TEST 3", 1);
  LCDTextDraw(30, 30, "TEST 4", 1);
  LCDTextDraw(30, 40, "TEST 5", 1);
  LCDTextDraw(30, 50, "TEST 6", 1);
}

void loop()
{}

Now produces the desired result:


text:
Laser tripwire and LDR
I am planning to make a laser tripwire but I have an issue. Let me explain what I am trying to do:
Making a laser tripwire is actually pretty easy at its core. You just need an LDR and a laser diode. You look at the normal results of the LDR; it's usually around 60.
When the laser hits the LDR, it's usually around 600 so you write an if statement saying if the LDR value is below 500, power the LED or buzzer.
But there is an issue here. The LDR module must be connected to Arduino with cables for signaling. I don't want that. Luckily, I have a Bluetooth module but I have no idea how to use it for sending signal to my Android phone. I know how to send signals though. So to simplify things:

Can I send any kind of signal to my phone with Bluetooth (I am using an app called Arduino Bluecontroll but I can upload a different app if necessary)? If yes, how?

First, LDR module must be connected to Arduino with cables for signaling. I don't want that. -- So use a retro-reflector. That's what most people use. It also makes aiming a whole lot easier...

@Majenko That's actually... pretty clever. I don't want to buy more equipment though. Can I use a tiny mirror instead?

No, it has to be a retroreflector. They're special - they always reflect back near 180° - a normal mirror reflects at the inverse of the incident angle - so you'd not only have to aim perfectly at the right spot on the mirror, but the mirror would also have to be at precisely the right angle. Theoretically doable, but a nightmare in practice.

you actually may already have a retroreflector in your house ... it is what is used on bicycles ... usually a red one on back and a clear one on front

@jsotola brilliant advice but sadly, I don't have one.

LDR module must be connected to Arduino with cables for signaling.. Yes, but the laser diode does not need to be connected to the Arduino. It only needs power.

A bike reflector might work, instead of a mirror.

3 small mirrors put together at 90 degrees give you a retroreflector, if you have small mirros, but no retroreflector.

What bluetooth module do you have? There are different modules for different applications, which need to be handled differently

@chrisl I have HC-06.

Can I send any kind of signal to my phone with Bluetooth?

You have an HC-06, which is a bluetooth Serial (UART) bridge. Thus the bluetooth device exposes the profile for a serial terminal. You can only transmit serial data. It doesn't work for HID input to the smatphone or audio. The Bluecontrol app seems to use serial. So that is not a problem.
To get the communication to work, you need to pair the HC-06 with your phone. The actual connection is then established by the app. It will send serial data to the HC-06, which will output it on its TX pin. Serial communication on its RX pin will be transmitted back to the app.
You need to test, for which baudrate the HC-06 is configured. For that write a test sketch, you use an extra serial interface (either another hardware interface or SoftwareSerial) for the HC-06 and send every byte, that you receive from it, to your PC, so that you can see, what the Arduino receives. Try different standard baudrates (like those, which are listed in the serial monitor), until you find the one, which gives you the correct output.
When that works, you can write your sketch to read the commands from the HC-06 serial interface and act accordingly. How exactly that works depends on the data, that the app is sending. Most likely is sends ASCII encoded text, each message terminated by a newline character \n. In that case you could read the data into a buffer byte by byte, when they arrive. When you read a newline character, you know, that you received a full message. Then you can process it and act accordingly.

Thanks chrisl but I already solved it with my own way.

Then please write an own answer and accept it as correct. That way others can learn from you


text:
Way(s) to store an integer from the serial output and sutract it from the next Serial output
This seems so simple but I can't solve it. (I'm new to Programming) I do not want to use EEPROM. Just store it and do the math. I strip the Azmuth and Elevation values from a satellite tracker program and need to calculate the difference the satellite has moved to turn the rotors. Here's my efforts so far as requested ...Thanks
/*  Sketch for WXtrack satellite tracking software
 *  VE3COJ Burlington, Ontario, Canada
 *  Requires COM port and Max 232 from PC
 *  to Serial in on Arduino (Rx)
 *
 *  Download URL:  http://www.satsignal.eu/software/wxtrack.htm
 *
 *  Setup in WXtrack: Go to <Tracker menu> <Options> <Select EGIS COM port> <check box XY mode>
 *  Select a Satellite using Manual in Timeframe box.
 *  Highlight Satellite icon, Use seconds box (third box from left side) to increment satellite.
 *  Use the Sketch Monitor to see Elevation and azimuth reading from Serial port.
 *  Alternatly, one can use an array to simulate Elevation and Azimuth increments in degrees.
 */

      #include <Stepper.h>
      #include <avr/pgmspace.h>
      #define STEP 50
      #define motorSteps 600      // Number of steps to turn the motor
      #define motorPin1 8
      #define motorPin2 9
      #define motorPin3 10
      #define motorPin4 11

      // 2 EasyDriver boards will be used in final project //

          String readString, read_az, read_el;

          int el_current_store_0;           // elevation ... global value ??
          int el_current_store_1;
          int el_position;                  // final value in degrees to move rotor

          int az_current_store_1;           // azimuth ..... global value ??

       void setup() {

          Serial.begin(9600);
          Serial.println("  AZ & EL "); // so I can keep track of elevation and Azimuth
          Serial.println (" =========");
          Serial.print("");
      }

      void loop() {

           while (Serial.available()) {
              delay(3);  //delay to allow buffer to fill
               if (Serial.available() >0) {
              char c = Serial.read();  //gets one byte from serial buffer
           readString += c; //makes the string readString
      }
    }

          if (readString.length() >0) {
          //Serial.println(readString); //see what was received from Serial input

          // pull out the number values required... parse the serial output
          // On WXtrack menu, select "Tracker" > "Options" > "EGIS COM" & "XY mode"
          read_az = readString.substring(3, 7);   //get the first 3 to the 6th integers (azmuth)
          read_el = readString.substring(10, 13); //get the next 10 to thee 13th integers (elevation)

         int el_current_store = read_el.toInt();  // Change String el to Integer
         int az_current_store = read_az.toInt();  // Change String Az to integer

        /* This is an attemp to calculate the difference in degrees the satellite moves. */

         int n1 = el_current_store_0;       // first elevation reading ... store it ... how?
         int n2 = el_current_store_1;       // second elevation reading ...
         int el_position = (n2 - n1);       // Subtract first from second ... equals how many degrees to turn the rotor

                                           // if result is negative, rotor changes direction

          /* Can't be done as is because the reading gets put in all variables

           * I cannot figure out how to store the number of degrees in memory (Not EEPROM)
           *  EEPROM will burn out eventually, FLASH cannot change values it appears... in docs.
           *
           * From here:
           * Store first reading from Serial port into memory.
           * Rotor moves to degrees probably 3 degrees ... read second position (if 4 degrees)
           * Subtract 3 degrees from 4 degrees equals 1 and multiply by variable STEP (200 STEP = 1 degree motor rotation)
           * Get next elevation reading and repeat subtraction...
           */

           // Print to serial monitor to see results of all values //

           Serial.print("  Elevation = ");
           Serial.println(read_el);

           Serial.print("  Azimuth = ");
           Serial.println(read_az);

           //Serial.println(el_position);
           Serial.println (" --------next-------");

           Serial.print("");

           readString="";
          }
         }

          /* 1. ========= Send Antenna to 0 degrees / Check for interrup at 0 degrees & Stop =========
                ========= Wait for Serial input then goto 2. =========

             2. ========= Get Az and El from Serial Port and Start Tracking ==========

             3. ========= Store (first, second, etc. ) El and AZ =========

             4. ========= Get Next El and Az / Subtract from one before El & Az =========

             5. ========= Move Antenna to Next Position =======

             6. ======== Goto 3. =========

             7. ======== If El Equals 0, Goto 1.

                       When El = 90 degrees, (Satellite overhead) Az rotates 180 degrees and

                       El decreases, coming down to the horizon.

                      When Satellite is off to E or W, elevation does not reach 90 degrees!
         */

When you say you want to "store" the values, but not use EEPROM, what is the time frame you are meaning? Do you want to store it so it is not lost when the microcontroller resets (power cycles)? Or do you just mean to store it within the program for use in subsequent statements?

You have the following global variables declared:
int el_current_store_0;           // elevation ... global value ??
int el_current_store_1;
int el_position;                  // final value in degrees to move rotor

int az_current_store_1;           // azimuth ..... global value ??

But you never put anything into these variables.
Here is your relevant code that attempts to work with these values:
// pull out the number values required... parse the serial output
// On WXtrack menu, select "Tracker" > "Options" > "EGIS COM" & "XY mode"
read_az = readString.substring(3, 7);   //get the first 3 to the 6th integers (azmuth)
read_el = readString.substring(10, 13); //get the next 10 to thee 13th integers (elevation)

int el_current_store = read_el.toInt();  // Change String el to Integer
int az_current_store = read_az.toInt();  // Change String Az to integer

Above, you are declaring new variables el_current_store and az_current_store and giving them integer values converted from your input string. When you prefix a variable name with int (or any other type) you are declaring a new variable within that scope. In this case, the scope is the if (readString.length() >0) {} block. Once that block ends, those variables don't exist anymore, and every time that block runs, new variables are created there, and destroyed at the end of the block.
/* This is an attemp to calculate the difference in degrees the satellite moves. */

int n1 = el_current_store_0;       // first elevation reading ... store it ... how?
int n2 = el_current_store_1;       // second elevation reading ...
int el_position = (n2 - n1);       // Subtract first from second ... equals how many degrees to turn the rotor

Above, you declare new variables n1, n2, and el_position. However, you give n1 and n2 whatever was in el_current_store_0 and el_current_store_1, but you have never put any value into those variables, and so they have nothing.
Once that is solved, you also need to take a look at declaring a new variable by the command:
int el_position = (n2 - n1);       // Subtract first from second ... equals how many degrees to turn the rotor

which, because it's in a nearer scope than the global variable of the same name, is used instead of the global. And when the scope block ends, it is destroyed.
You should instead assign the computed value to el_position without making a new variable:
el_position = (n2 - n1);       // Subtract first from second ... equals how many degrees to turn the rotor

(Note, no int in front...)
**EDIT: To actually keep the values for the next loop(), you do have to store them in global (or static) variables. Something like this appears to be what you were going for:
     int el_current_store = read_el.toInt();  // Change String el to Integer
     int az_current_store = read_az.toInt();  // Change String Az to integer

    /* This is an attemp to calculate the difference in degrees the satellite moves. */

     // Added code below keeps the older value in *_1
     // Puts the newer value in *_0
     el_current_store_1 = el_current_store_0;
     el_current_store_0 = el_current_store;

     az_current_store_1 = az_current_store_0;
     az_current_store_0 = az_current_store;

     int n1 = el_current_store_0;       // first elevation reading ... store it ... how?
     int n2 = el_current_store_1;       // second elevation reading ...
     int el_position = (n2 - n1);       // Subtract first from second ... equals how many degrees to turn the rotor

Hi Jose... Yes there re some variables not used yet...

It's not necessarily a problem to have unused variables. But what you have are uninitialized variables that you are trying to use.

Sorry... The program works... getting the AZ and EL I need. Once I get the two values, I need to stuff them somewhere so they do not get overwritten on the next loop around. When I have the next  Az and El I want to get the previous Az and El and subtract the difference. Then I know the satellite has moved x degrees. This will then turn the stepper motors. I can't figure out how to temporarily hold the Az & El values.

@jeff: You need two pairs of variables; one for the current values and one for the previous values. You have to declare the pair for the previous values "static", which means they get permanent memory assignments and will not be overwritten when your loop() function exits and gets called again. Those declaration would look like: "int az, el;" and "static int prevAz, prevEl". On each loop, once you've calculated the 'az' and 'el' differences and moved the rotors, copy 'az' and 'el' to 'prevAz' and 'prevEl', respectively.

@JRobert. Thank you for your suggestions. I will see what I can do to get this to work using static memory. It will be a new learning curve.

@jose can u c. Thanks for the feedback. I need to clean up some code and have noted your added code. Also, I see where I slipped up not putting info in the variables. I'll go at it again. Thanks

@jeff: A variable declared 'static; is just like one without the declaration; the difference is where it will be stored. Variables you declare within a function are local variables and are only "visible" to code within that function, regardless of the memory class. Without 'static', the variable is 'automatic': it "comes into being" when the function is called and "ceases to exist" when the function returns (which is why you can't use one to save a value between calls). With 'static', it exists for the entire duration of the program run. Besides that, you use them the same way.


text:
Arduino Fried? Power is being delivered to Arduino but COM not found
When i connect my arduino nano to windows 10; the arduino nano is powered on (the "POW" led is on and not blinking; none of the others are on) but it doesn't show up on my computer. It used to but I think I may have shorted it.
Oddly, I get a measurement of 5V coming from digital pins 2,3,4 if connected through USB or 12V if I connect external power source to V_in. These are the pins that were on before what I believe was a short. Can someone tell me what is the component that is damage and whether it is possible to fix. Thanks!

If you observe 12V on an MCU pin, the MCU is certainly dead.

Sometimes this happens when there is a short circuit, but does not necessarily fry the board. Is the nano touching any other conductive material? Finally, I would like to suggest that you try and restarting windows since windows at times just fails to pick up the Arduino.

If you were powering from 12V and shorted the 5V to GND then yes, it is all dead. The regulator will have stopped regulating. 12V will have then been sent to every component on the board. The USB chip, the main MCU, the 5V regulator - all will be toast.
You could repair it by replacing almost every component on the board, but when they're so cheap, why would you bother?


text:
Cannot set Pins to LOW
I am controlling 2 motors from my Arduino Pro Mini and L293D motor driver module. Problem is, I have to set a pin high and after 1 second set it to LOW. But that doesn't happen... The pin just stays HIGH and is never LOW.
Here's my Code -
    int IN2Left = 10;
    int E1 = 12;
    int E2 = 7;
    int IN3RevRight = 6;
    int trigPin1 = A0;
    int echoPin1 = A1;
    int distance1 = 0;
    int IN4Right = 5;
    int IN1RevLeft = 11;

    void setup()
    {
      pinMode(IN2Left, OUTPUT);
      pinMode(E1, OUTPUT);
      pinMode(E2, OUTPUT);
      pinMode(IN3RevRight, OUTPUT);
      pinMode(IN4Right, OUTPUT);
      pinMode(IN1RevLeft, OUTPUT);
      pinMode(trigPin1, OUTPUT);
      pinMode(echoPin1, INPUT);
      pinMode(13, OUTPUT);
      Serial.begin(9600);
    }

    void loop() {
  digitalWrite(13, HIGH);
  digitalWrite(E1, HIGH);
  digitalWrite(E2, HIGH);
  digitalWrite(IN2Left, HIGH);
  digitalWrite(IN4Right, HIGH);
  delay(3000);
  digitalWrite(IN4Right, LOW);
  digitalWrite(IN3RevRight,HIGH);
  delay(500);
  digitalWrite(IN3RevRight, LOW);
  digitalWrite(IN4Right, HIGH);
  delay(1500);
  digitalWrite(IN2Left, LOW);
  digitalWrite(IN1RevLeft, HIGH);
  delay(500);
  digitalWrite(IN1RevLeft, LOW);
  digitalWrite(IN2Left, HIGH);
  delay(100000);
    }

The IN2Left Pin never goes LOW... I am assuming a faulty Arduino but my Arduino seems to be working just fine as it runs other stuff (tested blink and reading an Ultrasonic sensor) just fine.
My deadline is 2 hours from now...
EDIT: Here's the complete void loop function... Note the two pins on top which go HIGH? They Never go LOW again in the entire code.

If you load a blank sketch, like int main () { } does the pin in question start off high?

Are you sure there isn't something else connected to pin 10?

@NickGammon No... Its very strange..

@Gerben Too damn sure

I tried your amended code and the pin went low every 1 minute 40 seconds for half a second, which is what you told it to do. You have to watch closely to spot it.

Your code sets it high, delays for 1000ms, sets it low, and then... turns around and sets it high almost immediately after. Try delaying in between.

Beaten by 24 seconds. :)

yeah it does... However, if the LOW command is in an if it never executes even when the if block runs.

  digitalWrite(IN2Left, HIGH);
  delay(1000);
  digitalWrite(IN2Left, LOW);

It would go LOW for a few microseconds. Maybe put a delay after going LOW?

yeah it does... However, if the LOW command is in an if it never executes even when the if block runs...

@YaddyVirus Maybe you are trying to pull down something stronger than output driver. How about using LEDs with series resistors to confirm it (with everything else disconnected)?

if the LOW command is in an if - What are you talking about? There is no if in your code.

@NickGammon Actually I tried various ways of setting pins to LOW... One was to set a condition and accordingly set the pins to LOW.

Try: void setup() { pinMode(10, OUTPUT); digitalWrite (10, LOW); } void loop () {} - is pin 10 low then? If so, you can't say that pin 10 "never" goes low.

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


text:
Arduino Pro Mini automatically resetting
I have an Arduino Pro Mini 3.3v in a robot. The problem is, the Mini would automatically randomly overwrite the uploaded sketch with the default blink sketch... And this is becoming quite a problem.
I have connected the Arduino to a L293D Motor Driver and the Arduino gets its power from the motor driver only. It will work just fine, but randomly will reset to the blink sketch...
Please help
P.S- It automatically corrected after a while

I think you are seeing the bootloader, not the blink sketch.

@Gerben whatever it is... My sketch isn't running!

The most obvious cause for a reset is pulling to much current from the Arduino.  I have never heard of an Arduino downloading a new sketch to itself.  Is it possible you are seeing the board booting up and flashing the LED as its doing so?
If you are getting the power from the motor driver its possible you are either giving the board noisy/dirty power or the motor is pulling to much current and depriving the board of power.  I would run them on separate supplies (with a common ground) to avoid this.

I am providing ~18V (2 9v batteries connected in series) to the Motor driver. The motors can easily run on single 9v battery. I am clueless about what to do

Thats overvoltage, not over current. Connect the batteries in parrallel

The board may be resetting itself due to the overvoltage. Running the batteries in parallel should eliminate that as a suspected cause.

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


text:
Arduino UNO suddenly stops responding
I wrote this simple script to control a servo over serial comm -
#include <Servo.h>
Servo steeringServo;
char data = ' ';

void setup() {
  steeringServo.attach(9);
  Serial.begin(115200);

}

void loop() {
  if(Serial.available()){
    data = Serial.read();
  }

  if(data =='L'){
    steeringServo.write(50);
  }
  else if(data == 'R'){
    steeringServo.write(135);
  }
  else if(data == 'S'){
    steeringServo.write(90);
  }

}

It was working fine, I was sending values through a python script. I turned my Arduino off and after a while I come back and reconnect all stuff exactly the way it was, but now my Arduino isn't responding! I tried sending values through the serial monitor to the above sketch but nothing happens! I tried another code which takes values over serial comm and that didn't work as well. The Arduino just receives the values but doesn't do what its supposed to when it receives.
Not only this, I tried uploading the sweep sketch and that didn't work either. Everything is connected exactly the way it was when stuff was fine.
What has gone wrong with my Arduino?
UPDATE
The Arduino works fine if the values are sent through my script.
UPDATE 2
The Arduino works fine if the values are sent through puTTY.

What script? Possibly when you turned it off and on again it went to a different serial port. Check which serial port shows up in the IDE.

Does the script give you some errors? Something like "cannot open COM port" or "COM port busy". Also, try to run your python scripts in administrator mode.

@FrAxl93 no the script doesn't give any errors. Tried running in admin mode, ran flawlessly

@NickGammon Nah, I thought that initially too the Serial Port is the same.


text:
How to get char array's length
I use a LCD display to display a not known size of text ( changes over time ). I wish to display it at the center of LCD ( 2X16 ).
I declare:

  char t[16];
  char h[16];
  sprintf(t, "%.1f%cC %.0f%%", temperature,223, humidity);

Now, since I want to add additional data on a specific line and center it, I need to know it size. When using:
sizeof(t)/(sizeof(t[0])

I get 16 which is the size determined and not its actual size.
How can I get the exact number of chars used?

The function I think you are looking for is strlen - STRing LENgth.
It counts the number of characters in a string up until it finds the "NULL" end of string marker.
Serial.println(strlen(t));

well my guess was it refers to String only

strlen is for C strings (NULL-terminated character arrays).  For String you want String.length().

@Guy.D the code you posted is using char arrays, not String objects. Majenko's answer is what you need, not String.length(). Note that you need to be careful not to overflow your char array. That will cause undefined behavior (read "bugs.")


text:
Problem in defining a variable as multiplication
I have a simplest code to turn on and off a led. The variable holding time definition is onTime, using Arduino Nano.
When it is written as: onTime=1000*30, all is good.
When onTime is greater than this, if loop does not return true value when needed ( see code below ).
BUT when writing it implicit as onTime=60000, and not onTime=1000*60 code run OK.
I'm guessing that value of 30*1000 - has to be something with int value.
CODE:

int enbPin = 10;
bool onState = true;
unsigned long onPeriod = 60*1000; // <----
unsigned long startTime = millis();
void setup() {
  // put your setup code hee, to run once:
  Serial.begin(9600);
  pinMode(enbPin, OUTPUT);
  digitalWrite(enbPin, onState);
  Serial.println("START");
}

void loop() {
  // put your main code here, to run repeatedly:
  if (millis() - startTime >= onPeriod ) {
    onState = !onState;
    startTime = millis();
    digitalWrite(enbPin, onState);
    Serial.println(onState);
  }
}

your code does not have a variable named onTime

unsigned long onPeriod = 60ul * 1000;
ul makes 60 to unsigned long and then the calculation has place for result.
without ul the constants and the result are int and it overflows

thank you for your quick answer. 1) when using NodeMCU, without ul - result was OK, why is that ?  2) to define 1hr should I write 60ul*1000*60 ?

The NodeMCU is a 32-bit chip. int is 32 bits and can hold a massive amount more (same as a long). 2) Sure. Any one (or all of) the numbers can have ul - as long as at least one does.

Thank you very much for comprehensive answer

Juraj already told you how to fix this.
Some more info on why:
(Edited)
By default, the C/C++ compiler uses the smallest size that can hold the specified value for integer constants, starting with the "native" integer size on the platform it's compiling for. For a 16 bit device like an AVR-based Arduino, an int is 16 bits. A signed 16 bit int can hold a value from -32768 to 32767.
(As pointed out by AnT in his comment, if you declare an integer constant of 60,000, the compiler automatically promotes it to the larger long int type.)
It evaluates expressions assuming int constants are of type int unless their value doesn't fit in an int. If you try to do math with an int and a long int, or store the results of int math into a long, the int gets "promoted" to the larger data type first.
In your expression:
unsigned long onPeriod = 60 * 1000;

The compiler first evaluates the right side of the expression, 60 * 1000, as (int)60 * (int)1000). Since it treats both parts of that expression as 16 bit signed ints, it does the multiplication using 16 bit integer math. The result of the multiplication is 60,000, which is too large to store in a signed int, so the intermediate calculation overflows.
It then tries to store the result to an unsigned long. It promotes the now-overflowed value to an unsigned long and stores the (garbled, and thus wrong) result into the unsigned long destination.
By either expressing either or both values as an unsigned long constant, or casting one or both of them to an unsigned long type, the compiler then promotes both values to unsigned longs before doing the math on them, so the result doesn't overflow before being assigned to the destination variable.

"By default, the C/C++ compiler uses the "native" size for integer constants". This is a bit misleading. For an unsuffixed decimal literal, the compiler will automatically chose the smallest type from int -> long -> long long sequence that can accommodate the constant. In this case int is chosen just because the constants fit in it. And int happens to be a 16 bit signed type on this platform. It is more appropriate to say that the compiler uses "native" size for int type, not for integer constants. For example, 2 * 40000 would not overflow, even though 80 * 1000 does.

@AnT. Good point. I struggled a bit with how to word that. Your wording is more accurate.


text:
Verifiy NTP server update - at start
I have function to start an NTP service, right after obtaining wifi connection ( using ESP8266 board ).
from time to time, I get an error saying date and time is01-01-1970... which I assume is due to not reaching the server as intended.
A retry counter was added to give few more retries, but somehow I does not do the trick since I never get the expected message NTP CHECK: # and retry number ( while get an invalid date ).
I know that NTP.begin() returns a bool to describe success/ failure obtaining a NTP server
EDIT1: using NtpClientLib
How can it be done ?

void startNTP() {
        int counter = 0;
        while ( !NTP.begin("pool.ntp.org", 2, true) && counter <=2){
          Serial.print("NTP CHECK: #");
          Serial.println(counter);
          counter +=1;
          delay(1000);
        };
        NTP.setInterval(clockUpdateInt); // in seconds
}

which NTP library are you using? never get the expected message NTP CHECK: # and retry number - that suggests that that NTP.begin returns true

if you are using https://github.com/gmag11/NtpClient library, then the only reason begin returns false is if you pass in invalid arguments

@JaromandaX - I'm using NtpClientLib- and YES I know that result is true but still date is as noted...

the point is there's no point in running begin over and over again, since it only returns false if you pass in invalid arguments - as you are passing valid arguments, there's no need to check ... the way I would do it, in the code that relies on valid time, check NTP.getLastNTPSync() and skip the code if the result is 0

But those are the arguments- which are not invalid

As I said, they are valid, therefore there's no point in checking if .begin returns true ... it does ... but .begin doesn't return true when the time has been synchronised! it returns true before there's even an attempt to synchronise the time - so you need to check for when the time is synchronised

Having read the NTPClientLib code, I would say that the first sync is not even attempted for 1 second after NTP.begin() is called anyway.

You could do this
void startNTP() {
    NTP.begin("pool.ntp.org", 2, true);
    delay(2000); // there seems to be a 1 second delay before first sync will be attempted, delay 2 seconds allows request to be made and received
    int counter = 2;
    while ( !NTP.getLastNtpSync() && counter <=2) {
        Serial.print("NTP CHECK: #");
        Serial.println(counter);
        counter +=1;
        delay(1000);
    };
    NTP.setInterval(clockUpdateInt); // in seconds
}

or, you could do this
void loop() {
    // code that doesn't rely on valid time
    //
    // lets say this bit of code requires sync'd time
    if (NTP.getLastNtpSync()) {
        // this will only run once NTP has been sync'd at least once
    }
    // more code that doesn't require sync'd time
}

Now, you may want to check how long time hasn't been sync'd for in your code and do something if it's been too long


text:
String & Char concatenations
A newbie in Arduino- and I'm trying to concatenate string and chars ( well in python it is quite different ).
I'm trying to post a MQTT message- constructed following format to the client.publish(outTopic, "["+outTopic+"]"+ msg)
while outTopic is a char* variable, and msg is char- but I get an error for such concatenation.
please your help
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// GPIOs on SONOFF board
int LED_SONOFF = 13;
int REL_SONOFF = 12;
int PIN_SW = 14;

const char* ssid = "HomeNetwork_2.4G";
const char* password = "pswd";
const char* mqtt_server = "192.168.2.113";

WiFiClient espClient;
PubSubClient client(espClient);

char msg[50];
const char* outTopic = "HomePi/Dvir/Messages";
const char* inTopic = "HomePi/Dvir/Windows/SONOFF";
const char* inTopic2 = "HomePi/Dvir/Windows/All";
const char* clientID = "Sonoff#1";
String m1, m2;

void start_wifi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void setup() {
  start_wifi(); // start wifi service
  Serial.begin(115200); // start serial service
  delay(10);

  // define sonoff gpios
  pinMode(LED_SONOFF, OUTPUT);
  pinMode(REL_SONOFF, OUTPUT);
  pinMode(PIN_SW, INPUT_PULLUP); // GPIO14 has a pullup resistor
  digitalWrite(LED_SONOFF,HIGH); // LED high is OFF
  digitalWrite(REL_SONOFF,LOW);

  // start mqtt
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void switch_on() {
  digitalWrite(REL_SONOFF,HIGH);
  digitalWrite(LED_SONOFF, LOW); // LED ON
  pub_mqtt("Switch ON");
}

void switch_off() {
  digitalWrite(REL_SONOFF,LOW);
  digitalWrite(LED_SONOFF, HIGH); // LED OFF
  pub_mqtt("Switch OFF");
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  if ((char)payload[0] == '1') {
    switch_on();
  }
  if ((char)payload[0] == '0') {
    switch_off();
    Serial.print("payload: ");
    Serial.println(payload[0]);
  }

}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP8266Client")) {
      Serial.println("connected");
      client.publish(outTopic, "Connected");

      client.subscribe(inTopic);
      m1="Subscribed to: "+inTopic;
      client.publish(outTopic, m1);
      if (inTopic2 !=""){
        client.subscribe(inTopic2);
        m2="Subscribed to: ";//+ String(inTopic2);
        client.publish(outTopic, m2);
      }

    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

void pub_mqtt(char* msg) {
  client.publish(outTopic, msg);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  if (digitalRead(PIN_SW)==1) {
    if (digitalRead(REL_SONOFF)!=LOW) {
      switch_off();
    }
  }
  else if (digitalRead(PIN_SW)==0) {
    if (digitalRead(REL_SONOFF)!=HIGH){
      switch_on();
    }
  }
   delay(100);
}

Likely it would be best if you created a new string in which you place what you want to pass to the called method.  Guessing, you have asked if the C/C++ compiler could implicitly do this by asking it to arrange for pulling out bits of the string from flash memory (the const outTopic and the "[" characters you added in the line of code) with bits from RAM (the string msg).

You can't simply concatenate C strings like that. Instead you have to build them up into a new string.  For formatting like that the simplest way is with sprintf:
char outMessage[strlen(outTopic) + strlen(msg) + 3]; // Room for topic, message, [ and ] and terminating \0
sprintf(outMessage, "[%s]%s", outTopic, msg);
client.publish(outTopic, outMessage);

Another method is with strcpy and strcat:
char outMessage[strlen(outTopic) + strlen(msg) + 3]; // Room for topic, message, [ and ] and terminating \0
strcpy(outMessage, "[");
strcat(outMessage, outTopic);
strcat(outMessage, "]");
strcat(outMessage, msg);
client.publish(outTopic, outMessage);

You have to ensure that your "holding" string outMessage is big enough to hold everything you want to send, plus a terminating NULL character, otherwise your program will crash.
Another way of creating the "holding" variable is with alloca(). That allocates bytes on the stack for a variable - just like malloc() does on the heap, but doesn't require free()ing because it's on the stack and is reclaimed when the function exits:
char *outMessage = (char *)alloca(strlen(outTopic) + strlen(msg) + 3);

thank you- i fund first method more short and sensable. does it matter that outTopic is char* ?

%s connects to a char * data type.

I was referring to char outMessage[strlen(outTopic) + strlen(msg) + 3];

char *foo and char foo[x] are essentially the same. The second is a char * with memory allocation added in.

@Mejnko - can you please explain why +3 is needed, since for purpose of string concatenation, it is not needed - does it relevent for sending ?

One for the [, one for the ] and one for the terminating NULL character. Three in total.

I've edited my comment, after your reply :) - i ment to ask if an oridinary concatenation ( just any other 2 strings ) needn that NULL char ?

You always need the null character.


text:
Arduino Project Power Consumption Calculations
I have built an automated window blind controller that will adjust the angle of a servo based on the value received via a light dependent resistor.  Once every 10 minutes the MCU wakes up, gets the current value of the LDR, adjusts the angle of the servo accordingly and then goes back to SLEEP_MODE_PWR_DOWN using the watchdog timer.  I am using a 5v 16MHz ATMega168 Arduino Pro Mini as the MCU.  I have removed both of the on board LEDs to reduce idle power consumption.  I am also powering directly from the VCC pin so that I bypass the on board regulator reducing power consumption even more.  I'm trying to determine what is the best battery power option for this project.  The project is still in testing but appears to be working as intended.
Here is the sketch:
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <VarSpeedServo.h>

const int ldrPin = A0;          //Analog pin that the light dependent resistor is connected to
const int ldrPower = 8;         //Supply 5v to ldr just before reading and then shutoff after
const int servoPin = 9;         //Digital pin that the Clone Futaba S3003 servo is connected to

//PARAMETERS FOR LOW BATTERY WARNING
const int xVPin = A1;             //Analog pin that the external +V non-boosted power supply is connected to
const int lowVLED = 10;           //Digital pin LED is connected to.  Used to identify battery levels
const int flashDelay = 250;       //LED flash length for low battery warning
const int numFlash_Low = 3;       //Number of LED flashes for LOW battery warning
const int numFlash_Mid = 1;       //Number of LED flashes for MID battery warning
int runningTotalVoltage;          //Variable that stores the sum total of the voltage readings
float voltage = 0.00;             //Calculate voltage
unsigned sampleCount = 0;         //Variable that stores the current voltage sampling number
unsigned char LEDFlashCount = 0;  //Variable that stores the current LED flash number
const int voltageSamples = 20;    //Total number of voltage readings to take
float boostVoltage = 5.27;        //Variable for the output voltage from the 5v boost coverter
float minValert = 3.20;           //Variable for the very low battery level (for 3.7v Li-on battery)
float midValert = 3.60;           //Variable for early warning low battery level (for 3.7v Li-on battery)

//PARAMETERS FOR THE SERVO
VarSpeedServo myservo;        //Create servo object to control servo
const int angle1 = 2350;      //Variable for "Fully Closed" servo moving counter-clockwise rotation
const int angle2 = 1900;      //Variable for "Partially Open" servo moving conter-clockwise rotation
const int angle3 = 1468;      //Variable for "Fully Open" servo moving counter-clockwise rotation
int dest = 0;                 //Servo destination depending on sensor reading
const int spd = 15;           //Controls the speed of the servo moving between positions; 5 is slow
int prevPos = 0;              //Keep track of the angle two loops prior
int currPos = 0;              //Keep track of the angle one loop prior
int nextPos = 0;              //Keep track of the angle moving to during current loop

//PARAMETERS FOR THE VARIOUS LIGHT LEVELS THAT TRIGGER THE SERVO TO ROTATE
int lightLevel;               //The analog reading from the LDR
const int lowLight = 400;
const int midLight = 800;

int ATimer;
int BatTimer;
int SleepTime = 80;  //80 = 10 Min
int BatCheckTime = 8;  //8 = 1 Min

//WATCHDOG INTERRUPT
ISR (WDT_vect)
{
  wdt_disable();
}

void setup()
{
  //Serial.begin(9600);
  myservo.attach(servoPin);
  myservo.write(angle3, spd, true);
  pinMode(lowVLED, OUTPUT);
  pinMode(ldrPower, OUTPUT);
  doFirstRun();
}

void loop()
{
  BatteryCheckTimer();
  AwakeTimer();
  if (BatTimer == BatCheckTime)
  {
    doBattCheck();
  }

  if (ATimer == SleepTime)
  {
    doWhileAwake();
  } //End of Main loop if timer was reached

//Preparing to go to sleep

  byte old_ADCSRA = ADCSRA;                        // disable ADC //
  ADCSRA = 0;                                      // disable ADC //

  byte old_PRR = PRR;                              // disable Internal modules//
  PRR = 0xFF;                                      // disable Internal modules//

  MCUSR = 0;                                       // clear various "reset" flags//

  // Watchdog Timer Parameters//
  WDTCSR = bit (WDCE) | bit (WDE);                 // allow changes, disable reset
  WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0);   // set WDIE, and 8 seconds delay
  wdt_reset();                                     // pat the dog once program has executed.

  // Sleep Activation //
  set_sleep_mode (SLEEP_MODE_PWR_DOWN);            //Sleep mode Selection//
  sleep_enable();                                  //Sleep Now//

  sleep_cpu ();                                    //CPU is now sleeping

// Once awake, code executes from this point. Once CPU wakes up do the follwoing to restore full operations
  sleep_disable();
  PRR = old_PRR;
  ADCSRA = old_ADCSRA;
}

void BatteryCheckTimer()
{
  BatTimer++;
}

void AwakeTimer()
{
  ATimer++;
}

void doFirstRun()
{
  digitalWrite(ldrPower, HIGH);
  delay(flashDelay);
  lightLevel = analogRead(ldrPin);  //Query photo cell
  digitalWrite(ldrPower, LOW);
  //Define the ranges based on how bright it is, and set corresponding servo position
  if (lightLevel <= lowLight)
  {
    //Servo rotates to fully closed
    dest=angle1;
    nextPos=angle1;
  }
  else if (lightLevel > lowLight && lightLevel <= midLight)
  {
    //Servo rotates to partially open
    dest=angle2;
    nextPos=angle2;
  }
  else if (lightLevel > midLight)
  {
    //servo rotates to fully open
    dest=angle3;
    nextPos=angle3;
  }
  prevPos = nextPos;
  currPos = nextPos;
  myservo.attach(servoPin);         //Connect to servo
  myservo.write(dest, spd, true);   //Move the servo to the new position
  delay(flashDelay);
  myservo.detach();                 //Detach servo to keep it from humming on strain
  ATimer = 0;
  BatTimer = 0;
}

void doBattCheck()
{
  while (sampleCount < voltageSamples)
  {
    runningTotalVoltage += analogRead(xVPin);
    sampleCount++;
    delay(10);
  }
  //The boostVoltage value is external power source dependent.  If using a 5v boost conveter
  //check the boost output voltage and then enter that number in the boostVoltage variable.
  voltage = ((runningTotalVoltage/voltageSamples) * (boostVoltage/1023));
  if (voltage >= minValert && voltage <= midValert)
  {
    while (LEDFlashCount < numFlash_Mid)
    {
      digitalWrite(lowVLED, HIGH);
      delay(flashDelay);
      digitalWrite(lowVLED, LOW);
      LEDFlashCount++;
      delay(flashDelay);
    }
  }
  else if (voltage < minValert)
  {
    while (LEDFlashCount < numFlash_Low)
    {
      digitalWrite(lowVLED, HIGH);
      delay(flashDelay);
      digitalWrite(lowVLED, LOW);
      LEDFlashCount++;
      delay(flashDelay);
    }
  }
  sampleCount = 0;
  runningTotalVoltage = 0;
  LEDFlashCount = 0;
  BatTimer = 0;
}

void doWhileAwake()
{
  digitalWrite(ldrPower, HIGH);
  delay(flashDelay);
  lightLevel = analogRead(ldrPin);  //Query photo cell
  digitalWrite(ldrPower, LOW);
  //Define the ranges based on how bright it is, and set corresponding servo position
  if (lightLevel <= lowLight)
  {
    //Servo rotates to fully closed
    dest=angle1;
    nextPos=angle1;
  }
  else if (lightLevel > lowLight && lightLevel <= midLight)
  {
    //Servo rotates to partially open
    dest=angle2;
    nextPos=angle2;
  }
  else if (lightLevel > midLight)
  {
    //servo rotates to fully open
    dest=angle3;
    nextPos=angle3;
  }
  //IF the photocell reading is different from last sample then execute servo controls
  if (nextPos == prevPos && nextPos != currPos)
  {
    prevPos = currPos;
    ATimer = 0;
  }
  else if (nextPos != prevPos && nextPos != currPos)
  {
    prevPos = currPos;
    currPos = nextPos;  //Remember angle so we can compare it again next round
    pos_change();
  }
  else
  {
    prevPos = currPos;
    ATimer = 0;
  }
}

//This code moves the servo to the desired position
void pos_change()
{
  myservo.attach(servoPin);         //Connect to servo
  myservo.write(dest, spd, true);   //Move the servo to the new position
  delay(flashDelay);
  myservo.detach();                 //Detach servo to keep it from humming on strain
  ATimer = 0;
}

So, I hooked up a multi-meter and set it to monitor current draw.  I watched it for 30 minutes and below are the results.

Constant current draw is 26.8 microamps.
Every minute the sketch wakes up and quickly checks the battery voltage.  This process takes less than a seconds and the current draw increases to 38.8 microamps.
Every ten minutes the sketch wakes up and checks the LDR sensor.  If the sensor reading is different from the last reading the servo moves to a new preset angle.  When this happens the current draw increases to about 11 milliamps.  I forced a servo rotation a couple of times during this time period so that I could measure the current draw.  However, during the course of a normal day, I would expect the servo to rotate no more than four times (when the sun is rising, when the sun is at its highest level, when the sun is setting, and finally when the sun has completely set).

For the last 12 days I have been running the project from a single 18650 3.7v LiPo battery.  When I started the battery was at 4.12v.  Battery reading today is about 3.68v.  Seems to me that the project is draining the battery faster than it should be.  I drained the battery and then fully charged it before starting the test so I know the battery is good. I used an inline power bank capacity tester to measure the battery capacity during charge and when it was done it registered 2405 mah.
Here are the components of this project:

Arduino pro mini with on board LEDs and voltage regulator removed.
LDR sensor with 10k resistor
LED with 220K resistor for low battery warning
5v boost converter with on board LEDs removed (used to boost the 3.7v LiPo battery to 5v; actually boosts to about 5.27v)
Knock-off clone Futaba S3003 servo

Ultimately I would like to be able to power this project from a couple of 18650 batteries for 3 months or maybe 3 AA batteries for the same period of time.  Based on my research and power consumption expectations, I should be able to do it.  If I can't get any better power consumption out of this little think, I might hookup a small solar panel with a LiPo battery charge controller to help extend the battery life.
Any thoughts? Thanks.

Hello 28µA in sleep mode still quite high, have a look on this board... talk2.wisen.com.au/product-talk2-whisper-node-avr less the 4µA when sleeping and you can have the node powered by a single AA while the servo is powered by some fat batteries, like two Alkaline D.This setup will isolate the high drainage servo from the MCU and you can even monitor the all voltages. Finally, avoid rechargeable cells as the self discharge is quite high. For best results you could try the 3.6V Lithium thionyl chloride for the servos, but they're quite expensive.

The constant draw of 26.8 μA amounts to 0.6432 mAh per day.  38.8 μA for one second per minute is an additional 0.0048 mAh per day, and a second of 11 mA draw six times per hour would be 0.44 mAh per day.  This totals to 1.088 mAh per day, or 13.056 mAh in 12 days.  That's less than 5% of the 2405 mAh mentioned as the LiPo's capacity.  Judging from the usual discharge voltage graphs, battery voltage should still be above 4 V at that point.
If the above is correct, you might have a defective battery, or defective current measurements.  You could charge the battery in question, then connect a 100KΩ–150KΩ resistor across it.  As the battery discharges, measure and record its voltage a couple of times a day.  If you charge up several batteries at the same time, you could set one aside as an experimental control, attach a resistor across one of them, and attach another to your circuit.
The 26.8 μA draw while in power-down sleep is higher than I'd expect [by a factor of 3 or so].  If it includes boost converter quiescent current, perhaps use a PFET to shut down the converter when the servo isn't needed.  I'm supposing the Arduino is powered directly from the battery, and that you have a boost converter to get servo power.  Will the servo work ok straight from the battery?
You could power the Arduino straight from one LiPo, and power the converter and/or servo from another, to make it more likely the system will degrade safely as the batteries run down.
[Edit:] Although your Pro Mini is a 5V version, since you are powering directly from the VCC pin you can run it at a lower voltage.  See §30.3 Speed Grades, in spec sheet, for the “Safe Operating Area”, ie, the guaranteed-to-work voltage-vs-MHz region.  From Figure 30-1, Maximum Frequency vs. VCC, 3.78 V safely supports 16 MHz operation.  Running the Pro Mini at 16 MHz below that voltage is out of spec, but I'd expect it to work fine even at appreciably lower voltages.
Prescaling the system clock [see last paragraph, below] also reduces voltage requirements.  As the system clock scales down, current draw scales down more than linearly.  [End Edit]
When trying to reduce current draw in sleep mode, work with a sketch that just tries out various setups; that is, a sketch that doesn't read the LDR or control the servo.  A simple test sketch makes it easier to figure out what is going on.  You can try tests such as all irrelevant pins initialized to low outputs, or to pulled-up inputs, etc.
It looks like the code doesn't do any intensive processing.  The CPU needn't run at 16 MHz while executing delays.  Instead, you could prescale the system clock (ref. §10.10, System Clock Prescaler, in spec sheet) which will drop CPU current from a few milliamps to under a milliamp during delays.  You'd divide your delay counts by the scale factor, and might also change ADC clock scaling (ref. §25.4, Prescaling and Conversion Timing, in spec sheet).

thanks for the very detailed response.  Prolly gonna take me a bit to digest.  One correction: The 11 mA draw only occurs maybe 4 times per day rather than 6 times per hour.  Everything is being power from the one 18650 LiPo. The pro mini is the 5v variety.  Picture of project: https://s6.postimg.org/cn0okq9v5/Screen_Shot_2016_06_25_at_8_45_37_PM.png

I'm going to try to test one of my 18650 batteries using the resistor.  Is the process as simple as connecting one end of the resistor to the positive lead and one end to the negative?  Will any 100KΩ–150KΩ resistor do? Do I need to worry about resistor wattage rating?  Thanks.

@darksidekilo6, see edit. Note, feel free to upvote any and all useful answers. Note, almost any such resistor should be ok; power dissipation is on the order of 30 μA times 4 V, or 120 μW which is under a milliwatt.  Yes, just connect it straight across the battery.  Possibly use an ammeter in series, at first, to verify about 30 μA current.   Note, if Pro Mini is powered straight from battery, to measure voltages above battery voltage you would need a voltage divider (two resistors in series)

copy all on the resistor type and ability to run the 5v pro mini from VCC at less that 5v; I'm going to give it a try on the next battery test.  Your posts have been very helpful and should get me closer to my answer.  I have upvoted your comments but because I am a newbie to this forum, I don't have enough "wasta" yet the upvote count isn't showing.

could you provide me with a link to the spec sheet you are referencing.  The one's I have found online don't seem to match with the section references you are providing.  Thanks.

I think I found the current culprit.  So, I tried a different approach and place my multimeter inline with the positive lead from the servo only. Low and behold, it is drawing 3.65 milliamps in sleep mode.  Doing the math using the battery life calculator I get about 27 days which is about what I would expect based on the current draw for the last 12 days.  Anyway to get the servo to draw no current during sleep mode.  I figured using the software code myservo.detach() would do the trick; obviously not.

Atmel-42176-ATmega48PB-88PB-168PB_Datasheet.pdf is like the spec sheet I ref'd, but I was looking at the Oct 2015 version instead of the March 2016 version [see link].  For the March 2016 version, add 4 to the main section numbers in my answer.

Great, thanks.  I guess because the servo is always pulling some current that I just need to use more batteries.  If I can make 1 last about 27 days then 3 in parallel should get me close to the 90 days I'm looking for.

You should measure with a power meter the consumption of the arduino in the two conditions, active and standby. Remember that batteries last only for the 80% of their total capacity. If you can't achieve better results, you should build it with an attiny85.

Alberto, thanks for you input.  So I have those current draw measurements.  In standby or power down mode the project draws 26.8 microamps.  When the servo is rotating, the project draws about 11 milliamps.  On any given day, the project will spend 99% of its time in standby mode and the other 1% active.  So why can't I get a 2,500 mah 3.7v LiPo battery to last longer than a couple of weeks?

With some approximation, the battery in your setup will last 20 days at its best, so it seems to respect what you saw.

Alberto, looks like your right.  The darn servo current draw in idle mode is draining the battery more than I expected.  Need to isolate the servo with its own power source.

Or you should use a relay to detach the servo when in idle

I though about using a relay but I have read some posts that stay that the servo "Jumps" when powered on and moves to the manufacturer established angle before executing my sketch.  I guess that isn't really a big deal as I'm just controlling the angle of windows blinds and am more concerned with battery life.  What kind of relay would I use?  I have used DC to AC relays before; am i looking for a DC to DC relay?

You could use an optocoupler (til113 or similar) or a transistor seen your current draw. If you want to use a relay, you can use any relay with the coil rated at 5v. For less power consumption I suggest optocoupling or transistors.

did some research on the optocoupler and I wonder if I need to use a transistor as well with this circuit?  Can I just go from from the arduino through a resistor to the optocoupler then through another resistor to the servo?  Thanks.

4N35 has a Ic max of 50 mA so it should be fine if your servo just needs 11 mA

The scheme isn't correct, you should connect servo pos to battery pos then servo neg to opto collector and opto emitter to battery neg. The sig wire should be connected to an arduino pin directly, or if you want to isolate it, use also an optocoupler.

thanks.  Updated the scheme.  Need to order some optocouplers and test out.  Will let you know if all goes well.  New scheme here: https://postimg.org/image/j39natiel/

Ok thank you, I've seen the scheme, the resistor on the servo isn't necessary, but is all well connected.

If you look at the discharge curves of LiPo batteries, you can see the voltage will drop a bit faster when full. Then flatten out, and have a big voltage drop when they are almost empty. So I'm not sure you can tell from the 0.44V drop that the battery is being discharged faster.
If there is a problem, I think it is either the boost converters quiescent current, or the servo. Also not that because you have to convert the 3.7V up to 5V, the current coming from the battery will have to increase by 1.35 times (at 100% efficiency).
What booster are you using? How do you turn off the servo?
PS1;
I always use this calculator to get an approximate battery life.
PS2; I'd connect the pull-up resistor on the LDR to a digital pin, so you can activate it only when you need to measure the light level, saving 2-5 µA.

thanks for the reply.  I am in the process of putting together a picture that shows the wiring of the project.  I believe I have already connected the pull-up resistor of the LDR to a digital pin (const int ldrPower = 8;).  As far as the boost converter goes I am using one of those postage stamp size modules available from eBay.  According to the seller, the quiescent current is 130 microamps.  The servo is turned on and off via code right before and after an angle change.  Thanks.

Have you tried measuring the power going out of the battery, so including everything (servo, booster, and arduino)?

just checked the battery with a multi-meter and the power coming out before the booster is 3.68v.  The power coming off the booster going in to the servo and arduino is 5.27v.

link to picture of project: https://s6.postimg.org/cn0okq9v5/Screen_Shot_2016_06_25_at_8_45_37_PM.png

You measured voltage. What I meant was current.

I still don't see how you are turning off the servo!

it is prolly more appropriate to say that I am detaching the servo.  I guess there is no way to TURN OFF the servo unless I use a relay or attach it directly to one of the arduino pins.

So physically detached. In that case it can't use any current. I'd use a P-CHANNEL MOSFET to provide power to the servo when needed. Did you measure the current (so Amps, not volts) coming from the battery?

thanks.  I'll look into the P-Channel MOSFET.  As far as the amps go, I isolated just the servo and it is pulling 3.65 milliamps while the arduino is in sleep mode.  I don't know why I'm only getting 26.8 microamps for the whole project.  When I checked the current draw for the whole project I put one lead of the multimeter just before the battery and the other just after all of the other positive leads for all the sensors (LDR, LED, and servo).
P.S. I'm an electronics novice so most of what I know comes from research not extensive practical application.

these MOSFETs are making my brain hurt.  Link to picture of project with PFET providing power to servo.  Does it look right?  Im using pin 8 to momentarily provide power to the servo and pin 9 (PWM) to rotate the servo.  If I understand PFETs correctly I have to take pin 8 LOW to power the servo, so does that means that the PIN will be HIGH the rest of the time?  That seems like it will draw power from my battery during sleep.  https://postimg.org/image/irs6y21yl/

So, not sure which PFET to use.  I just need to power a 5v servo that will draw less than 100 ma. Any recommendations?

Pin 8 will be high during sleep but there is no current flowing from this pin to the mosfet. From what I read I get the feeling you are measuring the current wrong. The leads of the meter should be connected in series. It should be connected in such a way that if you were to remove the multimeter, the entire project would be without any power.


text:
Passing pointers between setup and loop
I'm new to the Arduino world. The last time i was programming microprocessors, was back with the Z80 in assembly language.
I am also teaching myself C++ and seems to be going quite well.
I have decided to write my own 'library' for driving 7 segment LED's. The reason for writing my own, rather then using an existing one is to aid with the learning process. I'm quite pleased to say it works ( it may not be the most efficient code)
The books I have on C++ are great, but i do find sometimes the explanation of concepts seem to get lost.
what I would like to know, how do you go about initialising an object class in setup() and using it in loop()? I have this sneaky suspicion that it involves creating the object on the heap, and passing a pointer to the object over somehow.
I could just initialise it once in loop(), and make my own continuous loop afterwards, but there are other things done between the and of a loop() and the beginning of the next loop() (things like timer interrupts).
I will post the code im using, but not the library unless asked to, as it is quite a few lines.
# include "Leddisplay.h"
void setup() {

    byte Digit[9] = { 22, 23 , 24 ,25, 26, 27, 28, 29, 2 };

    Leddisplay *pRightDigit = new Leddisplay(Digit);

}

void loop() {

    pRightDigit->setDigit(5);
    pRightDigit->displayDigit();

}

^^  Obviously this does not compile  ^^
# include "Leddisplay.h"
void setup() {

}

void loop() {

    byte Digit[9] = { 22, 23 , 24 ,25, 26, 27, 28, 29, 2 };
    Leddisplay *pRightDigit = new Leddisplay(Digit);

    pRightDigit->setDigit(5);
    pRightDigit->displayDigit();

    for (;;);   // or do.. while within which has other code to repeat
                // but wont allow anything to be executed between loop() iterations

}

^^  This does, and runs fine, but may not achieve what I want  ^^
I'm not sure if I have used the right wording, or even asked the right question.
Thank you for any help in advance.
Dave

Declare the Leddisplay *pRightDigit variable outside of the scope of these functions and in the global space.

I know that's a scope question. But remember that setup(){} and loop(){} are an Arduino thing. You could do is leave setup(){} empty and do:
setup(){}  loop(){  int a = 0;  while(1)  {    a++;  } }

Timer interrupts aren't handled after the loop! The will interrupt the current loop code, wherever it currently is, run the ISR, and then return back to where it was in the loop. The only thing that is handled after the loop is, the arduino code check is there is any serial data available, and calls the function serialEvent if it is defined. If you aren't using this function (which is kind of silly anyways), you can use a for(;;;) or while(1) without any problems.

What you have to understand is the concept of scope.
Everything (well, almost everything) in C and C++ is enclosed in { and }. Those define a scope, and everything defined within that scope is available to any other scopes defined within that scope.
You can also assume that the whole sketch is surrounded by { and }. This scope is called the global scope.  Anything defined within it is available anywhere in your sketch.
So by defining the object in the global scope it is available everywhere:
# include "Leddisplay.h"

Leddisplay *pRightDigit;

void setup() {
    byte Digit[9] = { 22, 23 , 24 ,25, 26, 27, 28, 29, 2 };
    pRightDigit = new Leddisplay(Digit);
}

void loop() {
    pRightDigit->setDigit(5);
    pRightDigit->displayDigit();
}

However the use of new etc is discouraged in low-memory systems. Better is to statically define the object:
# include "Leddisplay.h"

const byte Digit[9] = { 22, 23 , 24 ,25, 26, 27, 28, 29, 2 };
Leddisplay pRightDigit(Digit);

void setup() {
}

void loop() {
    pRightDigit.setDigit(5);
    pRightDigit.displayDigit();
}

Note that, when statically defined like this, things in the constructor aren't guaranteed to be run at the right time. They should be moved into a .begin() function that you then call from setup():
# include "Leddisplay.h"

const byte Digit[9] = { 22, 23 , 24 ,25, 26, 27, 28, 29, 2 };
Leddisplay rightDigit(Digit);

void setup() {
    rightDigit.begin();
}

void loop() {
    rightDigit.setDigit(5);
    rightDigit.displayDigit();
}

The Library I have written can (and does) drive multiple led displays.
I also understand then when programming for ucontrollers, you use as little ram as possible.
Also, you usually know at compile time, what hardware is available,
However, say you only know how many displays there are at runtime. This is why I have created the LED display instance on the heap (I assume on the Arduino, thats RAM, not flash)
Let us say at runtime the program would ask you how many displays are connected via the serial terminal, then they will be activated, and a recompile is not an option.
Regards,
Dave

... how do you go about initialising an object class in setup() and using it in loop()?

You declare it in a global context so that it's accessible by both.
But that's not quite what you want here:
#include "Leddisplay.h"

byte Digit[] = {...};
Leddisplay RightDigit(Digit);

void setup() {
}

void loop() {
    RightDigit.setDigit(5);
    RightDigit.displayDigit();
}

Sorry, I cannot comment as I do not yet have enough rep.
This is in response to @Dave Dunnes comment

The Library I have written can (and does) drive multiple led displays.
  I also understand then when programming for ucontrollers, you use as
  little ram as possible. Also, you usually know at compile time, what
  hardware is available, However, say you only know how many displays
  there are at runtime. This is why I have created the LED display
  instance on the heap (I assume on the Arduino, thats RAM, not flash)
  Let us say at runtime the program would ask you how many displays are
  connected via the serial terminal, then they will be activated, and a
  recompile is not an option. Regards, Dave – Dave Dunne 9 hours ago

If you do not know the exact number of segments (or any element really) at build time then you could implement a linked list and dynamically allocate new  Leddisplay objects at run time or build the list in to your class. Alternatively you can try try using std::list with the AVR port of the STL (I have not personally tried this).