I need data from IMU to be sent every 60ms and GPS every 3sec. For the IMU I send a request to the server every half second roughly. This means that I'm reading data eight times (8x60=480ms), inserting into a char array (that I prealocate in the beginning) then call send_request(). The size of the char array I'm allocating is 300, which is larger than my IMU worst case scenario data size (which is around 200 characters).
I tweaked the send_request function so I can send data in small packets (90 characters).
I am able to send data and read it but the problem I'm having is that the connection drops very frequently at random times (usually around a minute or less). I don't know if there is something to do but once I was able to collect data for almost 10min then it dropped. This test was done in a different network than the one I usually test, but the security was the same.
Looking at the arduino memory using free_ram, in all points I've placed it, the result was around 300. However, sometimes I have the led L on the arduino board flashing quickly and the reset button doesn't work - I have to unplug and plug the power back again. This strange behavior sometimes can be an indication of a memory issue, according to some post I've read, but I'm not sure.
Can you help me or give me any insight of what would be my issue? The program always freezes in the send_request function but in random points.
I appreciate any help.
Thanks
Code: Select all
/*
* Simple WiFi weather station with Arduino, the DHT11 sensor & the CC3000 chip
* Part of the code is based on the work done by Adafruit on the CC3000 chip & the DHT11 sensor
* Writtent by Marco Schwartz for Open Home Automation
*/
// Include required libraries
#include <Adafruit_CC3000.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_LSM303_U.h>
#include <Adafruit_L3GD20_U.h>
#include <Adafruit_9DOF.h>
#include <avr/wdt.h> // for watchdog timer
/*Assigning a unique ID to IMU sensors*/
Adafruit_LSM303_Accel_Unified accel = Adafruit_LSM303_Accel_Unified(30301);
Adafruit_L3GD20_Unified gyro = Adafruit_L3GD20_Unified(20);
//Adafruit_LSM303_Mag_Unified mag = Adafruit_LSM303_Mag_Unified(30302);
//********************************
// Define CC3000 chip pins
#define ADAFRUIT_CC3000_IRQ 2
#define ADAFRUIT_CC3000_VBAT 5
#define ADAFRUIT_CC3000_CS 10
// WiFi network (change with your settings !)
#define WLAN_SSID "BANNED" // cannot be longer than 32 characters!
#define WLAN_PASS "BANNED"
#define WLAN_SECURITY WLAN_SEC_WPA2 // This can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
// Create CC3000
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
SPI_CLOCK_DIV2);
// Local server IP, port, and repository (change with your settings !)
uint32_t ip = cc3000.IP2U32(10,1,10,62);
int port = 12345;
static unsigned long time=0; // IMU counter
static unsigned long time_gps=0; // GPS counter
int i=0;
int l=0;
static char data[300]; // Data buffer
static int counter = 0;
volatile int WD_counter; // for watchdog timer
volatile int countmax = 10; // Timer expires after...
// if 8 sec interval is selected below
// 8 x 10 = 80 sec...
// about 4 x the normal duration of 21 secs
void setup(void)
{
Serial.begin(9600);
// ***********************************
// Initialise the CC3000 module
if (!cc3000.begin())
{
while(1);
}
// Connect to WiFi network
cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY);
// Check DHCP
// Serial.println(F("Request DHCP"));
while (!cc3000.checkDHCP())
{
delay(100);
}
// **********************************
accel.begin();
gyro.begin();
}
void loop(void)
{
if(millis()-time>=60){ // IMU data collection every 60ms
time=millis();
// Serial.println(free_ram());
get_IMU(); // Function used to collect IMU data
i += 1;
watchdogEnable(); // Watchdog -> reset arduino if gets stuck
if(i == 8){ //Sending data every 484ms approx. 8->289 - 60
if(millis() - time_gps >= 3000){ // Collecting GPS data every 5min
get_GPS(); // Function to collect GPS data
time_gps = millis();
}
// Serial.println(free_ram());
send_request(); // Function to send data to website - cc3000
// Serial.println(free_ram());
counter = 0;
memset(data, 0, sizeof(data));
i=0;
}
}
}
// ******************************
// Function to send a TCP request and get the result as a string
void send_request (void) {
char temp[90];
int s = sizeof(data)/90;
char *temp1;
// Connect
Adafruit_CC3000_Client client = cc3000.connectTCP(ip, port);
// Send request and data transfer
if (client.connected()) {
client.fastrprint("GET /home/saveactivitydata/");
client.fastrprint("?data=");
for(int j=0; j<s; j++){ // For loop to brake data in small packets
strncpy(temp, data+(90*j), 90);
temp[90] = '\0';
temp1=temp;
client.fastrprint(temp1);
}
client.fastrprint("&id=1");
client.fastrprint(F("\r\n"));
// continue populating the http request header
client.fastrprint(F(" HTTP/1.1\r\nHost: "));
client.fastrprint(F("10.1.10.62:12345"));
client.fastrprint(F("\r\nUser-Agent: "));
client.fastrprint(F("CC3000_Wifi_Test"));
client.fastrprint(F("\r\nConnection: close\r\n"
"Content-Type: application/x-www-form-urlencoded;charset=UTF-8\r\n"
"Content-Length: "));
client.println(sizeof(data));
// Serial.println("Connected & Data sent");
}
else {
// Serial.println(F("Connection failed"));
}
while (client.connected()) {
while (client.available()) {
// Read answer
char c = client.read();
// Serial.print(c);
}
// Serial.println(F(" "));
}
client.close();
}
// ******************************
// Function to get IMU data
void get_IMU(void){
int dat;
String IMU="";
// Serial.println(free_ram());
sensors_event_t event;
accel.getEvent(&event);
// Serial.println(free_ram());
dat = 100*event.acceleration.x;
IMU+=String(dat)+";";
dat = 100*event.acceleration.y;
IMU+=String(dat)+";";
dat = 100*event.acceleration.z;
IMU+=String(dat)+";";
// Serial.println(free_ram());
gyro.getEvent(&event);
dat = 100*event.gyro.x;
IMU+=String(dat)+";";
dat = 100*event.gyro.y;
IMU+=String(dat)+";";
dat = 100*event.gyro.z;
IMU+=String(dat)+";";
// Serial.println(free_ram());
for (int k = 0; k < IMU.length(); k++){
data[counter] = IMU[k];
counter += 1;
}
// Serial.println(free_ram());
}
void get_GPS(void){
char temp_gps='\0';
l=0;
if(Serial.available()){
if(Serial.find("$GPGGA,")){
if(Serial.find(",")){
while(Serial.available()<24);
while(l<24){
temp_gps=Serial.read();
if(temp_gps=='.'){data[counter+l]=',';}
else if (temp_gps==','){data[counter+l]=';';}
else data[counter+l] = temp_gps;
l++;
data[counter+l]='\0';
}
}
}
}
}
void watchdogEnable()
{
WD_counter=0;
cli(); // disable interrupts
MCUSR = 0; // reset status register flags
// Put timer in interrupt-only mode:
WDTCSR |= 0b00011000; // Set WDCE (5th from left) and WDE (4th from left) to enter config mode,
// using bitwise OR assignment (leaves other bits unchanged).
WDTCSR = 0b01000000 | 0b100001; // set WDIE (interrupt enable...7th from left, on left side of bar)
// clr WDE (reset enable...4th from left)
// and set delay interval (right side of bar) to 8 seconds,
// using bitwise OR operator.
sei(); // re-enable interrupts
// delay interval patterns:
// 16 ms: 0b000000
// 500 ms: 0b000101
// 1 second: 0b000110
// 2 seconds: 0b000111
// 4 seconds: 0b100000
// 8 seconds: 0b100001
}
ISR(WDT_vect) // watchdog timer interrupt service routine
{
WD_counter+=1;
if (WD_counter < countmax)
{
wdt_reset(); // start timer again (in interrupt-only mode)
}
else // then change timer to reset-only mode with short (16 ms) fuse
{
MCUSR = 0; // reset flags
// Put timer in reset-only mode:
WDTCSR |= 0b00011000; // Enter config mode.
WDTCSR = 0b00001000 | 0b000000; // clr WDIE (interrupt enable...7th from left)
// set WDE (reset enable...4th from left), and set delay interval
// reset system in 16 ms...
// unless wdt_disable() in loop() is reached first
}
}
// Function to measure ram size
//int free_ram ()
//{
// extern int __heap_start, *__brkval;
// int v;
// return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
//}