time issue: millis() not properly used?

A sketch needs to detect a change to a analog input on pin 5, activate power to a HC12 transmitter (digital output pin8), send a one-time transmission burst (the analog value converted to a string plus some other string data), and then inhibit any further transmissions for a time interval2=2000ms. The power to the HC12 has to remain on during a time interval1=4000ms.
If a change to the analog input occurs within interval1 then the power on time has to be extended and the count-down timer with interval1 is to be reset.

What happens is that the power-on output pin8 produces a glitch (see picture, yellow trace) of 2ms.

(The blue trace is the output signal at the receiver end)

What in this sketch causes this glitch?

// http://forum.arduino.cc/index.php?topic=499210.msg3407044#msg3407044
// http://forum.arduino.cc/index.php?topic=396450.0

// HC12 Communication between Arduinos

/*
  This program serves to send one integer (or byte) only from two different HC12
  transmitters at one sensor each (A and B)to one HC12 receiver at the central
  controller Arduino. The receiving HC12 has to know from which transmitter A or B
  the value comes.
  The data are sent with start- and endmarkers

  v5: two integers used, one for the sensor values (integer1FromPC & integer2FromPC) and
  one char for the sensor identifier (A or B). At the transmitter the sensors A or B are
  identiefied by reading two digital inputs connected to a dipswitch with
  2 switches (max: 4 different sensor/transmitters).

  // TRANSMITTER PART
*/

#include <SoftwareSerial.h>
const byte HC12RxdPin = 4;                  // Recieve Pin on HC12
const byte HC12TxdPin = 5;                  // Transmit Pin on HC12
SoftwareSerial HC12(HC12TxdPin, HC12RxdPin); // Create Software Serial Port
int analogValue5, val5;
int previousAnalogValue5;
int HC12power = 8;
const int interval1 = 4000; // HC12 power-on time in milliseconds
const int interval2 = 2000; // HC12 retransmission time delay
static unsigned long previousMillis1; // timer1
static unsigned long previousMillis2; // timer2
boolean HC12ResendReady = true;

void setup()
{
  Serial.begin(9600);     // Open serial port to computer
  HC12.begin(9600);       // Open serial port to HC12
  pinMode(HC12power, OUTPUT);
}

void loop()
{
  // read analog pin 5
  analogValue5 = analogRead(5);
  // remap values from the analogValue5 variable to 0 / 255
  val5 = map(analogValue5, 0, 1023, 0, 255);
  // detect if there is a change in value, if so: switch on HC12
  if (analogValue5 > (previousAnalogValue5 + 10) || analogValue5 < (previousAnalogValue5 - 10))
  {
    previousAnalogValue5 = analogValue5;
    if (digitalRead(HC12power) == LOW)
    {
      digitalWrite(HC12power, HIGH);
      delay(50);
    }

    if (HC12ResendReady == true)
    {
      HC12.print('<');
      HC12.print(val5);
      HC12.print(',');
      HC12.print(val5);
      HC12.print(",B>");
      HC12ResendReady = false;
    }
    previousMillis2 = millis();
    previousMillis1 = millis();  //reset timer as long as changes are detected within interval window
  }
  if ((millis() - previousMillis2) >= interval2) {
    previousMillis2 = millis();
    HC12ResendReady = true;
  }

  else {
    //when no more change in value for analogValue5, then start timer before switching off HC12
    if ((millis() - previousMillis1) >= interval1) {
      digitalWrite(HC12power, LOW);
      previousMillis1 = millis();
    }
  }
}

OPs image

Now I would like to see a schematic and the OP's wiring.

vaj4088:
Now I would like to see a schematic and the OP's wiring.

Attachment 2: delay line54=1ms
Attachment 3: delay line54=100ms
Attachment 4: schematic
Attachment 1: wiring

CCF15092017_0001.pdf (172 KB)

How much power is this thing drawing from pin 8? I bet it is asking for more than the 40mA maximum that the pin can deliver. (And at 40mA, the voltage drops down a lot.) The instantaneous power draw when transmitting is certainly much higher than the average power.

Maybe try a big capacitor (100uF or more) on that power pin? The real solution is to use a relay or MOSFET which can deliver the instantaneous power that the module requires.

After power-up a delay of 50ms is introduced before transmission takes place. If that current draw were too high a second glitch after 50ms would be visible. It is not.
Actual current draw is about 16mA. When transmitting it is about 20mA in the mode in which the HC12 is now programmed.
But a 100uF cap would do no harm. I will test that tomorrow and post a screenshot of the result.

