in order to do that, i need to use the SDU library.
The SDU library complains :
“error unsupported board”
I rebuild the boot/xxxxxx.h
files, using the build.sh
file under extras
. Unfortunately, I still dont see any update. Forcing the SDU library to choose ARDUINO_SAMD_ZERO , for example does not work.
Here is my Sketch :
// define Battery Sensor
#define ADC_AREF 3.3f
#define BATVOLT_R1 4.7f
#define BATVOLT_R2 10.0f
#define BATVOLT_PIN BAT_VOLT
// ##############################################
// define outputs
// ----------------------------------------------
// define SDCARD
//#include "FS.h"
#include "SD.h"
#include <SPI.h>
#define SD_CS 10
#define SD_SCLK 13
#define SD_MISO 12
#define SD_MOSI 11
// define Server
// define EEPROM
#include "FlashStorage.h"
FlashStorage(wakeup, int);
int wakeUpCnt = 0;
// ----------------------------------------------
// ##############################################
// define bridge / conns
// ----------------------------------------------
// define LTE
#include <Arduino.h>
#include "Sodaq_R4X.h"
#include "Sodaq_wdt.h"
#define powerPin SARA_ENABLE
#define enablePin SARA_TX_ENABLE
static Sodaq_R4X r4x;
static Sodaq_SARA_R4XX_OnOff saraR4xxOnOff;
bool modemstat = false;
uint32_t getNow();
const int urat = 7; // LTE Cat 1 dual mode not possible
const int cid = 1 ; // cell id set to 1
const int mnoProfile = 31; // Deutsche Telekom
const int bandmask = 524420;
const int bandmaskRATind = 0;
const char * FOperator = "20404";
const char* APN = "";
const char* gprsUser = "";
const char* gprsPass = "";
#define MODEMBAUD 115200
#define R4XX // Uncomment when you use the ublox R4XX module
/* SODAQ SARA */
#define DEBUG_STREAM SerialUSB
#define MODEM_STREAM Serial1
#define powerPin SARA_ENABLE
#define enablePin SARA_TX_ENABLE
#define NETWORK_STATUS_GPIO_ID 16
#define TINY_GSM_MODEM_SARAR4 // Modem is SARA R4
#define TINY_GSM_RX_BUFFER 2048 // Set RX buffer to 1Kb
#include <TinyGsmClient.h>
#define TINY_GSM_DEBUG
#define TINY_GSM_TEST_GPRS true
#define TINY_GSM_TEST_GPS true
#define TINY_GSM_POWERDOWN true
TinyGsm modemGSM(MODEM_STREAM);
TinyGsmClient client(modemGSM);
int uploadedFlag = 0;
// define server
const char server[] = "78.47.186.254"; // domain name: example.com, maker.ifttt.com, etc
const char authURL[] = "/auth"; // resource path, for example: /post-data.php
const char sodaqUploadPath[] = "/upload"; // new function for sodaq upload, does not touch the other one
const int port = 5504;
// define fallback
// ----------------------------------------------
#define ARDUINO_SAMD_MKR1000
#include "SDU.h"
#if defined(ARDUINO_SAMD_ZERO)
#define BOARD "arduino_zero_edbg"
#elif defined(ARDUINO_SAMD_MKR1000)
#define BOARD "mkr1000"
#elif defined(ARDUINO_SAMD_MKRZERO)
#define BOARD "mkrzero"
#else
#error "Unsupported board!"
#endif
#define BOARD_LENGTH (sizeof(BOARD) - 1)
const uint32_t RESPONSE_TIMEOUT_MS = 5000;
const int updatePort = 4402;
// ##############################################
// define controls
#include "LedColor.h"
int wakeupCause = 0;
int debuglevel = 0;
#define CONSOLE_STREAM SerialUSB
#define CONSOLE_BAUD 115200
static uint8_t lastResetCause;
#define PROJECT_NAME "SODAQ - GPS Tracker Webaro"
#define VERSION "1.8"
#define STARTUP_DELAY 5000
bool uploadAborted;
int wpCounter = 1;
/*
*
* debuglevel = 0, say nothing
* debuglevel = 1, draw
* debuglevel = 2, text
*/
// ----------------------------------------------
// define dev configs
String devID = "GPS320024";
String fileID = "";
String authKEY = "uaVZHB67r55BfgjkikhFUZ64489533g6311GRDI908740HDWWlaykdtw2446jdsg";
// ##############################################
// define GSM functions
// ----------------------------------------------
// ##############################################
// ----------------------------------------------
// ##############################################
// define SERVER-CLIENT operation functions
// ----------------------------------------------
// ##############################################
// define EEPROM functions
void activate_EEPROM() {
wakeUpCnt = wakeup.read();
++wakeUpCnt ; SerialUSB.print("Wake up counter at: ");SerialUSB.println(wakeUpCnt);
wakeup.write(wakeUpCnt);
}
// ----------------------------------------------
// ##############################################
// define SDC functions
void init_SDC() {
Sd2Card card;
SdVolume volume;
SdFile root;
SerialUSB.print("\nInitializing SD card...");
// we'll use the initialization code from the utility libraries
// since we're just testing if the card is working!
if (!card.init(SPI_HALF_SPEED, SD_CS)) { SerialUSB.println("initialization failed. Things to check:");
SerialUSB.println("* is a card inserted?");
SerialUSB.println("* is your wiring correct?");
SerialUSB.println("* did you change the chipSelect pin to match your shield or module?");
while (1);
} else { SerialUSB.println("Wiring is correct and a card is present.");
}
// print the type of card
SerialUSB.println();
SerialUSB.print("Card type: ");
switch (card.type()) {
case SD_CARD_TYPE_SD1: SerialUSB.println("SD1");
break;
case SD_CARD_TYPE_SD2: SerialUSB.println("SD2");
break;
case SD_CARD_TYPE_SDHC: SerialUSB.println("SDHC");
break;
default: SerialUSB.println("Unknown");
}
// Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
while (!volume.init(card)) { SerialUSB.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
}
SerialUSB.print("Clusters: ");
SerialUSB.println(volume.clusterCount());
SerialUSB.print("Blocks x Cluster: ");
SerialUSB.println(volume.blocksPerCluster());
SerialUSB.print("Total Blocks: ");
SerialUSB.println(volume.blocksPerCluster() * volume.clusterCount());
SerialUSB.println();
// print the type and size of the first FAT-type volume
uint32_t volumesize; SerialUSB.print("Volume type is: FAT");
SerialUSB.println(volume.fatType(), DEC);
volumesize = volume.blocksPerCluster(); // clusters are collections of blocks
volumesize *= volume.clusterCount(); // we'll have a lot of clusters
volumesize /= 2; // SD card blocks are always 512 bytes (2 blocks are 1KB)
SerialUSB.print("Volume size (Kb): ");
SerialUSB.println(volumesize);
}
// ----------------------------------------------
// ##############################################
// define ACCEL functions
bool initialize_wakeUp() { return true;}
// ----------------------------------------------
// ##############################################
// define SENSOR functions
// ----------------------------------------------
// ##############################################
// define GPS functions
// ----------------------------------------------
// ##############################################
// define timer functions
long lastTickTime;
long sleepTime = 600;
// ----------------------------------------------
void setup() {
CONSOLE_STREAM.begin(CONSOLE_BAUD);
lastResetCause = PM->RCAUSE.reg; debug2(String(lastResetCause));
// In case of reset (this is probably unnecessary)
sodaq_wdt_disable();
// Setup the BOD33
//setupBOD33();
//sodaq_wdt_enable(WDT_PERIOD_8X);
//sodaq_wdt_reset();
sodaq_wdt_safe_delay(STARTUP_DELAY);
printBootUpMessage(CONSOLE_STREAM);
//Serial.begin(115200); /** set serial output **/
// CONSOLE_STREAM.println("waiting...");
//while(!CONSOLE_STREAM.available()); // wait until get debug level
debuglevel = 2;//CONSOLE_STREAM.parseInt(); // parse as integer
CONSOLE_STREAM.println(debuglevel);
// get_wakeupReason() // already set via callbacks
switch(wakeupCause) { // branch wakeup reason
case 0: // FIRST POWER UP
activate_initialProtocol();
break;
case 1: // ACCELEROMETER trigger
//activate_standardProtocol();
break;
case 2: // timer expired
//activate_sporadicProtocol();
break;
}
// shutdown_Peripherals(); // send unnecessary components to sleep
// activate_sensors();
lastTickTime = millis();
}
void activate_initialProtocol() {
bool initialized_wakeUP = initialize_wakeUp();
if (! initialized_wakeUP) return;
setLedColor(YELLOW);
sodaq_wdt_safe_delay(650);
init_SDC();
setLedColor(CYAN);
sodaq_wdt_safe_delay(650);
debug2("handling update ...");
sodaq_wdt_safe_delay(5000);
}
void handleUpdate() {
/*
bool isValidContentType = false;
const char* PATH = "http://78.47.186.254:4402/update.bin";
const unsigned long CHECK_INTERVAL = 5000;
if (!modemGSM.gprsConnect(APN, gprsUser, gprsPass)) { debug2(" fail apn");
} else {
if (!client.connect(server, updatePort)) { debug2("Cannot connect to " + String(server));
return;
}
}
client.print(String("GET ") + PATH + " HTTP/1.1\r\n");
client.print(String("Host: ") + server + "\r\n");
client.print("Connection: close\r\n\r\n");
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > RESPONSE_TIMEOUT_MS) { debug2("Client Timeout !");
client.stop();
return;
}
}
if(!SD.begin(SD_CS)) { debug2("SD FAILURE ::: ");
return;
}
File file = SD.open(BIN_FILENAME, O_CREAT | O_WRITE);
if (!file) {
client.stop(); debug2("Could not create bin file. Can't continue with update.");
return;
}
const uint32_t clientReadTimeout = 5000;
uint32_t clientReadStartTime = millis();
String headerBuffer;
bool finishedHeader = false;
uint32_t contentLength = 0;
uint32_t knownFileSize = 1024;
uint32_t timeElapsed = millis();
while (!finishedHeader) {
int nlPos;
if (client.available()) {
clientReadStartTime = millis();
while (client.available()) {
char c = client.read();
headerBuffer += c;
// Uncomment the lines below to see the data coming into the buffer
if (c < 16)
//SerialUSB.print('0');
//SerialUSB.print(c, HEX);
//SerialUSB.print(' ');
if (isprint(c))
SerialUSB.print(reinterpret_cast<char> (c));
else
SerialUSB.print('*');
SerialUSB.print(' ');
// Let's exit and process if we find a new line
if (headerBuffer.indexOf(F("\r\n")) >= 0)
break;
}
}
else {
if (millis() - clientReadStartTime > clientReadTimeout) {
// Time-out waiting for data from client
SerialUSB.println(F(">>> Client Timeout !"));
break;
}
}
// See if we have a new line.
nlPos = headerBuffer.indexOf(F("\r\n"));
if (nlPos > 0) {
headerBuffer.toLowerCase();
// Check if line contains content-length
if (headerBuffer.startsWith(F("content-length:"))) {
contentLength = headerBuffer.substring(headerBuffer.indexOf(':') + 1).toInt();
SerialUSB.print(F("Got Content Length: ")); // uncomment for
SerialUSB.println(contentLength); // confirmation
}
headerBuffer.remove(0, nlPos + 2); // remove the line
}
else if (nlPos == 0) {
// if the new line is empty (i.e. "\r\n" is at the beginning of the line), we are done with the header.
finishedHeader = true;
}
}
// The two cases which are not managed properly are as follows:
// 1. The client doesn't provide data quickly enough to keep up with this loop.
// 2. If the client data is segmented in the middle of the 'Content-Length: ' header,
// then that header may be missed/damaged.
//
uint32_t readLength = 0;
if (finishedHeader && contentLength == knownFileSize) {
SerialUSB.println(F("Reading response data"));
clientReadStartTime = millis();
printPercent(readLength, contentLength);
while (readLength < contentLength && client.connected() && millis() - clientReadStartTime < clientReadTimeout) {
while (client.available()) {
uint8_t c = client.read();
SerialUSB.print((c)); // Uncomment this to show data
readLength++;
if (readLength % (contentLength / 13) == 0) {
printPercent(readLength, contentLength);
}
clientReadStartTime = millis();
}
}
printPercent(readLength, contentLength);
}
timeElapsed = millis() - timeElapsed;
SerialUSB.println();
file.close();
client.stop();
*/
#ifdef __AVR__
wdt_enable(WDTO_15MS);
while (true);
#else
NVIC_SystemReset();
#endif
// if (contentLength && isValidContentType) {
//
//
// }
}
void loop() {
for(int i = 0; i < 10; i ++) { debug2(String(i) + "/10");
setLedColor(GREEN);
sodaq_wdt_safe_delay(1000);
setLedColor(RED);
sodaq_wdt_safe_delay(1000);
} debug2("handling update ");
handleUpdate();
}
void setLONG_LedColor_(LedColor color) {
setLedColor(color);
sodaq_wdt_safe_delay(3000);
}
void debug2(String s) {
if (debuglevel == 2){ CONSOLE_STREAM.println(s);}
}
void debug3(String f) {
if (debuglevel == 3){ CONSOLE_STREAM.println(f);}
}
static void printBootUpMessage(Stream& stream) {
stream.println("** " PROJECT_NAME " - " VERSION " **");
stream.println();
stream.print(" -> ");
printCpuResetCause(stream);
stream.println();
}
static void printCpuResetCause(Stream& stream){
stream.print("CPU reset by");
if (PM->RCAUSE.bit.SYST) {
stream.print(" System reset request was performed, e.g. by rebooting....");
}
// Syntax error due to #define WDT in CMSIS/4.0.0-atmel/Device/ATMEL/samd21/include/samd21j18a.h
// if (PM->RCAUSE.bit.WDT) {
if ((PM->RCAUSE.reg & PM_RCAUSE_WDT) != 0) {
stream.print(" Watchdog");
}
if (PM->RCAUSE.bit.EXT) {
stream.print(" External - expect this for the accelerometer ");
}
if (PM->RCAUSE.bit.BOD33) {
stream.print(" BOD33");
}
if (PM->RCAUSE.bit.BOD12) {
stream.print(" BOD12");
}
if (PM->RCAUSE.bit.POR) {
stream.print(" Power On Reset");
}
stream.print(" [");
stream.print(PM->RCAUSE.reg);
stream.println("]");
}
// OTHER FUNCTIONS
String split(String s, char parser, int index) {
String rs = "";
int parserIndex = index;
int parserCnt = 0;
int rFromIndex = 0, rToIndex = -1;
while (index >= parserCnt) {
rFromIndex = rToIndex + 1;
rToIndex = s.indexOf(parser, rFromIndex);
if (index == parserCnt) {
if (rToIndex == 0 || rToIndex == -1) return "";
return s.substring(rFromIndex, rToIndex);
} else parserCnt++;
}
return rs;
}
inline String getHeaderValue(String header, String headerName)
{
return header.substring(strlen(headerName.c_str()));
}
void printPercent(uint32_t readLength, uint32_t contentLength) {
// If we know the total length
if (contentLength != (uint32_t)-1) {
SerialUSB.print("\r ");
SerialUSB.print((100.0 * readLength) / contentLength);
SerialUSB.print('%');
} else {
SerialUSB.println(readLength);
}
}
The UPDATE.BIN file is in the SD card. The server communication is still in the sketch - but not implemented currently. The arduino compiler produced one file with bootloader, and one without. I tested both. The Chip select pin in the SDUBoot.ino
has been updated.
But, the system does NOT pick up the new firmware. Please help.