WebClient and MotionDetector stops after a while - c++

I've been digging this for around a week and doesn't have any way to solve this one. My Arduino code is working for a while (few times / few days) and then stops all of a sudden. I'm trying to implement a WebClient within the Arduino which sends HTTP GET requests to some other server every time (periodically - every 90 seconds) when a motion had been detected / when motion had stopped.
Below you can find the code. Can anyone assist?
#include <Ethernet2.h>
#include <SPI.h>
byte mac[] = { 0x90, 0xA2, 0xDA, 0x10, 0x73, 0x88 };
IPAddress ip(192,168,20,84);
IPAddress server(192,168,50,93); // Google
IPAddress myDns(8, 8, 8, 8);
EthernetClient client;
//getMovement - sends a GET request when motion is detected
void getMovement() {
client.stop();
if (client.connect(server, 8080)) {
client.println("GET /GetARoomMaven/motion?roomId=1&movement=1");
client.println();
Serial.println("Movement Request Sent");
} else {
Serial.println("connection failed");
}
}
//getNoMovement - sends a GET request when motion had stopped
void getNoMovement() {
client.stop();
if (client.connect(server, 8080)) {
client.println("GET /GetARoomMaven/motion?roomId=1&movement=0");
client.println();
Serial.println("Movement Request Sent");
} else {
Serial.println("connection failed");
}
}
//VARS
//the time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 10;
//the time when the sensor outputs a low impulse
long unsigned int lowIn;
//the amount of milliseconds the sensor has to be low
//before we assume all motion has stopped
long unsigned int pause = 90000;
//
boolean lockLow = true;
boolean takeLowTime;
int pirPin = 2; //the digital pin connected to the PIR sensor's output
int ledPin = 13;
/////////////////////////////
//SETUP
void setup(){
Serial.begin(9600);
pinMode(pirPin, INPUT);
pinMode(ledPin, OUTPUT);
digitalWrite(pirPin, LOW);
Ethernet.begin(mac);
//give the sensor some time to calibrate
Serial.print("calibrating sensor ");
for(int i = 0; i < calibrationTime; i++){
Serial.print(".");
delay(1000);
}
Serial.println(" done");
Serial.println("SENSOR ACTIVE");
delay(50);
loop();
}
////////////////////////////
//LOOP
void loop(){
if(digitalRead(pirPin) == HIGH){
digitalWrite(ledPin, HIGH); //the led visualizes the sensors output pin state
if(lockLow){
//makes sure we wait for a transition to LOW before any further output is made:
lockLow = false;
Serial.print("motion detected at ");
Serial.print(millis()/1000);
Serial.println(" sec");
getMovement();
}
takeLowTime = true;
}
if(digitalRead(pirPin) == LOW){
digitalWrite(ledPin, LOW); //the led visualizes the sensors output pin state
if(takeLowTime){
lowIn = millis(); //save the time of the transition from high to LOW
takeLowTime = false; //make sure this is only done at the start of a LOW phase
}
//if the sensor is low for more than the given pause,
//we assume that no more motion is going to happen
if(!lockLow && millis() - lowIn > pause){
//makes sure this block of code is only executed again after
//a new motion sequence has been detected
lockLow = true;
Serial.print("motion ended at "); //output
Serial.print((millis() - pause)/1000);
Serial.println(" sec");
getNoMovement();
}
}
}

