DaVinciChang 发表于 2015-8-2 13:25:50

求助SIM900模块无法执行AT命令。

本帖最后由 DaVinciChang 于 2015-8-3 14:23 编辑

本程序参考本论坛zcbzjx所发表的【第二弹】基于dht22+dsm501A+enc28J60+arduino+lcd1602+yeelink+实现家居环境监控。
使用网络上流传的SIM800 TCP代码经测试可以使用并能上传单个传感器数据到Yeelink。
以下代码SIM900和GPS模块使用了软串口,由于不会使用SoftSerial代码中没有使用listen监听可能有错误,但后来SIM900改为硬件串口。
Arduino nano
传感器及接口:

[*]Ublox NEO-5M GPS模块         PIN D7 D8
[*]SIM900 模块                     PIN D9 D10
[*]DHT11温湿度传感器             PIN A0
[*]DSM501B粉尘传感器             PIN A2 A4

问题描述:

[*]设备上电后呼叫SIM900手机号码提示无法接通。
[*]SIM900执行AT命令无响应。
[*]使用硬件串口同样无响应。
[*]单独测试SIM900部分代码可以运行并能上传单个数据到Yeelink。


#include <dht.h>
#include <TinyGPS.h>
#include <LCD5110_Basic.h>
#include <SoftwareSerial.h>
// GPRS UP LINK Test 01
// Jul_22_2015

// *********************************for yeelink api*****************************************//
//const String APIKey[] PROGMEM = "XXXX"; // replace your yeelink api key here
longDeviceID= 168888; // replace your device ID
// 固定的网关
//const char website[] PROGMEM = "api.yeelink.net";
//传感器个数及对应传感器ID
#define N 4
//上传数据的字符串变量及字符串长度变量
char sensorData;
intdataLength;
//传感器IDGPSTEMPHUMPM25
const longSensorID = {183754,183755, 183756, 183757, };

//********************************End of Yeelink *****************************************//
// 发送到服务器时间间隔,N大了可以适当缩短,
//每个传感器发送时间间隔为PostingInterval*N
const uint16_t PostingInterval = 5000;
// last time you connected to the server, in milliseconds
uint32_t lastConnectionTime = 0;
//轮流向服务器发送相应传感器变量 0 <= i <N,
uint8_t i = 0; //

//DHT11
#define DHT_PIN A0
//DSM501B
#define DSM_PIN_10 A4
#define DSM_PIN_25 A2
#define LINEBREAK "\r\n"
//DHT
DHT sensor = DHT();
LCD5110 lcd(2, 3, 4, 6, 5);
extern uint8_t SmallFont[];
SoftwareSerial GSMSerial(10, 9); //RX TX
TinyGPS gps;

SoftwareSerial GPS_SERIAL(7, 8);
//GPS data
bool newData = false;
char gps_lon;
char gps_lat;
float fkmph;//速度km/h
byte satnum = 0;
void setup() {
// put your setup code here, to run once:

Serial.begin(9600);
lcd.InitLCD();
lcd.setFont(SmallFont);
lcd.print("Initial Sensor...", CENTER, 0);
lcd.print("Enable DHT..", LEFT, 10);
sensor.attach(DHT_PIN);
lcd.print("GPS Searching...", LEFT, 20);
GPS_SERIAL.begin(9600);
//satnum = gps.satellites();

lcd.print("Register GPRS...", LEFT, 30);
GSMSerial.begin(9600);

GSMSerial.listen();
Serial.println("**********************************************************************");
Serial.println("debug========================GPRSINI");

//Serial.println(GSMSerial.print("ATI\r\n"));
delay(500);
////connect();

while (!gprsINI());

}

void loop()
{
// if (!ether.dhcpValid() && !ether.dhcpSetup())
//   Serial.println("DHCP failed");
// ether.packetLoop(ether.packetReceive());
if ( millis() < lastConnectionTime || millis() - lastConnectionTime > PostingInterval) {
    Serial.println(i);
    get_Send_String(i);
    send_Data(i);
    i++;
    if (i == N) i = 0;
}
else dsmStatistics();
}

void send_Data(uint8_t j) {
// Serial.print(sensorData);
// Serial.print(SensorID);
// Serial.println(j);
// sim800MSG("AT+CIPSTART=\"TCP\",\"api.yeelink.net\",\"80\"");
char *pstr = (char *)malloc(100 * sizeof(char));

sprintf(pstr, "POST /v1.0/device/%ld/sensor/%ld/datapoints HTTP/1.1" "\r\n"
          "Host: api.yeelink.net" "\r\n"
          "U-ApiKey: xxxxxxxxxxxxxxxxxx" "\r\n"
          "Content-Length: %d" "\r\n"
          "Content-Type: application/x-www-form-urlencoded" "\r\n"
          "%s" "\r\n0x1a",
          DeviceID, SensorID, dataLength, sensorData);
Serial.println(pstr);
Serial.println(sim800MSG(pstr));
lastConnectionTime = millis();
}
//比较周数,成功返回0-6的数,错误返回7
//p代表周数,取周数前3个字母,如Mon代表周1,以此类推
//改动周几不影响返回的时间值,可以通过改动日期的日数来达到修改时间

