@Carl
I tried this code with a CC3000 Shield from Adafruit and an Arduino Uno. The code easily allows you to add 3, 4, 5 and up to 6 variables to your request; just move the “/" and "/” lines in the “save_values” function to uncomment the needed variables:
**** As you can see in the code, your “Example A” is the right way to send a collection"****
/***************************************************
Based on the example from Adafruit's CC3000 Library
****************************************************/
/*
This example was built to find out how many Ubidots variables can be updated in a single request using the CC3000.
*/
#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
#include "utility/debug.h"
// These are the interrupt and control pins
#define ADAFRUIT_CC3000_IRQ 3 // MUST be an interrupt pin!
// These can be any two pins
#define ADAFRUIT_CC3000_VBAT 5
#define ADAFRUIT_CC3000_CS 10
// Use hardware SPI for the remaining pins
// On an UNO, SCK = 13, MISO = 12, and MOSI = 11
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
SPI_CLOCK_DIVIDER); // you can change this clock speed
#define WLAN_SSID "OpenWRT" // cannot be longer than 32 characters!
#define WLAN_PASS "123456789"
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define WLAN_SECURITY WLAN_SEC_WPA2
#define IDLE_TIMEOUT_MS 3000 // Amount of time to wait (in milliseconds) with no data
// received before closing the connection. If you know the server
// you're accessing is quick to respond, you can reduce this value.
////////////////////////////////////// Ubidots parameters
#define WEBSITE "things.ubidots.com"
#define URL "/api/v1.6/collections/values/?token=BDHq8DFi9dcaake6ABF5fkvJk2EWF3&force=true"
#define idvariable1 "568a84237625420e53b118d9"
#define idvariable2 "569133c976254212f0064733"
#define idvariable3 "569133cd762542111c03f057"
#define idvariable4 "569133d2762542111c03f06d"
#define idvariable5 "569133d776254212673e7a19"
#define idvariable6 "569133de762542111c03f0b6"
char payload[360]; // Reserve a char to store the data to send. Account for ~60 bytes per variable.
char le[4];
/**************************************************************************/
/*!
@brief Sets up the HW and the CC3000 module (called automatically
on startup)
*/
/**************************************************************************/
uint32_t ip;
void setup(void)
{
Serial.begin(115200);
Serial.println(F("Hello, CC3000!\n"));
Serial.print("Free RAM: "); Serial.println(getFreeRam(), DEC);
/* Initialise the module */
Serial.println(F("\nInitializing..."));
if (!cc3000.begin())
{
Serial.println(F("Couldn't begin()! Check your wiring?"));
while(1);
}
// Optional SSID scan
// listSSIDResults();
Serial.print(F("\nAttempting to connect to ")); Serial.println(WLAN_SSID);
if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
Serial.println(F("Failed!"));
while(1);
}
Serial.println(F("Connected!"));
/* Wait for DHCP to complete */
Serial.println(F("Request DHCP"));
while (!cc3000.checkDHCP())
{
delay(100); // ToDo: Insert a DHCP timeout!
}
/* Display the IP address DNS, Gateway, etc. */
while (! displayConnectionDetails()) {
delay(1000);
}
ip = 0;
// Try looking up the website's IP address
Serial.print(WEBSITE); Serial.print(F(" -> "));
while (ip == 0) {
if (! cc3000.getHostByName(WEBSITE, &ip)) {
Serial.println(F("Couldn't resolve!"));
}
delay(500);
}
cc3000.printIPdotsRev(ip);
}
void loop(void)
{
save_values(analogRead(A0), analogRead(A1), analogRead(A2), analogRead(A3), analogRead(A4), analogRead(A5));
delay(4000);
}
void save_values(int val0, int val1, int val2, int val3, int val4, int val5){
Serial.println("Free RAM: "); Serial.println(getFreeRam(), DEC);
// Prepare payload to send to server - using "sprintf" instead of String concatenation to avoid memory issues
Serial.println(F("Setting up payload..."));
sprintf(payload,"%s", "[");
sprintf(payload,"%s%s", payload, "{\"variable\":\"" idvariable1 "\",\"value\":");
sprintf(payload,"%s%d", payload, val0);
/*
sprintf(payload,"%s%s", payload, "},{\"variable\":\"" idvariable2 "\",\"value\":");
sprintf(payload,"%s%d", payload, val1);
sprintf(payload,"%s%s", payload, "},{\"variable\":\"" idvariable3 "\",\"value\":");
sprintf(payload,"%s%d", payload, val2);
sprintf(payload,"%s%s", payload, "},{\"variable\":\"" idvariable4 "\",\"value\":");
sprintf(payload,"%s%d", payload, val3);
sprintf(payload,"%s%s", payload, "},{\"variable\":\"" idvariable5 "\",\"value\":");
sprintf(payload,"%s%d", payload, val4);
sprintf(payload,"%s%s", payload, "},{\"variable\":\"" idvariable6 "\",\"value\":");
sprintf(payload,"%s%d", payload, val5);
*/
sprintf(payload,"%s%s", payload, "}]");
// Get length of the entire payload
sprintf(le,"%d", strlen(payload));
Serial.println(F("Done! Payload: "));
Serial.println(payload);
Serial.println(F("Length: "));
Serial.println(le);
Serial.println(F("Connecting to Ubidots..."));
Adafruit_CC3000_Client www = cc3000.connectTCP(ip, 80);
if (www.connected()) {
Serial.println(F("Making request..."));
Serial.print(F("POST "));
Serial.print(URL);
Serial.print(F(" HTTP/1.1\r\n"));
Serial.print(F("Content-Type: application/json\r\n"));
Serial.print(F("Connection: close\r\n"));
Serial.print(F("Host: "));
Serial.print(WEBSITE);
Serial.print(F("\r\n"));
Serial.print(F("Content-Length: "));
Serial.print(le);
Serial.print(F("\r\n"));
Serial.print(F("\r\n"));
Serial.print(payload);
Serial.print(F("\r\n"));
Serial.println();
www.fastrprint(F("POST "));
www.fastrprint(URL);
www.fastrprint(F(" HTTP/1.1\r\n"));
www.fastrprint(F("Content-Type: application/json\r\n"));
www.fastrprint(F("Connection: close\r\n"));
www.fastrprint(F("Host: "));
www.fastrprint(WEBSITE);
www.fastrprint(F("\r\n"));
www.fastrprint(F("Content-Length: "));
www.fastrprint(le);
www.fastrprint(F("\r\n"));
www.fastrprint(F("\r\n"));
www.fastrprint(payload);
www.fastrprint(F("\r\n"));
www.println();
} else {
Serial.println(F("Connection failed"));
return;
}
Serial.println(F("-------------------------------------"));
/* Read data until either the connection is closed, or the idle timeout is reached. */
unsigned long lastRead = millis();
while (www.connected() && (millis() - lastRead < IDLE_TIMEOUT_MS)) {
while (www.available()) {
char c = www.read();
Serial.print(c);
lastRead = millis();
}
}
www.close();
Serial.println(F("-------------------------------------"));
/* You need to make sure to clean up after yourself or the CC3000 can freak out */
/* the next time your try to connect ... */
memset(payload, 0, sizeof(payload));
}
/**************************************************************************/
/*!
@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;
}
}
After testing, I found that the CC3000 starts to block when sending/receiving larger amounts of data. This is also mentioned in Adafruits forums (http://forums.adafruit.com/viewtopic.php?f=31&p=273395):
As far as fixing this unfortunately I don’t think there’s any easy solution. You could bump up the size of the RX buffer by changing the CC3000_MINIMAL_RX_SIZE define in cc3000_common.h, but it will take more memory from your sketch. It’s annoying that the code halts when large data is received but it prevents an overflow that would cause weird, undefined behavior.
If you have control over what’s sending data to the Arduino, I would try to keep the max data it sends below ~90 bytes (i.e. break things up into a lot of smaller packets). If you don’t have control of it and need to receive a large amount of data you might look at using a mega or due–the due in particular has a lot of memory and could increase the buffer quite a bit (perhaps 20-50kb or more).
tdicola
Posts: 976
Joined: Thu Oct 17, 2013 9:11 pm
So my advise would be to:
-
Try this code with the Mega to find the limit of variables that can be sent at the same time.
-
Modify the “save_values” function to receive variable IDs and the amount of supported values. For example, if you could send only 3 values at the same time, the function would look like:
void save_values(String idvariable1, String idvariable2, String idvariable3, int val1, int val2, int val3){ …
-
In the main loop, call this function as many times as needed, for example:
save_values( idvariable1, idvariable2, idvariable3, analogRead(A0), analogRead(A1), analogRead(A2));
save_values( idvariable4, idvariable5, idvariable5, analogRead(A3), analogRead(A4), analogRead(A5));