EDIT: in hindsight, after reading subsequent posts, and doing a few more measurements I must stand corrected: you are right about the current draw.

brice3010:
But a 100uF cap would do no harm.

I wouldn't hang a 100uF cap on an output pin.

Why disconnect power.
The HC-12 can be put into a 22uA sleep mode.
Leo..

I'm not sure about the power glitch, but I don't think the timer management is correct. I have modified your code to start the timers when the events occur (analog value change or transmission) and removed the timeout actions from nested conditions. It looks cleaner to me.

// http://forum.arduino.cc/index.php?topic=499210.msg3407044#msg3407044
// http://forum.arduino.cc/index.php?topic=396450.0

// HC12 Communication between Arduinos

/*
  This program serves to send one integer (or byte) only from two different HC12
  transmitters at one sensor each (A and B)to one HC12 receiver at the central
  controller Arduino. The receiving HC12 has to know from which transmitter A or B
  the value comes.
  The data are sent with start- and endmarkers

  v5: two integers used, one for the sensor values (integer1FromPC & integer2FromPC) and
  one char for the sensor identifier (A or B). At the transmitter the sensors A or B are
  identiefied by reading two digital inputs connected to a dipswitch with
  2 switches (max: 4 different sensor/transmitters).

  // TRANSMITTER PART
*/

#include <SoftwareSerial.h>
const byte HC12RxdPin = 4;                  // Recieve Pin on HC12
const byte HC12TxdPin = 5;                  // Transmit Pin on HC12
SoftwareSerial HC12(HC12TxdPin, HC12RxdPin); // Create Software Serial Port
int analogValue5, val5;
int previousAnalogValue5;
int HC12power = 8;
const int interval1 = 4000; // HC12 power-on time in milliseconds
const int interval2 = 2000; // HC12 retransmission time delay
static unsigned long previousMillis1; // timer1
static unsigned long previousMillis2; // timer2
boolean HC12ResendReady = true;

void setup()
{
  Serial.begin(9600);     // Open serial port to computer
  HC12.begin(9600);       // Open serial port to HC12
  pinMode(HC12power, OUTPUT);
}

void loop()
{
  // read analog pin 5
  analogValue5 = analogRead(5);
  // remap values from the analogValue5 variable to 0 / 255
  val5 = map(analogValue5, 0, 1023, 0, 255);
  // detect if there is a change in value, if so: switch on HC12
  if (analogValue5 > (previousAnalogValue5 + 10) || analogValue5 < (previousAnalogValue5 - 10))
  {
    previousAnalogValue5 = analogValue5;
    //start or extend timer if power is off or on and analogValue5 changes
    previousMillis1 = millis();
    if (digitalRead(HC12power) == LOW)
    {
      digitalWrite(HC12power, HIGH);
      delay(50);
    }

    if (HC12ResendReady == true)
    {
      HC12.print('<');
      HC12.print(val5);
      HC12.print(',');
      HC12.print(val5);
      HC12.print(",B>");
      HC12ResendReady = false;
      previousMillis2 = millis();//start timer for reenable after send
    }
  }

  if ((millis() - previousMillis2) >= interval2)
  {
    HC12ResendReady = true;
  }

  if ((millis() - previousMillis1) >= interval1)
  {
    digitalWrite(HC12power, LOW);
  }
}

Looks to me like the HC is drawing more current then pin 8 can supply instantaneously, what is the time period between vertical divisions?

Transmit current of the HC-12 is 100mA.
Pin voltage seems to drop to just below 2volt during that transmit burst.
Leo..

A 100 microfarad capacitor can initially conduct a lot more than 40 mA.

This kind of behaviour can be caused by faults in the logic of what happens if there is a new burst of data during the retransmission supression interval. That is - which timers get restarted?

cattledog:
I'm not sure about the power glitch, but I don't think the timer management is correct. I have modified your code to start the timers when the events occur (analog value change or transmission) and removed the timeout actions from nested conditions. It looks cleaner to me.

// http://forum.arduino.cc/index.php?topic=499210.msg3407044#msg3407044

// Serial Input Basics - updated - Introductory Tutorials - Arduino Forum

// HC12 Communication between Arduinos