//比较月份,成功返回0-11的数,错误返回12
//P 为月份的前三个字母,如Feb代表二月,以此类推


//将字串格式的时间转换为结构体,返回距离1970年1月1日0:0:0的秒数,当字符串格式错误或超值时返回0
//BUF 为类似Tue May 15 14:46:02 2007格式的,p为时间结构体

//dsm501统计变量
uint32_t dsmStatTimes10 = 0; //DSM
uint32_t sumTimeofLow10 = 0;
uint32_t dsmStatTimes25 = 0;
uint32_t sumTimeofLow25 = 0;
uint8_t switch1025 = 0;
//递推滤波变量
#define FILT_N 10
#define FILT_I 2
uint8_t filtI = {
0, 0
};
uint16_t filtDsm;
uint32_t filtSum = {
0, 0
};

void dsmStatistics() {
if (switch1025) {
    dsmStatTimes10 ++;
    sumTimeofLow10 += !digitalRead(DSM_PIN_10);
    switch1025 = 0;
}
else {
    dsmStatTimes25 ++;
    sumTimeofLow25 += !digitalRead(DSM_PIN_25);
    switch1025 = 1;
}
}

uint16_t filteringDsm(uint8_t l, uint16_t _dsmData) {
filtSum = filtSum - filtDsm];
filtSum = filtSum + _dsmData;
filtDsm] = _dsmData;
filtI = filtI + 1;
if (filtI >= FILT_N) filtI = 0;
return filtSum / FILT_N;
}

float dsmTemp25;

void get_Send_String(uint8_t k) {
switch (k) {
    case 0: //DSM501
      {
      // gps型传感器格式如下:
      //{
      //"value": {"lat":35.4321,"lng":46.3451,"speed":98.2}
      //}
      feed_gps(k);
      }

    case 1://DHT temperature
      {

      sensor.update();
      uint16_t tempData = (sensor.getTemperatureInt() << 8) | sensor.getTemperatureFrac();

      lcd.print(String(tempData), LEFT, 0);
      //lcd.print(".");
      //lcd.print(tempData % 10);
      //lcd.print("C");
      format_String(k, tempData);
      break;
      }
    case 2://DHT humidity
      {
      sensor.update();
      uint16_t humiData = (sensor.getHumidityInt() << 8) | sensor.getHumidityFrac();
      //lcd.setCursor(6, 0);
      lcd.print(String(humiData / 10) + "%", LEFT, 20);
      //lcd.print(".");
      //lcd.print(humiData % 10);
      //lcd.print("%");
      format_String(k, humiData);
      break;
      }
    case 3://PM10
      {
      lcd.clrScr();
      float dsmTemp0 = (sumTimeofLow10 * 100.0) / dsmStatTimes10;
      float dsmTemp10 = 0.1776 * pow(dsmTemp0, 3) - 0.24 * pow(dsmTemp0, 2) + 94.003 * dsmTemp0;
      // lcd.setCursor(12, 0);
      // lcd.print(dsmTemp10);
      dataLength = sprintf(sensorData, "{\"value\":%d}", filteringDsm(k, int(dsmTemp10)));
      sumTimeofLow10 = 0;
      dsmStatTimes10 = 0;
      dsmTemp0 = (sumTimeofLow25 * 100.0) / dsmStatTimes25;
      dsmTemp25 = 0.1776 * pow(dsmTemp0, 3) - 0.24 * pow(dsmTemp0, 2) + 94.003 * dsmTemp0;
      dsmTemp25 = dsmTemp10 - dsmTemp25;
      sumTimeofLow25 = 0;
      dsmStatTimes25 = 0;
      lcd.print("PM10:" + String(dsmTemp10), LEFT, 0);
      break;
      }
    case 4://pm25
      {
      dataLength = sprintf(sensorData, "{\"value\":%d}", filteringDsm(k, int(dsmTemp25)));
      lcd.print("PM2.5:" + String(dsmTemp25), LEFT, 10);
      break;
      }
}
}

void format_String(uint8_t l, uint16_t sensor_Data) {
uint16_t Tc_100 = sensor_Data;
uint8_t whole, fract;
whole = Tc_100 / 10 ; // separate off the whole and fractional portions
fract = Tc_100 % 10;
dataLength = sprintf(sensorData, "{\"value\":%d.%d}", whole, fract);
}