It's hard to say without a better description of symptoms.
Are the LED still blinking ?
If yes, the socket code seems wrong to me:
void getMovement() {
client.stop();
You must remember that TCP requires connection tracking, so you can't immediately stop a socket, it has to linger a bit for acknowledging packets sent.
If you look at the implementation:
void EthernetClient::stop() {
if (_sock == MAX_SOCK_NUM)
return;
[...]
}
stop() will fail if you have more than MAX_SOCK_NUM (which is 4 on your platform) opened at a time. Can this happen?
In all case, you should avoid as much as possible dynamic allocations, you should have a single function sendMovement(bool detected) that's writing the detected value (getMovement and getNoMovement are the same function, so factorize them). You should re-use the client as much as possible (avoid closing the socket and re-opening it unless you get an error from any socket function). Finally, you might want to set up an interrupt on the digital input pin (with some software debouncing) to avoid polling on it, that would release CPU, and, depending on the configuration, might release more time to process SPI messages.
If the LED are not blinking, try to comment out the SPI related code (EthernetClient's code) and check if it works (in that case, I would check the HW for errors, some of the socket code is busy looping (socket::send does this) that would never finish and stop your loop function from progressing. In that case, if you use JTAG to pause the CPU, it'll be in the client.connect or client.println method.
If it still does not work (LED not blinking with no SPI code), then the issue is likely hardware, check voltage / temperature / JTAG connect to the board to interrupt the CPU to figure out where it's struck.
BTW, if you are doing HTTP, the request is wrong and should be:
GET url HTTP/1.1\r\n
Host: yourserverhost.com\r\n
Connection: Keep-Alive\r\n
\r\n
The part HTTP/1.x after the GET url is absolutely required even for HTTP/1.0. Unless you've written your own server (in that case, there's no need to mimick HTTP), it should not work at all, not even once.

Related

ESP8266-01 does not react to AT Commands over UART with TM4C123GH6PM

I am trying to connect my TM4C123GH6PM Microcontroller from Texas Instruments with my Smartphone and use it to control an alarm clock and LED Lights. (the LEDs are controlled over a Transistor, which is controlled over an GPIO Pin).
I have some experience with coding in C++ and the TM4C123GH6PM, but I am still learning a lot. So please excuse some foolish mistakes I might have made.
I want to connect the ESP8266 with the Microcontroller using UART and the TivaWare Framework.
I have written some code and my UART works correctly (I tested it by sending chars from UART 4 to 3).
According to the AT commands of ESP8266 It should respond to "AT" with "OK". But whenever I send something to the ESP it responds with exactly what I sent to it. I checked the wiring, and that's not The Issue. Or at least I think so. Please correct me, if the wiring is wrong.
ESP -> TM4C123GH6PM:
GND -> GND
VCC -> 3.3V
Tx -> Rx (UART3 / PC6)
Rx -> Tx (UART4 / PC5)
CH_PD -> 3.3V
I also checked for the power consumption of the ESP. Everything is powered by the USB-port of my laptop, since that helps keep the cable mess down. I monitor the power consumption with (https://www.amazon.de/gp/product/B07C8CM5TG/ref=ppx_yo_dt_b_asin_title_o08_s00?ie=UTF8&psc=1). The ESP is drawing about 150mA from the computer, but the port can provide a lot more. I checked with some LEDs and 400mA is not a problem.
Can anyone help me? I am working on this now for over two days and can't find a Solution. What is the Problem with the ESP not responding correctly to the AT command? The blue light is one, when the code is running.
PS: The attached code contains also code for the alarm clock control and LEDs. I attached it, since it could be part of the problem, but some of it is commented out and most of it is not used.
#include<stdint.h>
#include<stdbool.h>
#include"inc/hw_ints.h"
#include"inc/hw_memmap.h"
#include"inc/hw_types.h"
#include"driverlib/gpio.h"
#include"driverlib/sysctl.h"
#include"driverlib/timer.h"
#include"driverlib/interrupt.h"
#include"driverlib/uart.h"
#include"driverlib/pin_map.h"
#include "driverlib/rom.h"
// stores the time since system start in ms
uint32_t systemTime_ms;
//bools or controling the alarm clock and LEDS
bool an_aus = false;
bool alarm_clock = false;
void InterruptHandlerTimer0A (void)
{
// Clear the timer interrupt flag to avoid calling it up again directly
TimerIntClear(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
// increase the ms counter by 1 ms
systemTime_ms++;
}
void clockSetup(void)
{
uint32_t timerPeriod;
//configure clock
SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ| SYSCTL_OSC_MAIN);
//activate peripherals for the timer
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
// configure timers as 32 bit timers in periodic mode
TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC);
// set the variable timerPeriod to the number of periods to generate a timeout every ms
timerPeriod = (SysCtlClockGet()/1000);
// pass the variable timerPeriod to the TIMER-0-A
TimerLoadSet(TIMER0_BASE, TIMER_A, timerPeriod-1);
// register the InterruptHandlerTimer0A function as an interrupt service routine
TimerIntRegister(TIMER0_BASE, TIMER_A, &(InterruptHandlerTimer0A));
// activate the interrupt on TIMER-0-A
IntEnable(INT_TIMER0A);
// generate an interrupt when TIMER-0-A generates a timeout
TimerIntEnable(TIMER0_BASE, TIMER_TIMA_TIMEOUT);
// all interrupts are activated
IntMasterEnable();
// start the timer
TimerEnable(TIMER0_BASE, TIMER_A);
}
void UART (void)
{
//configure UART 4:
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART4);
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UART4));
//GPIO pins for transmitting and receiving
GPIOPinConfigure(GPIO_PC4_U4RX);
GPIOPinConfigure(GPIO_PC5_U4TX);
GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_4 | GPIO_PIN_5);
//configure UART 8Bit, no parity, baudrat 38400
UARTConfigSetExpClk(UART4_BASE, SysCtlClockGet(), 38400, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
//configure UART 3:
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART3);
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UART3));
GPIOPinConfigure(GPIO_PC6_U3RX);
GPIOPinConfigure(GPIO_PC7_U3TX);
GPIOPinTypeUART(GPIO_PORTC_BASE, GPIO_PIN_6 | GPIO_PIN_7);
UARTConfigSetExpClk(UART3_BASE, SysCtlClockGet(), 38400, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));
}
void delay_ms(uint32_t waitTime)
{
// Saves the current system time in ms
uint32_t aktuell = systemTime_ms;
// Wait until the current system time corresponds to the sum of the time at the start of the delay and the waiting time
while(aktuell + waitTime > systemTime_ms);
}
void ex_int_handler(void)
{
// press the button to start timer for alarm clock
alarm_clock = true;
GPIOIntClear(GPIO_PORTF_BASE,GPIO_PIN_4);
}
int main(void)
{
//Peripherals for LED and GPIO
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
//UART
UART();
//Timer
clockSetup();
// button
GPIOPinTypeGPIOInput(GPIO_PORTF_BASE,GPIO_PIN_4);
GPIOPadConfigSet(GPIO_PORTF_BASE,GPIO_PIN_4,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
//OnboardLED
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,GPIO_PIN_1);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE,GPIO_PIN_3);
//Interrupt Timer
GPIOIntDisable(GPIO_PORTF_BASE,GPIO_PIN_4);
GPIOIntClear(GPIO_PORTF_BASE,GPIO_PIN_4);
GPIOIntTypeSet(GPIO_PORTF_BASE,GPIO_PIN_4,GPIO_FALLING_EDGE);
GPIOIntRegister(GPIO_PORTF_BASE,ex_int_handler);
GPIOIntEnable(GPIO_PORTF_BASE,GPIO_PIN_4);
//Transistor Gate
GPIOPinTypeGPIOOutput(GPIO_PORTB_BASE,GPIO_PIN_0);
//GPIOPadConfigSet(GPIO_PORTB_BASE,GPIO_PIN_0,GPIO_STRENGTH_6MA,GPIO_PIN_TYPE_STD_WPU);
//debugging only: save all the received data from the ESP in an array to look at while debugging
int32_t data[20] = {0};
int32_t j = 0;
//Code for debugging the UART and ESP8266
while(1){
//Checks for Data in the FIFO
while(!UARTCharsAvail(UART4_BASE));
//send AT-command to ESP8266
UARTCharPut(UART4_BASE, 'A');
while(UARTBusy(UART4_BASE));
UARTCharPut(UART4_BASE, 'T');
while(UARTBusy(UART4_BASE));
if(UARTCharsAvail(UART3_BASE))
{
while(UARTCharsAvail(UART3_BASE))
{
//Read data from the FIFO in UART3 -> received from ESP8266
data[j] = UARTCharGet(UART3_BASE);
j++;
}
}
//clear array when its full
if (j >= 20)
{
j = 0;
for(int32_t a = 0; a <21; a++)
{
data[a] = 0;
}
}
}
//code to run the alarm clock and leds
/*
while(1)
{
if (alarm_clock)
{
GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_3,GPIO_PIN_3);
//Wait
delay_ms(30600000);
GPIOPinWrite(GPIO_PORTB_BASE,GPIO_PIN_0,GPIO_PIN_0);
alarm_clock = false;
GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_3,0x00);
//Start Red LED blinking when it is finished
while(1)
{
GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1,GPIO_PIN_1);
delay_ms(1000);
GPIOPinWrite(GPIO_PORTF_BASE,GPIO_PIN_1,0x00);
delay_ms(1000);
}
}
}
*/
}
According to the AT commands of ESP8266 It should respond to "AT" with
"OK". But whenever I send something to the ESP it responds with
exactly what I sent to it
Modems with AT Commands commonly ship with the echo mode turned on, so that when you are interacting with it manually through serial port, it will echo the characters you sent first, and then send the reply.
So, when you are automating the process, you first send the characters, then wait for the reply until you reach a '\r'. Well, you are reaching a '\r', but its the one from the echo. You might have some other characters next. You send AT, you should receive AT first, then you have the OK.
To solve this problem, you should turn echo mode off.
The command to turn off echo is ATE0.

