Thanks Pavel. Please find enclosed cleaned code. Still can to get the “sendUtime delay” to work properly. Just does not change. I have a reading on the App that displays Virtual pin 5 and a graph that displays AnalogPins 0 and 1 through virtual pins 1 and 2.
I want to avoid too much data.
I am also recording the UnixTime and the VWC values on the SD card and is working fine but the Arduino/CC3000 often disconnect and reconnect fine but sometimes they just hang and I need to restart the Arduino and the App.
Here is the code within the ~~~ and also </>.
Appreciate your help.
~~~
/*
SD card datalogger with internet NTP time updated every 24hrs.
This example shows how to log data from three analog sensors
to an SD card using the SD library.
The circuit:
* analog sensors on analog ins 0, 1, and 2
* SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 4
*/
// These are the interrupt and control pins
#define ADAFRUIT_CC3000_IRQ 3
#define ADAFRUIT_CC3000_VBAT 5
#define ADAFRUIT_CC3000_CS 10 //10 for WiFi, 4 for SD//
#define BLYNK_PRINT Serial // #define BLYNK_PRINT Serial // Comment this out to disable prints and save space
//#define BLYNK_DEBUG // Optional, this enables lots of prints
#define WLAN_SSID "JHLW"
#define WLAN_PASS "ZbyszZdzislaw"
#define WLAN_SECURITY WLAN_SEC_WPA2
char auth[] = "2ac207956d4140e8b17ddda8f4438b27"; //
#include <SPI.h>
#include <SD.h>
#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <Time.h>
#include <BlynkSimpleCC3000.h>
#include <WidgetSD.h>
#include <SimpleTimer.h>
//Required for NTP time to be updated every 24hrs for SD logger
Adafruit_CC3000_Client client;
const unsigned long
connectTimeout = 15L * 1000L, // Max time to wait for server connection
responseTimeout = 15L * 1000L; // Max time to wait for data from server
int
countdown = 0; // loop() iterations until next time server query
unsigned long
lastPolledTime = 0L, // Last value retrieved from time server
sketchTime = 0L; // CPU milliseconds since last server query
/*
//Attempt at having Sleep power save to create delay.
#define SERVER_IP 045, 055, 195, 102 // Logging server IP address. Note that this
// should be separated with commas and NOT periods!
#define SERVER_PORT 8442 // Logging server listening port.
#define MAX_SLEEP_ITERATIONS LOGGING_FREQ_SECONDS / 8 // Number of times to sleep (for 8 seconds) before
// a sensor reading is taken and sent to the server.
// Don't change this unless you also change the
// watchdog timer configuration.
// Heartbeat period in seconds.
#define BLYNK_HEARTBEAT 60// default 10
// Internal state used by the sketch.
//Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT);
int sleepIterations = 0;
uint32_t ip;
volatile bool watchdogActivated = false;
// Define watchdog timer interrupt.
ISR(WDT_vect)
{
// Set the watchdog activated flag.
// Note that you shouldn't do much work inside an interrupt handler.
watchdogActivated = true;
}
*/
WidgetSD sd;
BLYNK_ATTACH_WIDGET(sd, 1);
int chipSelect = 10; //4 for SD
// Setup a function to be called every second for sendUptime that does NOT work
SimpleTimer timer;
const int sensorsConnected = 2; //number of sensors
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
Blynk.begin(auth, "JHLW", "ZbyszZdzislaw", WLAN_SEC_WPA2); // Here your Arduino connects to the Blynk Cloud.
#define BLYNK_DEBUG // Optional, this enables lots of prints
// Setup a function to be called every second
timer.setInterval(1000L, sendUptime);
//Script to confirm Arduino/CC3000 working.
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(4)) {
Serial.println("Card failed, or not present");
// don't do anything more:
return;
}
Serial.println("card initialized.");
//WiFi connect
Serial.println(F("Hello, CC3000!\n"));
displayDriverMode();
Serial.println(F("\nInitialising the CC3000 ..."));
if (!cc3000.begin()) {
Serial.println(F("Unable to initialise the CC3000! Check your wiring?"));
for (;;);
}
uint16_t firmware = checkFirmwareVersion();
if (firmware < 0x113) {
Serial.println(F("Wrong firmware version!"));
for (;;);
}
displayMACAddress();
}
// This function sends Arduino's up time every second to Virtual Pin (5).
// In the app, Widget's reading frequency should be set to PUSH. This means
// that you define how often to send data to Blynk App. NOT WORKING TRIED for 60secs
void sendUptime()
{
// You can send any value at any time.
// Please don't send more that 10 values per second.
Blynk.virtualWrite(5, (millis() / 60000) );
}
void loop() {
Blynk.run(); // All the Blynk Magic happens here...
timer.run(); // Initiates SimpleTimer
// To reduce load on NTP servers, time is polled once per roughly 24 hour period.
// Otherwise use millis() to estimate time since last query. Plenty accurate.
if (countdown == 0) { // Time's up?
unsigned long t = getTime(); // Query time server
if (t) { // Success?
lastPolledTime = t; // Save time
sketchTime = millis(); // Save sketch time of last valid time query
countdown = 24 * 60 * 4 - 1; // Reset counter: 24 hours * 15-second intervals
}
} else {
countdown--; // Don't poll; use math to figure current time
}
//Read sensor data and prepare for Blynking and sending to SD card.
unsigned long currentTime = lastPolledTime + (millis() - sketchTime) / 1000;
// make a string for assembling the data to log:
String dataString = "";
dataString += String(currentTime);
dataString += ",";
// read three sensors and append to the string:
for (int analogPin = 0; analogPin < (sensorsConnected); analogPin++) {
float sensorValue = analogRead(analogPin);
float volt = (sensorValue / 1024.0) * 5.00 * 1.01 ; //Ref 5V
int VWC = 0;
//Volumetric Water Content is a piecewise function of the voltage from the sensor
if (volt < 0.00001 ) {
VWC = 0;
}
else if (volt < 1.1) {
VWC = (10 * volt) - 1;
}
else if (volt < 1.3) {
VWC = (25 * volt) - 17.5;
}
else if (volt < 1.82) {
VWC = (48.08 * volt) - 47.5;
}
else if (volt < 2.2) {
VWC = (26.32 * volt) - 7.89;
}
else {
VWC = (62.5 * volt) - 87.5;
}
dataString += String(VWC);
if (analogPin < (sensorsConnected - 1)) {
dataString += "%,";
}
else if (analogPin < (sensorsConnected)) {
dataString += "%";
}
Blynk.virtualWrite(1, VWC);
Blynk.virtualWrite(2, VWC);
Blynk.virtualWrite(3, volt);
Blynk.virtualWrite(7, millis() / 60000);
}
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
File dataFile = SD.open("datalog.csv", FILE_WRITE);
// if the file is available, write to it:
if (dataFile) {
dataFile.println(dataString);
dataFile.close();
// print to the serial port too:
Serial.println(dataString);
}
// if the file isn't open, pop up an error:
else {
Serial.println("error opening datalog.csv");
}
//delay(15000L);// Delay tried for delaying sendUptime but cc3000 times out and
//Blynk app stops working
}
//
//Scripts below provide MACROS for checking state of HARDWARE.
//
//
//-------------------------------------------------------------------------/
/*!
@brief Displays the driver mode (tiny of normal), and the buffer
size if tiny mode is not being used
@note The buffer size and driver mode are defined in cc3000_common.h
*/
//-------------------------------------------------------------------------/
void displayDriverMode(void)
{
#ifdef CC3000_TINY_DRIVER
Serial.println(F("CC3000 is configure in 'Tiny' mode"));
#else
Serial.print(F("RX Buffer : "));
Serial.print(CC3000_RX_BUFFER_SIZE);
Serial.println(F(" bytes"));
Serial.print(F("TX Buffer : "));
Serial.print(CC3000_TX_BUFFER_SIZE);
Serial.println(F(" bytes"));
#endif
}
//-------------------------------------------------------------------------/
/*!
@brief Tries to read the CC3000's internal firmware patch ID
*/
//-------------------------------------------------------------------------/
uint16_t checkFirmwareVersion(void)
{
uint8_t major, minor;
uint16_t version;
#ifndef CC3000_TINY_DRIVER
if (!cc3000.getFirmwareVersion(&major, &minor))
{
Serial.println(F("Unable to retrieve the firmware version!\r\n"));
version = 0;
}
else
{
Serial.print(F("Firmware V. : "));
Serial.print(major); Serial.print(F(".")); Serial.println(minor);
version = major; version <<= 8; version |= minor;
}
#endif
return version;
}
//-------------------------------------------------------------------------/
/*!
@brief Tries to read the 6-byte MAC address of the CC3000 module
*/
//-------------------------------------------------------------------------/
void displayMACAddress(void)
{
uint8_t macAddress[6];
if (!cc3000.getMacAddress(macAddress))
{
Serial.println(F("Unable to retrieve MAC Address!\r\n"));
}
else
{
Serial.print(F("MAC Address : "));
cc3000.printHex((byte*)&macAddress, 6);
}
}
//-------------------------------------------------------------------------/
/*!
@brief Tries to read the IP address and other connection details
*/
//-------------------------------------------------------------------------/
bool displayConnectionDetails(void)
{
uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;
if (!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))
{
Serial.println(F("Unable to retrieve the IP Address!\r\n"));
return false;
}
else
{
Serial.print(F("\nIP Addr: ")); cc3000.printIPdotsRev(ipAddress);
Serial.print(F("\nNetmask: ")); cc3000.printIPdotsRev(netmask);
Serial.print(F("\nGateway: ")); cc3000.printIPdotsRev(gateway);
Serial.print(F("\nDHCPsrv: ")); cc3000.printIPdotsRev(dhcpserv);
Serial.print(F("\nDNSserv: ")); cc3000.printIPdotsRev(dnsserv);
Serial.println();
return true;
}
}
// Minimalist time server query; adapted from Adafruit Gutenbird sketch,
// which in turn has roots in Arduino UdpNTPClient tutorial.
unsigned long getTime(void) {
uint8_t buf[48];
unsigned long ip, startTime, t = 0L;
Serial.print(F("Locating time server..."));
// Hostname to IP lookup; use NTP pool (rotates through servers)
if (cc3000.getHostByName("pool.ntp.org", &ip)) {
static const char PROGMEM
timeReqA[] = { 227, 0, 6, 236 },
timeReqB[] = { 49, 78, 49, 52 };
Serial.println(F("\r\nAttempting connection..."));
startTime = millis();
do {
client = cc3000.connectUDP(ip, 123);
} while ((!client.connected()) &&
((millis() - startTime) < connectTimeout));
if (client.connected()) {
Serial.print(F("connected!\r\nIssuing request..."));
// Assemble and issue request packet
memset(buf, 0, sizeof(buf));
memcpy_P( buf , timeReqA, sizeof(timeReqA));
memcpy_P(&buf[12], timeReqB, sizeof(timeReqB));
client.write(buf, sizeof(buf));
Serial.print(F("\r\nAwaiting response..."));
memset(buf, 0, sizeof(buf));
startTime = millis();
while ((!client.available()) &&
((millis() - startTime) < responseTimeout));
if (client.available()) {
client.read(buf, sizeof(buf));
t = (((unsigned long)buf[40] << 24) |
((unsigned long)buf[41] << 16) |
((unsigned long)buf[42] << 8) |
(unsigned long)buf[43]) - 2208988800UL;
Serial.print(F("OK\r\n"));
}
client.close();
}
}
if (!t) Serial.println(F("error"));
return t;
}
//Attempted script to display time in Human Time but decided against a changing from LONG time to other time loses accuracy.
void digitalClockDisplay() {
// digital clock display of the time
printHrs(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
Serial.print(day());
Serial.print(" ");
Serial.print(month());
Serial.print(" ");
Serial.print(year());
Serial.println();
}
void printHrs(int digits) {
// utility for digital clock display: prints preceding colon and leading 0
if (digits < 10)
Serial.print('0');
Serial.print(digits);
}
void printDigits(int digits) {
// utility for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if (digits < 10)
Serial.print('0');
Serial.print(digits);
}
// This function is used by Blynk to receive data
size_t BlynkStreamRead(void* buf, size_t len)
{
return Serial.readBytes((byte*)buf, len);
}
// This function is used by Blynk to send data
size_t BlynkStreamWrite(const void* buf, size_t len)
{
return Serial.write((byte*)buf, len);
}
~~~