Hi there!
Note: My question has been edited according to the changes in my program till now(reply#13).
I'm using Arduino UNO, Tiny Sine 3G GSM shield and a sensor (output values 0-1000)
I have written my code to read the sensor values from pin 12. But the code fails to enter the void loop () therefore failing to print the sensor value & send SMS to mobile. Can anyone explain to why I'm not able to see the values in Serial Monitor or get an SMS?
OUTPUT: FONA OK & prints IMEI number and nothing after that...
Please read the first post in any forum entitled how to use this forum. http://forum.arduino.cc/index.php/topic,148850.0.html then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.
// the setup routine runs once when you press reset:
#include "Adafruit_FONA.h"
#include <SoftwareSerial.h>
#define FONA_TX 2
#define FONA_RX 3
#define FONA_RST 4
// this is a large buffer for replies
char replybuffer[255];
char buffer[24];
char r[10];
SoftwareSerial C_Serial(12,13); //Sets up a virtual serial port
//Using pin 12 for Rx //and pin 13 for Tx
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX,FONA_RX);
SoftwareSerial *fonaSerial = &fonaSS;
// Hardware serial is also possible!
// HardwareSerial *fonaSerial = &Serial1;
// Use this for FONA 800 and 808s
//Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
// Use this one for FONA 3G
Adafruit_FONA_3G fona = Adafruit_FONA_3G(FONA_RST);
uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout = 0);
uint8_t type;
byte readC[] = {0xFF, 0X01, 0X86, 0X00, 0X00, 0X00, 0X00, 0X00,0X79}; //Command packet to read C (see app note)
byte response[] = {0,0,0,0,0,0,0,0,0}; //create an array to store the response
//multiplier for value. default is 1. set to 25 for O2 25%
int valMultiplier = 1;
void setup()
{
// put your setup code here, to run once:
Serial.begin(9600); //Opens the main serial port to communicate with the computer
C_Serial.begin(9600); //Opens the virtual serial port with a baud of 9600
Serial.println(F("FONA basic test"));
Serial.println(F("Initializing....(May take 3 seconds)"));
fonaSerial->begin(4800);
if (! fona.begin(*fonaSerial)) {
Serial.println(F("Couldn't find FONA"));
while (1);
}
type = fona.type();
Serial.println(F("FONA is OK"));
Serial.print(F("Found "));
switch (type) {
case FONA800L:
Serial.println(F("FONA 800L")); break;
case FONA800H:
Serial.println(F("FONA 800H")); break;
case FONA808_V1:
Serial.println(F("FONA 808 (v1)")); break;
case FONA808_V2:
Serial.println(F("FONA 808 (v2)")); break;
case FONA3G_A:
Serial.println(F("FONA 3G (American)")); break;
case FONA3G_E:
Serial.println(F("FONA 3G (European)")); break;
default:
Serial.println(F("???")); break;
}
// Print module IMEI number.
char imei[15] = {0}; // MUST use a 16 character buffer for IMEI!
uint8_t imeiLen = fona.getIMEI(imei);
if (imeiLen > 0) {
Serial.print("Module IMEI: "); Serial.println(imei);
}
// Optionally configure a GPRS APN, username, and password.
// You might need to do this to access your network's GPRS/data
// network. Contact your provider for the exact APN, username,
// and password values. Username and password are optional and
// can be removed, but APN is required.
fona.setGPRSNetworkSettings(F("yesinternet"), F("your username"), F("your password"));
// Optionally configure HTTP gets to follow redirects over SSL.
// Default is not to follow SSL redirects, however if you uncomment
// the following line then redirects over SSL will be followed.
//fona.setHTTPSRedirect(true);
}
void loop()
{
sendRequest(readC);
float valC = getValue(response);
Serial.print("C = ");
Serial.println(valC);
static unsigned long startTime = 0;
if (valC < 500)
startTime = millis();
dtostrf(valC, 3, 2, r);
sprintf(buffer, "%s High Level", r);
if (millis() - startTime > 1UL*60UL*1000UL) { // Has it been 15 minutes since the value was below 500?
//sendAlert();
fona.sendSMS("0xxxxxxx", buffer); //mobile number
}
//delay(1000);
}
void sendRequest(byte packet[])
{
while(!C_Serial.available()) //keep sending request until we start to get a response
{
C_Serial.write(readC,9);
delay(50);
}
int timeout=0; //set a timeoute counter
while(C_Serial.available() < 9 ) //Wait to get a 9 byte response
{
timeout++;
if(timeout > 10) //if it takes to long there was probably an error
{
while(C_Serial.available()) //flush whatever we have
C_Serial.read();
break; //exit and try again
}
delay(50);
}
for (int i=0; i < 9; i++)
{
response[i] = C_Serial.read();
}
}
unsigned long getValue(byte packet[])
{
int high = packet[2]; //high byte for value is 3rd byte in packet in the packet
int low = packet[3]; //low byte for value is 4th byte in the packet
unsigned long val = high*256 + low; //Combine high byte and low byte with this formula to get value
return val* valMultiplier;
}
char imei[15] = {0}; // MUST use a 16 character buffer for IMEI!
Did you forget to read your own comment? If the IMEI is indeed 16 bytes, it will clobber the stack, and when setup() returns, the program will wander off to la-la land.
@johnwasser ... I meant to say the program is perfectly running until void loop, sorry about that I should have mentioned that before.
And YES you were right, after commenting this part of the code:
{
// while(!C_Serial.available()) //keep sending request until we start to get a response
// {
// C_Serial.write(readC,9);
// delay(50);
// }
OUTPUT:FONA basic test
Initializing....(May take 3 seconds)
Attempting to open comm with ATs
---> AT
<--- OK
---> ATE0
<--- OK
---> ATE0
<--- OK
---> AT+CVHU=0
<--- OK
---> ATI
<--- Manufacturer: SIMCOM INCORPORATED
Model: SIMCOM_SIM5320E
Revision: SIM5320E_V1.5
IMEI: 861311008040262
+GCAP: +CGSM,+DS,+ES
OK
---> AT+CPMS="ME"
<--- +CPMS: 19,255,19,255,19,255
FONA is OK
Found FONA 3G (European)
---> AT+GSN
<--- 861311008040262
Module IMEI: 86XXXXXXXXXX
C = 4294967295
---> AT+CMGF=1
<--- OK
---> AT+CMGS="0xxxxxxx"
<--- >
4294967300.00 High Level
^Z
Can you please help me with the output, I'm not able to read the sensor connected to pin 12 ? I mean my valC variable is not reading the sensor value which is "0" .. Can you please look into this?
with regards to this part of the code: Sorry I used your part of the code here for checking sensor value for 1 minute and then sending the SMS
if (valC < 500)
startTime = millis();
dtostrf(valC, 3, 2, r);
sprintf(buffer, "%s High Level", r);
if (millis() - startTime > 15UL*60UL*1000UL) { // Has it been 15 minutes since the value was below 500?
//sendAlert();
fona.sendSMS("0XXXXXXX", buffer); //mobile number
}
1. Can you please help me with the output, as the expected output is '0' and the above output is showing " 4294967300.00 High Level"
I can't see enough of your code to figure out where that number is coming from. Please post the whole sketch again, after using auto-format to clean up the indentations.
Rishi_me:
2. with regards to this part of the code:
if (valC < 500)
startTime = millis();
dtostrf(valC, 3, 2, r);
sprintf(buffer, "%s High Level", r);
if (millis() - startTime > 15UL60UL1000UL) { // Has it been 15 minutes since the value was below 500?
//sendAlert();
fona.sendSMS("0424737176", buffer); //mobile number
}
but I'm getting SMS's every 1 sec ?
You forgot to put a "startTime = millis();" inside the "if (fifteen minutes has passed) {" so it waits at least another 15 minutes before sending another message.
// the setup routine runs once when you press reset:
#include "Adafruit_FONA.h"
#define FONA_TX 2
#define FONA_RX 3
#define FONA_RST 4
// this is a large buffer for replies
char replybuffer[255];
char buffer[24];
char r[10];
// We default to using software serial. If you want to use hardware serial
// (because softserial isnt supported) comment out the following three lines
// and uncomment the HardwareSerial line
#include <SoftwareSerial.h>
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX,FONA_RX);
SoftwareSerial *fonaSerial = &fonaSS;
SoftwareSerial Sensor_Serial(12,13);
// Hardware serial is also possible!
// HardwareSerial *fonaSerial = &Serial1;
// Use this for FONA 800 and 808s
//Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
// Use this one for FONA 3G
Adafruit_FONA_3G fona = Adafruit_FONA_3G(FONA_RST);
uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout = 0);
uint8_t type;
byte readCO[] = {0xFF, 0X01, 0X86, 0X00, 0X00, 0X00, 0X00, 0X00,0X79}; //Command packet to read CO (see app note)
byte response[] = {0,0,0,0,0,0,0,0,0}; //create an array to store the response
//multiplier for value. default is 1. set to 25 for O2 25%
int valMultiplier = 1;
void setup() {
while (!Serial);
Serial.begin(9600);
Sensor_Serial.begin(9600); //Opens the virtual serial port with a baud of 9600
Serial.println(F("FONA basic test"));
Serial.println(F("Initializing....(May take 3 seconds)"));
fonaSerial->begin(4800);
if (! fona.begin(*fonaSerial)) {
Serial.println(F("Couldn't find FONA"));
while (1);
}
type = fona.type();
Serial.println(F("FONA is OK"));
Serial.print(F("Found "));
switch (type) {
case FONA800L:
Serial.println(F("FONA 800L")); break;
case FONA800H:
Serial.println(F("FONA 800H")); break;
case FONA808_V1:
Serial.println(F("FONA 808 (v1)")); break;
case FONA808_V2:
Serial.println(F("FONA 808 (v2)")); break;
case FONA3G_A:
Serial.println(F("FONA 3G (American)")); break;
case FONA3G_E:
Serial.println(F("FONA 3G (European)")); break;
default:
Serial.println(F("???")); break;
}
// Print module IMEI number.
// char imei[15] = {0}; // MUST use a 16 character buffer for IMEI!
// uint8_t imeiLen = fona.getIMEI(imei);
// if (imeiLen > 0) {
// Serial.print("Module IMEI: "); Serial.println(imei);
// }
// Optionally configure a GPRS APN, username, and password.
// You might need to do this to access your network's GPRS/data
// network. Contact your provider for the exact APN, username,
// and password values. Username and password are optional and
// can be removed, but APN is required.
//fona.setGPRSNetworkSettings(F("yesinternet"), F("your username"), F("your password"));
// Optionally configure HTTP gets to follow redirects over SSL.
// Default is not to follow SSL redirects, however if you uncomment
// the following line then redirects over SSL will be followed.
//fona.setHTTPSRedirect(true);
}
void loop()
{
sendRequest(readCO);
unsigned long valCO = getValue(response);
static unsigned long startTime = 0;
if (digitalRead(valCO) < 500)
dtostrf(valCO, 3, 2, r);
sprintf(buffer, "%s High Level", r);
Serial.print("CO = ");
Serial.println(valCO);
//delay(1000);
if (millis() - startTime > 15UL*60UL*1000UL) { // Has it been 15 minutes since the value was below 500?
//sendAlert();
startTime = millis();
fona.sendSMS("0XXXXXX", buffer);
}
}
void sendRequest(byte packet[])
{
// while(!Sensor_Serial.available()) //keep sending request until we start to get a response
// {
// Sensor_Serial.write(readCO,9);
// delay(50);
// }
int timeout=0; //set a timeoute counter
while(Sensor_Serial.available() < 9 ) //Wait to get a 9 byte response
{
timeout++;
if(timeout > 10) //if it takes to long there was probably an error
{
while(Sensor_Serial.available()) //flush whatever we have
Sensor_Serial.read();
break; //exit and try again
}
delay(50);
}
for (int i=0; i < 9; i++)
{
response[i] = Sensor_Serial.read();
}
}
unsigned long getValue(byte packet[])
{
int high = packet[2]; //high byte for value is 3rd byte in packet in the packet
int low = packet[3]; //low byte for value is 4th byte in the packet
unsigned long val = high*256 + low; //Combine high byte and low byte with this formula to get value
return val* valMultiplier;
}
?!? The result of a digitalRead() will always be 0 (LOW) or 1 (HIGH). This is an obvious mistake.
It looks like your "response" packet contains 0xFF and 0xFF in 2 and 3 and that gets turned into 0xFFFFFFFF when returned as an unsigned long. I don't know why dtostrf() is putting 14 bytes into your buffer instead of 4 but your 'r' buffer is only 10 bytes long and that will cause errors. Why are you trying to display an unsigned long value as a three-character float?!?
Please read the comments after void loop for better understanding of my problem
// the setup routine runs once when you press reset:
#include "Adafruit_FONA.h"
#define FONA_TX 2
#define FONA_RX 3
#define FONA_RST 4
// this is a large buffer for replies
//char replybuffer[255];
char buffer[50];
char r[6];
// We default to using software serial. If you want to use hardware serial
// (because softserial isnt supported) comment out the following three lines
// and uncomment the HardwareSerial line
#include <SoftwareSerial.h>
SoftwareSerial fonaSS = SoftwareSerial(FONA_TX,FONA_RX);
SoftwareSerial *fonaSerial = &fonaSS;
SoftwareSerial Sensor_Serial(12,13);
// Hardware serial is also possible!
// HardwareSerial *fonaSerial = &Serial1;
// Use this for FONA 800 and 808s
//Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
// Use this one for FONA 3G
Adafruit_FONA_3G fona = Adafruit_FONA_3G(FONA_RST);
uint8_t readline(char *buff, uint8_t maxbuff, uint16_t timeout = 0);
uint8_t type;
byte readCO[] = {0xFF, 0X01, 0X86, 0X00, 0X00, 0X00, 0X00, 0X00,0X79}; //Command packet to read CO (see app note)
byte response[] = {0,0,0,0,0,0,0,0,0}; //create an array to store the response
//multiplier for value. default is 1.
int valMultiplier = 1;
void setup() {
while (!Serial);
Serial.begin(9600);
Sensor_Serial.begin(9600); //Opens the virtual serial port with a baud of 9600
Serial.println(F("FONA basic test"));
Serial.println(F("Initializing....(May take 3 seconds)"));
fonaSerial->begin(4800);
if (! fona.begin(*fonaSerial)) {
Serial.println(F("Couldn't find FONA"));
while (1);
}
type = fona.type();
Serial.println(F("FONA is OK"));
Serial.print(F("Found "));
switch (type) {
case FONA800L:
Serial.println(F("FONA 800L")); break;
case FONA800H:
Serial.println(F("FONA 800H")); break;
case FONA808_V1:
Serial.println(F("FONA 808 (v1)")); break;
case FONA808_V2:
Serial.println(F("FONA 808 (v2)")); break;
case FONA3G_A:
Serial.println(F("FONA 3G (American)")); break;
case FONA3G_E:
Serial.println(F("FONA 3G (European)")); break;
default:
Serial.println(F("???")); break;
}
}
void loop()
{
sendRequest(readCO);
unsigned long valCO = getValue(response);
static unsigned long startTime = 0;
if (valCO < 500)
dtostrf(valCO, 3, 2, r); // I don't know how to covert the unsigned long variable to string and I know //this part does the float to string conversion
sprintf(buffer, "%s High Level", r);// this part helps SEND SMS
Serial.print("CO = ");
Serial.println(valCO);
if (millis() - startTime > 1UL*60UL*1000UL) { // Has it been 1 minute since the value was below 500?
//sendAlert();
startTime = millis();
fona.sendSMS("0XXXXXXX", buffer);
}
}
void sendRequest(byte packet[])
{
while(!Sensor_Serial.available()) // If this part works the entire code works I think!!
//keep sending request until we start to get a response
{
//Sensor_Serial.write(readCO,9);
delay(50);
}
int timeout=0; //set a timeoute counter
while(Sensor_Serial.available() < 9 ) //Wait to get a 9 byte response
{
timeout++;
if(timeout > 10) //if it takes to long there was probably an error
{
while(Sensor_Serial.available()) //flush whatever we have
Sensor_Serial.read();
break; //exit and try again
}
delay(50);
}
for (int i=0; i < 9; i++)
{
response[i] = Sensor_Serial.read();
}
}
unsigned long getValue(byte packet[])
{
int high = packet[2]; //high byte for value is 3rd byte in packet in the packet
int low = packet[3]; //low byte for value is 4th byte in the packet
unsigned long val = high*256 + low; //Combine high byte and low byte with this formula to get value
return val* valMultiplier;
}
I forgot to edit that part of the code where I used digitalRead(valCO) but please ignore "digitalRead" its just valCO<500.
johnwasser:
Why are you trying to display an unsigned long value as a three-character float?!?
dtostrf(valCO, 3, 2, r); // I don't know how to covert the unsigned long variable to string and I know //this part does the float to string conversion
sprintf(buffer, "%s High Level", r);
I have used this part of the code for another program where my valCO was a float variable but here I'm using unsigned long variable for valCO. If I use float for valCO then OUTPUT: CO= ovf
My expected output range is 0-1000, so I think even if I use unsigned long it shouldn't be a problem but the program is somehow refusing to enter
void sendRequest(byte packet[])
{
while(!Sensor_Serial.available()) // If this part works the entire code works I think!!
//keep sending request until we start to get a response
{
Sensor_Serial.write(readCO,9);
delay(50);
}
Any fix for this as I think this part hold the key to my output..
unsigned long valCO = getValue(response);
static unsigned long startTime = 0;
if (valCO < 500)
dtostrf(valCO, 3, 2, r); // I don't know how to covert the unsigned long variable to string
Then you need to do some research or ask. Pretending that the long is an int, and adding two decimal places is stupid.
sprintf() is the sledgehammer to deal with this nail. ultoa() is the ball peen hammer.
I appreciate your time for posting comment @PaulS but I think the main problem is with the software serial ports. If I comment:
void sendRequest(byte packet[])
{
//while(!Sensor_Serial.available()) // If this part works the entire code works I think!!
//keep sending request until we start to get a response
// {
// Sensor_Serial.write(readCO,9);
// delay(50);
}
this part of the code its at least returning some error value for valCO. Well I can use float for my valCO:
float valCO = getValue(response);
static unsigned long startTime = 0;
if (valCO < 500)
dtostrf(valCO, 3, 2, r); // I don't know how to covert the unsigned long variable to string
sprintf(buffer, "%s High Level", r);
and as expected the code worked until printing the IMEI number ... How to better deal with software serial ports as at the moment I am trying to access both the software serial ports at the same time which I shouldn't be doing. I need my sensor and GSM to work simultaneously.
How do I use Sensor_Serial.listen() and fonaSerial->listen() as I need both the serial ports to work hand in hand?
I'm not sure what you mean by "hand in hand", but, if you are asking how to use listen() to listen to two different software serial ports at the same time, the answer is quite simple.
It would be most reliable if you could put one of those devices on the Serial pins. It looks like the sensor has a formatted read command, so it would ignore all the debug prints. You would have to temporarily disconnect the sensor TX pin from the Arduino RX pin 0 to upload new sketches over USB. Then connect the FONA to pins 8 & 9 and use AltSoftSerial instead of SoftwareSerial:
#define sensorPort Serial
AltSoftSerial fonaPort; // always 8 & 9 on an UNO
...
void sendRequest(byte packet[])
{
while(!sensorPort.available()) //keep sending request until we start to get a response
{
sensorPort.write(readC,9);
No data would be lost from the FONA while sending to or receiving from the sensor.
The next most reliable approach would be to use AltSoftSerial for the FONA and NeoSWSerial for the sensor:
NeoSWSerial sensorPort( 12, 13 );
AltSoftSerial fonaPort; // always 8 & 9 on an UNO
You could lose some data from the FONA while sending the read command to the sensor. No data from the FONA would be lost while receiving from the sensor.
There is no other combination of libraries that allows receiving from both devices at the same time, without losing data from one or the other device.
Both libraries are available from the Arduino IDE Library Manager, under the menu Sketch -> Include Library -> Manage Libraries.
Thanks @dev I tried the program using Serial1 for my sensor and its working perfectly!. I will take your suggestions in using AltSoftSerial and NeoSWSerial instead of serial for my program and will update the results of it.