Debugging Arduino Uno code running on Arduino MKR1000

So, I am an amateur programmer at Arduino, and have never used Arduino MKR1000 before. I used an Arduino Uno and wrote the attached code that detects heart beat and temperature using the Grove Ear clip heart beat sensor and the Grove Temperature sensor and then prints them in the console every 20 seconds. Previously, this code was written to show in an Grove OLED screen but later simplified it back to using it by reading on just the console.
Because of the wearable nature of my project I have to switch to using a MKR1000 instead. I know the MKR1000 uses the same Arduino code and should work the same way as it did on my Arduino Uno, but I have been having some issues with using the MKR1000 with the same code.
The issue is that the code only runs once and stops after that. While I am aware of the for loops and how it works to certain extent, I cannot find the exact issue why it stops looping instead of taking the data constantly and publishing it on the console, like it did previously with my Uno.
Just for the heads up, following is how my code reacted to Arduino Uno:
The result in the console shows:
Please be ready
This will now begin
then it prints number 1 to 20 every second followed by sensor readings. After publishing this, it repeats this process again.
Again sorry for the inconvenience and thank you for your help.
I used direct codes from the documentation blog of the sensors (bottom of the page of the linked page):
Grove heart bear sensor
Grove Temperature sensor
#define LED 4//indicator, Grove - LED is connected with D4 of Arduino
boolean led_state = LOW;//state of LED, each time an external interrupt
//will change the state of LED
float tempa;
int tempPin = 0;
unsigned char counter;
unsigned long temp[21];
unsigned long sub;
bool data_effect=true;
unsigned int heart_rate;//the measurement result of heart rate
const int max_heartpluse_duty = 2000;//you can change it follow your system's request.
//2000 meams 2 seconds. System return error
//if the duty overtrip 2 second.
void setup()
{
pinMode(LED, OUTPUT);
Serial.begin(9600);
while (!Serial){
;
}
Serial.println("Please be ready");
delay(5000);
arrayInit();
Serial.println("This will now begin.");
attachInterrupt(0, interrupt, RISING);//set interrupt 0,digital port 2
}
void loop()
{
digitalWrite(LED, led_state);//Update the state of the indicator
}
/*Function: calculate the heart rate*/
void sum()
{
if(data_effect)
{
heart_rate=1200000/(temp[20]-temp[0]);//60*20*1000/20_total_time
Serial.print("Heart_rate_is:\t");
Serial.println(heart_rate);
tempa = analogRead(tempPin);
tempa = tempa * 0.11;
Serial.print("Body Temperature = ");
Serial.print(tempa);
Serial.print("*C");
Serial.println();
delay(1000);
}
data_effect=1;//sign bit
}
/*Function: Interrupt service routine.Get the sigal from the external interrupt*/
void interrupt()
{
temp[counter]=millis();
Serial.println(counter,DEC);
switch(counter)
{
case 0:
sub=temp[counter]-temp[20];
break;
default:
sub=temp[counter]-temp[counter-1];
break;
}
if(sub>max_heartpluse_duty)//set 2 seconds as max heart pluse duty
{
data_effect=0;//sign bit
counter=0;
Serial.println("measurement error,test will restart!" );
arrayInit();
}
else if (counter==20&&data_effect)
{
counter=0;
sum();
}
else if(counter!=20&&data_effect)
{
counter++;
}
else
{
counter=0;
data_effect=1;
}
}
/*Function: Initialization for the array(temp)*/
void arrayInit()
{
for(unsigned char i=0;i < 20;i ++)
{
temp[i]=0;
}
temp[20]=millis();
}
Your problem is the interrupt pin. On the Arduino UNO the digital pin D2 is interrupt pin 0, as you have done in your code. On the Arduino MKR1000 the interrupt pin is tha same as the physical pin number, so if you'r connecting to pin 2, change attachInterrupt(0, interrupt, RISING); to attachInterrupt(2, interrupt, RISING);
If you wanna be sure to use the right pin you can use digitalPinToInterrupt(pin) to get the correct interrupt number on any Arduino board. Like this attachInterrupt(digitalPinToInterrupt(pin), interrupt, RISING); where pin is the physical pin number.
Info
On the Arduino MKR1000 you can use pin 0, 1, 4, 5, 6, 7, 8, 9, A1 and A2 as interrupt