boolean gprsINI()
{
Serial.println("GPRS INI");
String msg;
msg = sim800MSG("AT+SAPBR=2,1");
Serial.println(msg);
sim800MSG("ATE");
if (msg.indexOf("OK") > 0)
    if (msg.indexOf("0.0.0.0") > 0)
    {
      sim800MSG("AT+SAPBR=3,1,\"Contype\",\"GPRS\"");
      sim800MSG("AT+SAPBR=3,1,\"APN\",\"UNINET\"");
      sim800MSG("AT+SAPBR=1,1");
    }
    else return 1;
delay(2000);
return 0;
}

String sim800MSG(String msg)
{
Serial.println(String("") + "POST DATA:" + msg);
String str;
boolean ActionFlag = false;

if (msg.indexOf("HTTPACTION") > 0)
    ActionFlag = true;

GSMSerial.println(msg);
while (!GSMSerial.available())
    delay(10);
while (GSMSerial.available())
{
    char c = GSMSerial.read();
    str += c;
    delayMicroseconds(1200);
    // delay(2);
}

if (ActionFlag)
{
    while (!GSMSerial.available())
      delay(10);

    while (GSMSerial.available())
    {
      char c = GSMSerial.read();
      str += c;
      delay(2);
    }
}
//Serial.println(str);
return str;
}
char feed_gps(uint8_t dataid)
{
lcd.clrScr();
newData = false;
unsigned long chars;
unsigned short sentences, failed;

// For one second we parse GPS data and report some key values
// for (unsigned long start = millis(); millis() - start < 1000;)
// {
while (GPS_SERIAL.available())
{
    char c = GPS_SERIAL.read();
    Serial.write(c); // uncomment this line if you want to see the GPS data flowing
    if (gps.encode(c)) // Did a new valid sentence come in?
      newData = true;
    lcd.clrScr();
    Serial.println("GPS READY!");
    // lcd.print("GPS READY!", CENTER, 15);
}
// }

if (newData)
{

    float flat, flon;
    unsigned long age;
    int _year;
    byte _month, _day, _hour, _minute, _second, _hundredths;
    gps.f_get_position(&flat, &flon, &age);
    gps.crack_datetime(&_year, &_month, &_day, &_hour, &_minute, &_second, &_hundredths, &age);
    fkmph = gps.f_speed_kmph();
    if ( satnum != TinyGPS::GPS_INVALID_SATELLITES) {
      lcd.print("SAT:" + satnum, CENTER, 40);
    }

    if (fkmph != TinyGPS::GPS_INVALID_F_SPEED)
    {
      if (fkmph < 0.5) fkmph = 0.0; //屏蔽0时速时的误差显示
    }
    else
    {
      fkmph = 0.0;
    }

    if (age == TinyGPS::GPS_INVALID_AGE) {
      Serial.print("********** ******** ");
      //myLCD.print("********** ********", CENTER, 20);
    }
    else
    {
      char gps_date;
      char gps_time;
      sprintf(gps_date, "%02d/%02d/%02d",
            _month, _day, _year);
      lcd.print(gps_date, LEFT, 20);
      sprintf(gps_time, "%02d:%02d:%02d ",
            _hour, _minute, _second);
      lcd.print(gps_time, LEFT, 30);
    }
    // float fkmph = gps.f_speed_kmph(); // speed in km/hr
    flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flat, 6;
    flon == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : flon, 6;
    dtostrf(flat, 11, 6, gps_lat);
    dtostrf(flon, 10, 6, gps_lon);
    sprintf(gps_lon, "LON: %ld", gps_lon);
    sprintf(gps_lat, "LAT: %ld", gps_lat);
    lcd.print(gps_lat, LEFT, 0);
    lcd.print(gps_lon, LEFT, 10);
    Serial.println("lat:"); //latitude
    Serial.println(gps_lat);
    Serial.println("lon:");
    Serial.println(gps_lon);//longitude
    dataLength = sprintf(sensorData, "{\"value\":{\"lat\":%d,\"lng\":%d,\"speed\":%f}", gps_lat, gps_lon, fkmph);
}
}

void ShowSerialData()
{
String str;
while (GSMSerial.available() != 0)
{
    char c = GSMSerial.read();
    str += c;
}
Serial.print(str);
}
int getLength(int someValue) {
// there's at least one byte:
int digits = 1;
// continually divide the value by ten,
// adding one to the digit count for each
// time you divide, until you're at 0:
int dividend = someValue / 10;
while (dividend > 0) {
    dividend = dividend / 10;
    digits++;
}
// return the number of digits:
return digits;
}


DaVinciChang 发表于 2015-8-3 16:40:59

求助高手提供一下调试思路或方法。串口没回显不知道怎么改啊!
页: [1]
查看完整版本: 求助SIM900模块无法执行AT命令。