/*
  This program serves to send one integer (or byte) only from two different HC12
  transmitters at one sensor each (A and B)to one HC12 receiver at the central
  controller Arduino. The receiving HC12 has to know from which transmitter A or B
  the value comes.
  The data are sent with start- and endmarkers

v5: two integers used, one for the sensor values (integer1FromPC & integer2FromPC) and
  one char for the sensor identifier (A or B). At the transmitter the sensors A or B are
  identiefied by reading two digital inputs connected to a dipswitch with
  2 switches (max: 4 different sensor/transmitters).

// TRANSMITTER PART
*/

#include <SoftwareSerial.h>
const byte HC12RxdPin = 4;                  // Recieve Pin on HC12
const byte HC12TxdPin = 5;                  // Transmit Pin on HC12
SoftwareSerial HC12(HC12TxdPin, HC12RxdPin); // Create Software Serial Port
int analogValue5, val5;
int previousAnalogValue5;
int HC12power = 8;
const int interval1 = 4000; // HC12 power-on time in milliseconds
const int interval2 = 2000; // HC12 retransmission time delay
static unsigned long previousMillis1; // timer1
static unsigned long previousMillis2; // timer2
boolean HC12ResendReady = true;

void setup()
{
  Serial.begin(9600);    // Open serial port to computer
  HC12.begin(9600);      // Open serial port to HC12
  pinMode(HC12power, OUTPUT);
}

void loop()
{
  // read analog pin 5
  analogValue5 = analogRead(5);
  // remap values from the analogValue5 variable to 0 / 255
  val5 = map(analogValue5, 0, 1023, 0, 255);
  // detect if there is a change in value, if so: switch on HC12
  if (analogValue5 > (previousAnalogValue5 + 10) || analogValue5 < (previousAnalogValue5 - 10))
  {
    previousAnalogValue5 = analogValue5;
    //start or extend timer if power is off or on and analogValue5 changes
    previousMillis1 = millis();
    if (digitalRead(HC12power) == LOW)
    {
      digitalWrite(HC12power, HIGH);
      delay(50);
    }

if (HC12ResendReady == true)
    {
      HC12.print('<');
      HC12.print(val5);
      HC12.print(',');
      HC12.print(val5);
      HC12.print(",B>");
      HC12ResendReady = false;
      previousMillis2 = millis();//start timer for reenable after send
    }
  }

if ((millis() - previousMillis2) >= interval2)
  {
    HC12ResendReady = true;
  }

if ((millis() - previousMillis1) >= interval1)
  {
    digitalWrite(HC12power, LOW);
  }
}

Thank you, that was the code clean-up I suspected was needed but I could not figure out. Done.

Wawa:
I wouldn't hang a 100uF cap on an output pin.

Why disconnect power.
The HC-12 can be put into a 22uA sleep mode.
Leo..

Something that I did not state clearly enough: the purpose here is to measure the minimum delay needed between power-on and transmit to obtain reliable transmissions.

edgemoron:
Looks to me like the HC is drawing more current then pin 8 can supply instantaneously, what is the time period between vertical divisions?

That you can see in the upper left corner, after the white "H".

Wawa:
Transmit current of the HC-12 is 100mA.
Pin voltage seems to drop to just below 2volt during that transmit burst.
Leo..

You are about right: I extended the recording time of the oscilloscope to include a dip caused by the instant the actual transmission takes place, see attachement.
This is also recorded with a 100uF cap in place, attachement 2 shows the power-on instant: compared to prior to cap installed the ramp-up is slower but the cap clearly acts as a buffer-reservoir.

Conclusion: the arduino output should not drive this load directly.

brice3010:

what is the time period between vertical divisions?

That you can see in the upper left corner, after the white "H".

While that answer is factually correct (cr@p quality notwithstanding) why didn't you just answer the question?

PaulMurrayCbr:
This kind of behaviour can be caused by faults in the logic of what happens if there is a new burst of data during the retransmission supression interval. That is - which timers get restarted?

In the code above interval2 gets priority: no transmission unless expired, even if new data is present (interval1).

kenwood120s:
That you can see in the upper left corner, after the white "H".

While that answer is factually correct (cr@p quality notwithstanding) why didn't you just answer the question?

Because screenshots with different timebase had been posted.

vaj4088:
A 100 microfarad capacitor can initially conduct a lot more than 40 mA.

A 100uF cap is indeed playing with fire. The HC12 should be fed through a MOSFET switch. I will adapt my circuit.