Arduino Uno to Particle Photon - Converting Code

Please bear with me. I am an amateur programmer at Arduino, and have never used Particle photon before.
I used an Arduino Uno and wrote the attached code that detects heart beat and temperature using the Grove Ear clip heart beat sensor and the Grove Temperature sensor and then prints them in the console every 20 seconds. Previously, this code was written to show in an Grove OLED screen but later simplified it back to using it without the OLED screen.
I am now looking into using the same application and function using the same sensor on a Particle Photon (as it is smaller and has WiFi capability). I have never previously used this technology before but I saw online that it, more or less, uses the same code application. I have been through the sample codes for this online available on its website but I have no idea how to convert my code for the Arduino into code for the photon (Photon console compiles the code without any error but does not show any sensor data). Can someone either point me to the right direction/ appropriate online resources / help me change this code here to make it work on the Photon? (I just added the Particle.publish() wherever I was using Arduino's Serial.println() but it still doesn't print anything).
The result in the console shows:
Please be ready
This will now begin
then it prints number 1 to 20 every second followed by sensor readings.
Again sorry for the inconvenience and thank you for your help.
I used direct codes from the documentation blog of the sensors (bottom of the page of the linked page):
Grove heart bear sensor
Grove Temperature sensor
#define LED 4//indicator, Grove - LED is connected with D4 of Arduino
boolean led_state = LOW;//state of LED, each time an external interrupt
//will change the state of LED
float tempa;
int tempPin = 0;
unsigned char counter;
unsigned long temp[21];
unsigned long sub;
bool data_effect=true;
unsigned int heart_rate;//the measurement result of heart rate
const int max_heartpluse_duty = 2000;//you can change it follow your system's request.
//2000 meams 2 seconds. System return error
//if the duty overtrip 2 second.
void setup()
{
pinMode(LED, OUTPUT);
Serial.begin(9600);
while (!Serial){
;
}
Serial.println("Please be ready");
delay(5000);
arrayInit();
Serial.println("This will now begin.");
attachInterrupt(0, interrupt, RISING);//set interrupt 0,digital port 2
}
void loop()
{
digitalWrite(LED, led_state);//Update the state of the indicator
}
/*Function: calculate the heart rate*/
void sum()
{
if(data_effect)
{
heart_rate=1200000/(temp[20]-temp[0]);//60*20*1000/20_total_time
Serial.print("Heart_rate_is:\t");
Serial.println(heart_rate);
tempa = analogRead(tempPin);
tempa = tempa * 0.11;
Serial.print("Body Temperature = ");
Serial.print(tempa);
Serial.print("*C");
Serial.println();
delay(1000);
}
data_effect=1;//sign bit
}
/*Function: Interrupt service routine.Get the sigal from the external interrupt*/
void interrupt()
{
temp[counter]=millis();
Serial.println(counter,DEC);
switch(counter)
{
case 0:
sub=temp[counter]-temp[20];
break;
default:
sub=temp[counter]-temp[counter-1];
break;
}
if(sub>max_heartpluse_duty)//set 2 seconds as max heart pluse duty
{
data_effect=0;//sign bit
counter=0;
Serial.println("measurement error,test will restart!" );
arrayInit();
}
else if (counter==20&&data_effect)
{
counter=0;
sum();
}
else if(counter!=20&&data_effect)
{
counter++;
}
else
{
counter=0;
data_effect=1;
}
}
/*Function: Initialization for the array(temp)*/
void arrayInit()
{
for(unsigned char i=0;i < 20;i ++)
{
temp[i]=0;
}
temp[20]=millis();
}

