summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libraries/OBD/OBD.cpp129
-rw-r--r--libraries/OBD/OBD.h31
-rw-r--r--libraries/SIM800/SIM800.cpp294
-rw-r--r--libraries/SIM800/SIM800.h55
-rw-r--r--libraries/SIM800/examples/GPRSTest/GPRSTest.ino126
5 files changed, 549 insertions, 86 deletions
diff --git a/libraries/OBD/OBD.cpp b/libraries/OBD/OBD.cpp
index 42fa1c5..c28c1f2 100644
--- a/libraries/OBD/OBD.cpp
+++ b/libraries/OBD/OBD.cpp
@@ -6,6 +6,7 @@
*************************************************************************/
#include <Arduino.h>
+#include <Wire.h>
#include "OBD.h"
//#define DEBUG Serial
@@ -54,12 +55,12 @@ byte hex2uint8(const char *p)
/*************************************************************************
* OBD-II UART Adapter
*************************************************************************/
-#include <Wire.h>
byte COBD::sendCommand(const char* cmd, char* buf)
{
- write(cmd);
- return receive(buf);
+ write(cmd);
+ dataIdleLoop();
+ return receive(buf);
}
void COBD::sendQuery(byte pid)
@@ -244,12 +245,6 @@ void COBD::sleep()
receive();
}
-void COBD::wakeup()
-{
- write('\r');
- receive();
-}
-
float COBD::getVoltage()
{
char buf[OBD_RECV_BUF_SIZE];
@@ -295,46 +290,48 @@ void COBD::begin()
{
OBDUART.begin(OBD_SERIAL_BAUDRATE);
#ifdef DEBUG
- DEBUG.begin(115200);
+ DEBUG.begin(115200);
#endif
+ recover();
}
byte COBD::receive(char* buffer, int timeout)
{
unsigned char n = 0;
- for (unsigned long startTime = millis();;) {
- if (available()) {
- char c = read();
- if (n > 2 && c == '>') {
- // prompt char received
- break;
- } else if (!buffer) {
- n++;
- } else if (n < OBD_RECV_BUF_SIZE - 1) {
- if (c == '.' && n > 2 && buffer[n - 1] == '.' && buffer[n - 2] == '.') {
- n = 0;
- timeout = OBD_TIMEOUT_LONG;
- } else {
- buffer[n++] = c;
- }
- }
- } else {
- if (millis() - startTime > timeout) {
- // timeout
- return 0;
- }
- dataIdleLoop();
- }
+ unsigned long startTime = millis();
+ for (;;) {
+ if (available()) {
+ char c = read();
+ if (n > 2 && c == '>') {
+ // prompt char received
+ break;
+ } else if (!buffer) {
+ n++;
+ } else if (n < OBD_RECV_BUF_SIZE - 1) {
+ if (c == '.' && n > 2 && buffer[n - 1] == '.' && buffer[n - 2] == '.') {
+ // waiting siginal
+ n = 0;
+ timeout = OBD_TIMEOUT_LONG;
+ } else {
+ buffer[n++] = c;
+ }
+ }
+ } else {
+ if (millis() - startTime > timeout) {
+ // timeout
+ break;
+ }
+ dataIdleLoop();
+ }
}
- if (buffer) buffer[n] = 0;
+ if (buffer) buffer[n] = 0;
return n;
}
void COBD::recover()
{
- write('\r');
- delay(100);
- while (available()) read();
+ write("AT\r");
+ receive(0, 1000);
}
bool COBD::init(OBD_PROTOCOLS protocol)
@@ -403,9 +400,7 @@ bool COBD::setBaudRate(unsigned long baudrate)
delay(50);
OBDUART.end();
OBDUART.begin(baudrate);
- OBDUART.print('ATV\r');
- delay(50);
- while (available()) read();
+ recover();
return true;
}
@@ -481,11 +476,10 @@ void COBD::debugOutput(const char *s)
void COBDI2C::begin()
{
Wire.begin();
- memset(obdPid, 0, sizeof(obdPid));
- memset(obdInfo, 0, sizeof(obdInfo));
#ifdef DEBUG
- DEBUG.begin(115200);
+ DEBUG.begin(115200);
#endif
+ recover();
}
void COBDI2C::end()
@@ -523,35 +517,36 @@ byte COBDI2C::receive(char* buffer, int timeout)
{
uint32_t start = millis();
byte offset = 0;
- delay(10);
do {
Wire.requestFrom((byte)I2C_ADDR, (byte)MAX_PAYLOAD_SIZE, (byte)1);
-
- bool hasEnd = false;
- for (byte i = 0; i < MAX_PAYLOAD_SIZE && Wire.available(); i++) {
- char c = Wire.read();
- buffer[offset + i] = c;
- if (c == 0)
- hasEnd = true;
- }
-
- if (buffer[0] == 0) {
- // data not ready
+ int c = Wire.read();
+ if (offset == 0 && (c == 0 || c == -1)) {
+ // data not ready
dataIdleLoop();
- continue;
+ continue;
}
-
- offset += MAX_PAYLOAD_SIZE;
- if (!hasEnd) {
- continue;
+ if (buffer) buffer[offset++] = c;
+ for (byte i = 1; i < MAX_PAYLOAD_SIZE && Wire.available(); i++) {
+ char c = Wire.read();
+ if (c == '.' && offset > 2 && buffer[offset - 1] == '.' && buffer[offset - 2] == '.') {
+ // waiting signal
+ offset = 0;
+ timeout = OBD_TIMEOUT_LONG;
+ } else if (c == 0 || offset == OBD_RECV_BUF_SIZE - 1) {
+ // string terminator encountered or buffer full
+ if (buffer) buffer[offset] = 0;
+ // discard the remaining data
+ while (Wire.available()) Wire.read();
+ return offset;
+ } else {
+ if (buffer) buffer[offset++] = c;
+ }
}
-
- return offset;
} while(millis() - start < timeout);
return 0;
}
-void COBDI2C::setPID(byte pid)
+void COBDI2C::setPID(byte pid, byte obdPid[])
{
byte n = 0;
for (; n < MAX_PIDS && obdPid[n]; n++) {
@@ -565,16 +560,16 @@ void COBDI2C::setPID(byte pid)
obdPid[n] = pid;
}
-void COBDI2C::applyPIDs()
+void COBDI2C::applyPIDs(byte obdPid[])
{
- sendCommandBlock(CMD_APPLY_OBD_PIDS, 0, (byte*)obdPid, sizeof(obdPid));
+ sendCommandBlock(CMD_APPLY_OBD_PIDS, 0, (byte*)obdPid, sizeof(obdPid[0])* MAX_PIDS);
delay(200);
}
-void COBDI2C::loadData()
+void COBDI2C::loadData(PID_INFO obdInfo[])
{
sendCommandBlock(CMD_LOAD_OBD_DATA);
dataIdleLoop();
Wire.requestFrom((byte)I2C_ADDR, (byte)MAX_PAYLOAD_SIZE, (byte)0);
- Wire.readBytes((char*)obdInfo, MAX_PAYLOAD_SIZE);
+ Wire.readBytes((char*)obdInfo, sizeof(obdInfo[0]) * MAX_PIDS);
}
diff --git a/libraries/OBD/OBD.h b/libraries/OBD/OBD.h
index dcd30fb..74e4225 100644
--- a/libraries/OBD/OBD.h
+++ b/libraries/OBD/OBD.h
@@ -128,12 +128,10 @@ public:
virtual bool read(byte pid, int& result);
// set device into
virtual void sleep();
- // wake up device from previous sleep
- virtual void wakeup();
// set working protocol (default auto)
virtual bool setProtocol(OBD_PROTOCOLS h = PROTO_AUTO);
// send AT command and receive response
- virtual byte sendCommand(const char* cmd, char* buf);
+ virtual byte sendCommand(const char* cmd, char* buf = 0);
// clear diagnostic trouble code
virtual void clearDTC();
// get battery voltage (in 0.1V, e.g. 125 for 12.5V, works without ECU)
@@ -196,8 +194,8 @@ private:
#define CMD_SEND_AT_COMMAND 0x11
#define CMD_APPLY_OBD_PIDS 0x12
#define CMD_LOAD_OBD_DATA 0x13
-#define CMD_GPS_SETUP 0x20
-#define CMD_GPS_QUERY 0x22
+#define CMD_GPS_SETUP 0x14
+#define CMD_GPS_QUERY 0x15
typedef struct {
uint16_t age;
@@ -212,22 +210,17 @@ typedef struct {
class COBDI2C : public COBD {
public:
- void begin();
+ void begin();
void end();
- bool read(byte pid, int& result);
- void write(const char* s);
+ bool read(byte pid, int& result);
+ void write(const char* s);
// API not applicable
bool setBaudRate(unsigned long baudrate) { return false; }
- // Asynchronized access API
- void setPID(byte pid);
- void applyPIDs();
- void loadData();
- uint16_t getData(byte pid, int& result);
+ // Asynchronized access API
+ void setPID(byte pid, byte obdPid[]);
+ void applyPIDs(byte obdPid[]);
+ void loadData(PID_INFO obdInfo[]);
protected:
- byte receive(char* buffer, int timeout = OBD_TIMEOUT_LONG);
- byte m_addr;
- PID_INFO obdInfo[MAX_PIDS];
- byte obdPid[MAX_PIDS];
-private:
- bool sendCommandBlock(byte cmd, uint8_t data = 0, byte* payload = 0, byte payloadBytes = 0);
+ byte receive(char* buffer = 0, int timeout = OBD_TIMEOUT_SHORT);
+ bool sendCommandBlock(byte cmd, uint8_t data = 0, byte* payload = 0, byte payloadBytes = 0);
};
diff --git a/libraries/SIM800/SIM800.cpp b/libraries/SIM800/SIM800.cpp
new file mode 100644
index 0000000..7a63482
--- /dev/null
+++ b/libraries/SIM800/SIM800.cpp
@@ -0,0 +1,294 @@
+/*************************************************************************
+* Test sketch for SIM800 library
+* Distributed under GPL v2.0
+* Written by Stanley Huang <stanleyhuangyc@gmail.com>
+* For more information, please visit http://arduinodev.com
+*************************************************************************/
+
+#include "SIM800.h"
+
+bool CGPRS_SIM800::init()
+{
+ simser.begin(115200);
+ pinMode(SIM800_RESET_PIN, OUTPUT);
+ digitalWrite(SIM800_RESET_PIN, HIGH);
+ delay(10);
+ digitalWrite(SIM800_RESET_PIN, LOW);
+ delay(100);
+ // generate turn on pulse
+ digitalWrite(SIM800_RESET_PIN, HIGH);
+ delay(3000);
+ if (sendCommand("AT")) {
+ sendCommand("AT+IPR=115200");
+ sendCommand("ATE0");
+ return true;
+ }
+ return false;
+}
+byte CGPRS_SIM800::setup(const char* apn)
+{
+ bool success = false;
+ for (byte n = 0; n < 30; n++) {
+ if (sendCommand("AT+CREG?", 2000)) {
+ char *p = strstr(buffer, "0,");
+ if (p) {
+ char mode = *(p + 2);
+#if DEBUG
+ con.print("Mode:");
+ con.println(mode);
+#endif
+ if (mode == '1' || mode == '5') {
+ success = true;
+ break;
+ }
+ }
+ }
+ delay(1000);
+ }
+
+ if (!success)
+ return 1;
+
+ if (!sendCommand("AT+CGATT?"))
+ return 2;
+
+ if (!sendCommand("AT+SAPBR=3,1,\"Contype\",\"GPRS\""))
+ return 3;
+
+ simser.print("AT+SAPBR=3,1,\"APN\",\"");
+ simser.print(apn);
+ simser.println('\"');
+ if (!sendCommand(0))
+ return 4;
+
+ for (byte n = 0; n < 10 && !(success = (sendCommand("AT+SAPBR=1,1") != 0)); n++)
+ delay(500);
+
+ if (!success)
+ return 5;
+
+ return 0;
+}
+bool CGPRS_SIM800::getOperatorName()
+{
+ // display operator name
+ if (sendCommand("AT+COPS?", "OK\r", "ERROR\r") == 1) {
+ char *p = strstr(buffer, ",\"");
+ if (p) {
+ p += 2;
+ char *s = strchr(p, '\"');
+ if (s) *s = 0;
+ strcpy(buffer, p);
+ return true;
+ }
+ }
+ return false;
+}
+bool CGPRS_SIM800::checkSMS()
+{
+ if (sendCommand("AT+CMGR=1", "+CMGR:", "ERROR") == 1) {
+ // reads the data of the SMS
+ sendCommand(0, 100, "\r\n");
+ if (sendCommand(0)) {
+ // remove the SMS
+ sendCommand("AT+CMGD=1");
+ return true;
+ }
+ }
+ return false;
+}
+int CGPRS_SIM800::getSignalQuality()
+{
+ sendCommand("AT+CSQ");
+ char *p = strstr(buffer, "CSQ: ");
+ if (p) {
+ int n = atoi(p + 2);
+ if (n == 99 || n == -1) return 0;
+ return n * 2 - 114;
+ } else {
+ return 0;
+ }
+}
+void CGPRS_SIM800::httpUninit()
+{
+ sendCommand("AT+HTTPTERM");
+}
+
+bool CGPRS_SIM800::httpInit()
+{
+ if (!sendCommand("AT+HTTPINIT", 10000) || !sendCommand("AT+HTTPPARA=\"CID\",1", 5000)) {
+ httpState = HTTP_DISABLED;
+ return false;
+ }
+ httpState = HTTP_READY;
+ return true;
+}
+bool CGPRS_SIM800::httpConnect(const char* url, const char* args)
+{
+ // Sets url
+ simser.print("AT+HTTPPARA=\"URL\",\"");
+ simser.print(url);
+ if (args) {
+ simser.print('?');
+ simser.print(args);
+ }
+
+ simser.println('\"');
+ if (sendCommand(0))
+ {
+ // Starts GET action
+ simser.println("AT+HTTPACTION=0");
+ httpState = HTTP_CONNECTING;
+ bytesRecv = 0;
+ checkTimer = millis();
+ } else {
+ httpState = HTTP_ERROR;
+ }
+ return false;
+}
+// check if HTTP connection is established
+// return 0 for in progress, 1 for success, 2 for error
+byte CGPRS_SIM800::httpIsConnected()
+{
+ byte ret = checkbuffer("0,200", "0,60", 10000);
+ if (ret >= 2) {
+ httpState = HTTP_ERROR;
+ return -1;
+ }
+ return ret;
+}
+void CGPRS_SIM800::httpRead()
+{
+ simser.println("AT+HTTPREAD");
+ httpState = HTTP_READING;
+ bytesRecv = 0;
+ checkTimer = millis();
+}
+// check if HTTP connection is established
+// return 0 for in progress, -1 for error, number of http payload bytes on success
+int CGPRS_SIM800::httpIsRead()
+{
+ byte ret = checkbuffer("+HTTPREAD: ", "Error", 10000) == 1;
+ if (ret == 1) {
+ bytesRecv = 0;
+ // read the rest data
+ sendCommand(0, 100, "\r\n");
+ int bytes = atoi(buffer);
+ sendCommand(0);
+ bytes = min(bytes, sizeof(buffer) - 1);
+ buffer[bytes] = 0;
+ return bytes;
+ } else if (ret >= 2) {
+ httpState = HTTP_ERROR;
+ return -1;
+ }
+ return 0;
+}
+byte CGPRS_SIM800::sendCommand(const char* cmd, unsigned int timeout, const char* expected)
+{
+ if (cmd) {
+ purgeSerial();
+#if DEBUG
+ con.print('>');
+ con.println(cmd);
+#endif
+ simser.println(cmd);
+ }
+ uint32_t t = millis();
+ byte n = 0;
+ do {
+ if (simser.available()) {
+ char c = simser.read();
+ if (n >= sizeof(buffer) - 1) {
+ // buffer full, discard first half
+ n = sizeof(buffer) / 2 - 1;
+ memcpy(buffer, buffer + sizeof(buffer) / 2, n);
+ }
+ buffer[n++] = c;
+ buffer[n] = 0;
+ if (strstr(buffer, expected ? expected : "OK\r")) {
+#if DEBUG
+ con.print("[1]");
+ con.println(buffer);
+#endif
+ return n;
+ }
+ }
+ } while (millis() - t < timeout);
+#if DEBUG
+ con.print("[0]");
+ con.println(buffer);
+#endif
+ return 0;
+}
+byte CGPRS_SIM800::sendCommand(const char* cmd, const char* expected1, const char* expected2, unsigned int timeout)
+{
+ if (cmd) {
+ purgeSerial();
+#if DEBUG
+ con.print('>');
+ con.println(cmd);
+#endif
+ simser.println(cmd);
+ }
+ uint32_t t = millis();
+ byte n = 0;
+ do {
+ if (simser.available()) {
+ char c = simser.read();
+ if (n >= sizeof(buffer) - 1) {
+ // buffer full, discard first half
+ n = sizeof(buffer) / 2 - 1;
+ memcpy(buffer, buffer + sizeof(buffer) / 2, n);
+ }
+ buffer[n++] = c;
+ buffer[n] = 0;
+ if (strstr(buffer, expected1)) {
+#if DEBUG
+ con.print("[1]");
+ con.println(buffer);
+#endif
+ return 1;
+ }
+ if (strstr(buffer, expected2)) {
+#if DEBUG
+ con.print("[2]");
+ con.println(buffer);
+#endif
+ return 2;
+ }
+ }
+ } while (millis() - t < timeout);
+#if DEBUG
+ con.print("[0]");
+ con.println(buffer);
+#endif
+ return 0;
+}
+
+byte CGPRS_SIM800::checkbuffer(const char* expected1, const char* expected2, unsigned int timeout)
+{
+ while (simser.available()) {
+ char c = simser.read();
+ if (bytesRecv >= sizeof(buffer) - 1) {
+ // buffer full, discard first half
+ bytesRecv = sizeof(buffer) / 2 - 1;
+ memcpy(buffer, buffer + sizeof(buffer) / 2, bytesRecv);
+ }
+ buffer[bytesRecv++] = c;
+ buffer[bytesRecv] = 0;
+ if (strstr(buffer, expected1)) {
+ return 1;
+ }
+ if (expected2 && strstr(buffer, expected2)) {
+ return 2;
+ }
+ }
+ return (millis() - checkTimer < timeout) ? 0 : 3;
+}
+
+void CGPRS_SIM800::purgeSerial()
+{
+ while (simser.available()) simser.read();
+}
+
diff --git a/libraries/SIM800/SIM800.h b/libraries/SIM800/SIM800.h
new file mode 100644
index 0000000..ca3104f
--- /dev/null
+++ b/libraries/SIM800/SIM800.h
@@ -0,0 +1,55 @@
+/*************************************************************************
+* Test sketch for SIM800 library
+* Distributed under GPL v2.0
+* Written by Stanley Huang <stanleyhuangyc@gmail.com>
+* For more information, please visit http://arduinodev.com
+*************************************************************************/
+
+#include <Arduino.h>
+
+#define SIM800_RESET_PIN 7
+#define simser Serial1
+#define con Serial
+#define DEBUG 0
+
+typedef enum {
+ HTTP_DISABLED = 0,
+ HTTP_READY,
+ HTTP_CONNECTING,
+ HTTP_READING,
+ HTTP_ERROR,
+} HTTP_STATES;
+
+class CGPRS_SIM800 {
+public:
+ CGPRS_SIM800():httpState(HTTP_DISABLED) {}
+ bool init();
+ byte setup(const char* apn);
+ bool getOperatorName();
+ bool checkSMS();
+ int getSignalQuality();
+ void httpUninit();
+ bool httpInit();
+ bool httpConnect(const char* url, const char* args = 0);
+ // check if HTTP connection is established
+ // return 0 for in progress, 1 for success, 2 for error
+ byte httpIsConnected();
+ void httpRead();
+ // check if HTTP connection is established
+ // return 0 for in progress, -1 for error, number of http payload bytes on success
+ int httpIsRead();
+ byte sendCommand(const char* cmd, unsigned int timeout = 2000, const char* expected = 0);
+ byte sendCommand(const char* cmd, const char* expected1, const char* expected2, unsigned int timeout = 2000);
+ bool available()
+ {
+ return simser.available();
+ }
+ char buffer[256];
+ byte httpState;
+private:
+ byte checkbuffer(const char* expected1, const char* expected2 = 0, unsigned int timeout = 2000);
+ void purgeSerial();
+ byte bytesRecv;
+ uint32_t checkTimer;
+};
+
diff --git a/libraries/SIM800/examples/GPRSTest/GPRSTest.ino b/libraries/SIM800/examples/GPRSTest/GPRSTest.ino
new file mode 100644
index 0000000..e752166
--- /dev/null
+++ b/libraries/SIM800/examples/GPRSTest/GPRSTest.ino
@@ -0,0 +1,126 @@
+/*************************************************************************
+* Test sketch for SIM800 library
+* Distributed under GPL v2.0
+* Written by Stanley Huang <stanleyhuangyc@gmail.com>
+* For more information, please visit http://arduinodev.com
+*************************************************************************/
+
+#include "SIM800.h"
+
+#define APN "connect"
+static const char* url = "http://arduinodev.com/datetime.php";
+
+
+CGPRS_SIM800 gprs;
+uint32_t count = 0;
+uint32_t errors = 0;
+
+void setup()
+{
+ con.begin(9600);
+ while (!con);
+
+ con.println("SIM800 TEST");
+
+ for (;;) {
+ con.print("Resetting...");
+ while (!gprs.init()) {
+ con.write('.');
+ }
+ con.println("OK");
+
+ con.print("Setting up network...");
+ byte ret = gprs.setup(APN);
+ if (ret == 0)
+ break;
+ con.print("Error code:");
+ con.println(ret);
+ con.println(gprs.buffer);
+ }
+ con.println("OK");
+ delay(3000);
+
+ if (gprs.getOperatorName()) {
+ con.print("Operator:");
+ con.println(gprs.buffer);
+ }
+ int ret = gprs.getSignalQuality();
+ if (ret) {
+ con.print("Signal:");
+ con.print(ret);
+ con.println("dB");
+ }
+
+#if 0
+ sendCommand("AT+CSQ");
+ lcd.println("Dialing...");
+ if (sendCommand("ATD + +61402533012;", 10000)) {
+ lcd.println(buffer);
+ }
+ if (sendCommand("ATH"))
+ lcd.println(buffer);
+ delay(1000);
+#endif
+
+ gprs.sendCommand("AT+CMGF=1"); // sets the SMS mode to text
+ gprs.sendCommand("AT+CPMS=\"SM\",\"SM\",\"SM\""); // selects the memory
+
+ for (;;) {
+ if (gprs.httpInit()) break;
+ con.println(gprs.buffer);
+ gprs.httpUninit();
+ delay(1000);
+ }
+ delay(3000);
+}
+
+void loop()
+{
+ count++;
+
+ char mydata[16];
+ sprintf(mydata, "t=%lu", millis());
+ con.print("Requesting ");
+ con.print(url);
+ con.print('?');
+ con.println(mydata);
+ gprs.httpConnect(url, mydata);
+ while (gprs.httpIsConnected() == 0) {
+ // can do something here while waiting
+ con.write('.');
+ for (byte n = 0; n < 25 && !gprs.available(); n++) {
+ delay(10);
+ }
+ }
+ if (gprs.httpState == HTTP_ERROR) {
+ con.println("error");
+ errors++;
+ delay(3000);
+ return;
+ }
+ gprs.httpRead();
+ int ret;
+ while ((ret = gprs.httpIsRead()) == 0) {
+ // can do something here while waiting
+ }
+ if (gprs.httpState == HTTP_ERROR) {
+ con.println("error");
+ errors++;
+ delay(3000);
+ return;
+ }
+
+ // now we have received payload
+ con.print("\n[Payload]");
+ con.println(gprs.buffer);
+
+ // show stats
+ con.print("Total Requests:");
+ con.print(count);
+ if (errors) {
+ con.print(" Errors:");
+ con.print(errors);
+ }
+ con.println();
+}
+