Arduino not reading float level switch signal

Hey I am trying to set up a project at the moment, I have a float level switch connected to pin 2 of my Arduino board, the other end is connected to the 5v in on the arduino.
I want to have the software display a message when the switch goes high but at the moment it goes straight to the message and I know that the switch is not set high as I have it in my hand.
In future it will send a text message when the signal goes high, being used for flood monitoring using a float level switch.
#include "SIM900.h"
#include <SoftwareSerial.h>
#include "sms.h"
SMSGSM sms;
//To change pins for Software Serial, use the two lines in GSM.cpp.
int numdata;
boolean started=false;
char smsbuffer[160];
char n[20];
int closed=0;//Sets initial signal to 0
const int switchPin = 2;
int switchState = 0; // current state of the button
int lastswitchState = 0; // previous state of the button
void setup()
{
//Serial connection.
Serial.begin(9600);
Serial.println("GSM Shield for Flood Early Warning System \n");
pinMode(switchPin, INPUT);
//Start configuration of shield with baudrate.
//For http uses is recommended to use 4800 or slower.
}
void loop() {
closed=digitalRead(switchPin);
// compare the buttonState to its previous state
if (switchState != lastswitchState) {
// if the state has changed, increment the counter
if (switchState == HIGH) {
// if the current state is HIGH then the button
// wend from off to on:
Serial.println("on");
} else {
// if the current state is LOW then the button
// wend from on to off:
Serial.println("off");
}
// Delay a little bit to avoid bouncing
delay(50);
}
// save the current state as the last state,
//for next time through the loop
lastswitchState = switchState;
if (closed == HIGH) {
Serial.println ("Switch signal received");
if (gsm.begin(2400)){
Serial.println("\n status=READY");
started=true;
}
else Serial.println("\n status=IDLE");
if(started){
//Enable this two lines if you want to send an SMS.
if (sms.SendSMS("0871234567", "Arduino SMS"))//Number you wish to text and the message to be sent
Serial.println("\nSMS sent OK");//Alert for Serial monitor once sms sent
}
}
}
You should connect your input pin to GND via a 10KOhm resistor. See https://www.arduino.cc/en/Tutorial/DigitalPins :
"This also means however, that pins configured as pinMode(pin, INPUT) with nothing connected to them, ... will report seemingly random changes in pin state, picking up electrical noise from the environment, or capacitively coupling the state of a nearby pin. ".
And https://www.arduino.cc/en/Reference/DigitalRead :
If the pin isn't connected to anything, digitalRead() can return either HIGH or LOW (and this can change randomly).
In other words, when your switch is open, the input pin is not in a defined state (either on or off). By adding a pulldown resistor (a 10 KOhm resistor between your input pin and GND, the resistor "pulls down" (=toward the ground) your pin, unless the switch is closed, in which case the connection to +5V prevails (because it is a direct connection, without a resistor).

Timing duration between two events

I want to compute the time between when I transmit and when I receive. My timer will start counting once I start transmitting then the timer will stop once I receive a response. I'm using C++ on my arduino uno. Base on my code I'm just measuring the delay, Which is not good. what I'm trying to measure is the elapsed time between i transmit and received. I hope you can help me.
output image
My code
#include <VirtualWire.h>
const int transmit_pin = 12;
const int receive_pin = 11;
char *controller;
unsigned long start, finished, elapsed;
void setup() {
//receiver settings
Serial.begin(9600); // Debugging only
vw_set_rx_pin(11);
vw_rx_start();
//transmitter settings
pinMode(13, OUTPUT);
vw_set_ptt_inverted(true);
vw_set_tx_pin(12);
vw_setup(1000); // speed of data transfer Kbps
}
void displayResult()
{
float h,m,s,ms;
unsigned long over;
elapsed=finished-start;
h=int(elapsed/3600000);
over=elapsed%3600000;
m=int(over/60000);
over=over%60000;
s=int(over/1000);
ms=over%1000;
Serial.print("Raw elapsed time: ");
Serial.println(elapsed);
Serial.print("Elapsed time: ");
Serial.print(h,0);
Serial.print("h ");
Serial.print(m,0);
Serial.print("m ");
Serial.print(s,0);
Serial.print("s ");
Serial.print(ms,0);
Serial.println("ms");
Serial.println();
}
void loop() {
//Transmitter
digitalWrite(13, 1);
controller = "1";
vw_send((uint8_t *)controller, strlen(controller));
vw_wait_tx(); //Wait until the whole message is go
start=millis();
delay(1000); // for debounce
Serial.println("Started...");
//Receiver
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen)) { // Non-blocking
digitalWrite(13, 0); //Flash a light to show received good
for(int i = 0;i < buflen;i++) {
if (buf[i] == '2')
{
finished=millis();
delay(1000); // for debounce
displayResult();
elapsed=finished-start;
Serial.print(start);
Serial.println(" milliseconds start");
Serial.print(finished);
Serial.println(" milliseconds finished");
Serial.print(elapsed);
Serial.println(" milliseconds elapsed");
Serial.println();
}
}
}
}
You say "Base on my code I'm just measuring the delay, Which is not good."
Ok, well:
start=millis();
delay(1000); // for debounce
Well, if you don't want to include the delay in your elapsed time, then take the start time after the delay(), not before.
This seems to be too obvious, so I suspect that you're really asking about something else. You need to show the output you're getting, why you think it's wrong, and what output you expect to get, instead.
Every thing happens during your delay period (the 1000ms delay). The message is received and stored in the buffer waiting for you to read it while you're in the delay. You're now measuring the execution time of a couple of lines of code and that takes less than a millisecond that is why you are getting the 0ms time.