囧囧-科技大神粉 发表于 2016-1-4 23:34:15

重新玩GPS

起因:20来好要滚去海南呆一阵子,家里没人,担心小花小草全灭,所以打算搞一个自动浇花的

原理非常简单

1、先设定个开始时间,比如000000,010116 (hhmmss,ddmmyy),然后没隔 5天,浇水200L ,把这个写进arduino 的EEPROM里

2、GPS 读取时间,发现间隔时间到了,就控制电池阀防水浇花,流量计检测流量,流量到达后,停止浇花

3、把本次的浇花时间、是否浇花完成、浇了多少流量写如EEPROM,这样如果因为停水、断电啥的原因,前次没浇够,这次还能补上

4、至于浇花部分,停水时不能浇花,免得电池阀坏了,这个配合流量计要做个检测

注意:GPS方面为了节约资源,降低难度,用命令操作,让gps 只输出GPRMC,每秒一次




囧囧-科技大神粉 发表于 2016-1-4 23:36:12

先上EEPROM初始化化程序,写入最初始的设定

/*
设置格式如下
hhmmss,ddmmyy,A,B,C,D,E
A=数字1(0-127) 为由存储时间开始,间隔多少个单位时间浇水一次
B=数字2(0-127) 每次浇水多少个单位体积
C=数字3(0-127) 1单位时间=x*10min
D=数字4(0-127) 1单位体积=x*1L
E=数字5(0-127) 索引,如果分每条分配25字节,那么撑死能记录39条浇水记录,默认为字符0

(浇水记录)程序存储格式如下

hhmmss,ddmmyy,A,B,C,D
A=数字1(0-127) 识别码,本条是否已存记录
B=数字2(0-127) 是否浇水完毕
C=数字3(0-127) 已经浇水的单位体积
D=数字4(0-127) 已经消耗的单位时间

*/

#include <EEPROM.h>

char EEPROMtemp;

void setup()
{
       
       Serial.begin(19200);
        /*
hhmmss,ddmmyy,A, B,C, D,E
000000,010116,60,20,12,10,0
A=数字1(0-127) 为由存储时间开始,间隔多少个单位时间浇水一次,默认设置为60(60*120min=5天)
B=数字2(0-127) 每次浇水多少个单位体积,默认数值为20,(20*10L=200L),对应ASCII的字符是 DC4 (device control 4) 设备控制4
C=数字3(0-127) 1时间单位=x*10min,默认数值为12
D=数字4(0-127) 1单位体积=x*1L 默认数值是10,对应ASCII的字符是 LF (NL line feed, new line) 换行键
E=数字5(0-127) 索引,如果分每条分配25字节,那么撑死能记录39条浇水记录,默认为字符0,ascII=48
*/


//000000,010116,
    EEPROM.write(0, '0');
    EEPROM.write(1, '0');
    EEPROM.write(2, '0');
    EEPROM.write(3, '0');
    EEPROM.write(4, '0');
    EEPROM.write(5, '0');
   
        EEPROM.write(6, ',');

    EEPROM.write(7, '0');
    EEPROM.write(8, '1');
    EEPROM.write(9, '0');
    EEPROM.write(10, '1');
    EEPROM.write(11, '1');
    EEPROM.write(12, '6');
       
        EEPROM.write(13, ',');
                       
//60,20,12,10,0
EEPROM.write(14,60);
EEPROM.write(15, ',');

EEPROM.write(16, 20);
EEPROM.write(17, ',');

EEPROM.write(18, 12);
EEPROM.write(19, ',');

EEPROM.write(20, 10);
EEPROM.write(21, ',');

EEPROM.write(22, '0');
EEPROM.write(23, 0);


for(int col=0;col<24;col++) EEPROMtemp = EEPROM.read(col);//读取预设参数
}

void loop()
{
       
                                        for(int col=0;col<14;col++)Serial.print(EEPROMtemp);
                                int x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                Serial.println(EEPROMtemp);
                               
                               delay(3000);
                               
}


囧囧-科技大神粉 发表于 2016-1-4 23:37:00

主程序来了,浇花部分还没上呢


//输出控制:
//调试信息
//#define tiaoshixinxi


#include<EEPROM.h>
int EEPROMvalue; //EEPROM的值
char EEPROMtemp;
/*
设置格式如下
hhmmss,ddmmyy,A,B,C,D,E

A=数字1(0-127) 为由存储时间开始,间隔多少个单位时间浇水一次
B=数字2(0-127) 每次浇水多少个单位体积
C=数字3(0-127) 1单位时间=x*10min
D=数字4(0-127) 1单位体积=x*1L
D=数字5(0-127) 索引,如果分每条分配25字节,那么撑死能记录39条浇水记录

(浇水记录)程序存储格式如下

hhmmss,ddmmyy,A,B
A=数字1(48-49) 48未完毕 49已完毕
B=数字2(0-127) 已经浇水的单位体积

*/


#include <SoftwareSerial.h>
SoftwareSerial gps(8, 9); // RX, TX

char tempx;//提取GPS的时间到tempx数组中hhmmss,ddmmyy


char GPRMC;//临时数组1,放gps数据的
unsigned long gpstimes;//gps计时器,如果超过一定时间10ms,则证明gps数据已经发送完毕
unsigned long quanjujishu;//全局计数,计算1秒之内,循环了多少次,这个次数在一定程度上表示了剩余性能
boolean konghangpanduan=1;//空行判断,因为在读取串口数据后并没有延迟,完全依赖全局循环,那么,特定程序是否执行,就全靠布尔量来标记了
int jsq1=0;


String jianyan="";//GPS数据包的ASCII异或校验
int yihuoyunsuan;//异或运算——校验结果
boolean jiaoyanjieguo=0;//校验结果
boolean dingweiok=0;//定位有效
boolean ruanchuankouchongqi=0;//重启软串口1次,无效时 冷启动GPS
int feiyuqileijiA=0;//非预期累积A,对应gps输出不是GGA 或 RMC时,累积到30次,定义GPS输出1次
int feiyuqileijiB=0;//非预期累积B,对应异或验证不能通过的情况,累积到30次,重启软串口1次,无效时 冷启动GPS 1次
int feiyuqileijiC=0;//非预期累积C,对应RMC长时间不能定位的情况,累积到10次,通过检查年数10位是否为默认值,来确定时间是否可用

boolean TimeOK=0;
int jilusuoyin=0;//记录索引
long shijijiangeshijian=0;//实际间隔时间
long yushejiangeshijian=0;//预设间隔时间


int daijiaoguanliang=0;//待浇灌量
boolean jiaohuakaishi=0;//浇花开始


void setup() {
gps.begin(19200);
Serial.begin(19200);


//EEPROM预处理
/*
设置格式如下
hhmmss,ddmmyy,A,B,C,D,E
000000,010116,60,20,12,10,0
A=数字1(0-127) 为由存储时间开始,间隔多少个单位时间浇水一次,默认设置为60(60*120min=5天)
B=数字2(0-127) 每次浇水多少个单位体积,默认数值为20,(20*10L=200L),对应ASCII的字符是 DC4 (device control 4) 设备控制4
C=数字3(0-127) 1时间单位=x*10min,默认数值为12
D=数字4(0-127) 1单位体积=x*1L 默认数值是10,对应ASCII的字符是 LF (NL line feed, new line) 换行键
E=数字5(0-127) 索引,如果分每条分配25字节,那么撑死能记录39条浇水记录,默认为字符0,ascII=48


(浇水记录)程序存储格式如下

hhmmss,ddmmyy,A,B
A=数字1(48-49) 48未完毕 49已完毕
B=数字2(0-127) 已经浇水的单位体积

*/
        for(int col=0;col<24;col++) EEPROMtemp = EEPROM.read(col);//读取预设参数
       
        jilusuoyin=EEPROMtemp-48;//把索引数字化
       
        if(jilusuoyin<40 && jilusuoyin>0){
                //每条记录分配25字节空间,jilusuoyin为最近记录的首地址
                for(int col=0;col<13;col++) EEPROMtemp = EEPROM.read(col+jilusuoyin*25);//更新至最近一次的浇水时间
       }
       
       

}



// the loop routine runs over and over again forever:
void loop() {

if(jiaohuakaishi){
       
                //具体浇花程序
                jiaohua();
                       
}else{
       
       
        while (gps.available() > 0 && !TimeOK) {
        gpstimes=millis();//重置gpstimes为millis()
        konghangpanduan=0;//因为串口有数据,所以空行判断为0,即不空行
        GPRMC = gps.read();//软串口读取GPS数据,并保存在临时数组GPRMC中
        if(jsq1<99)jsq1++;//确保GPS跑飞时,或设置不当时,单片机自身数组不溢出
        delayMicroseconds(500);
        }



        if(millis()-gpstimes>20 && !konghangpanduan){
        konghangpanduan=1;
        gpsyihuojianyan();//异或运算,校验GPS输出字符串的准确性
        tiqushijian();//提取时间,装入tempx, 存储格式如下 hhmmss,ddmmyy
        }
       


        //在取得时间的情况下,讨论是否启动浇花程序
        if(TimeOK){
        TimeOK=0;
       
        qidongjiaohuadepanduan();
        }


       
}







}






void gpsyihuojianyan()
{

//异或运算,校验GPS输出字符串的准确性



//然而最终的jsq1 与实际的GPRMC的关系究竟如何,还是以实际调试为准
//手中这个jsq1就比GPRMC实际长度大2,估摸着换行符占了一位,但打印不显示,而程序在
//GPS串口传输完毕后,还对jsq1加了1,$ *XX不参与异或运算,第一位$ 所在数组为0

/*

        Serial.print("jsq1= ");
        Serial.println(jsq1);
        Serial.println(GPRMC);
        */

for(int col=1;col<jsq1-5;col++){
if(col==1)yihuoyunsuan=GPRMC;
else yihuoyunsuan=yihuoyunsuan ^ GPRMC;
}
//因为定义int的时候,yihuoyunsuan的结果是以10进制DEC表示的,所以需转换为16进制HEX
//因为GPS校验数据0位也进行了传输,所以在转换的时候有必要将情况分类讨论
//(yihuoyunsuan=0)/(0<yihuoyunsuan<17)/(17<yihuoyunsuan)
if(yihuoyunsuan==0){
//校验数10进制为0,直接填充字符串00
jianyan="00";
}else if(yihuoyunsuan>15){
//此时转换为16进制以后,天然有2位,很理想,不用处理
jianyan = String(yihuoyunsuan,HEX);
}else{
//校验数10进制为1-15时,转换为16进制就只有1位数,所以需要在前面填0
jianyan = "0";
jianyan += String(yihuoyunsuan,HEX);
}
//实践中发现,jianyan中的字符是以小写方式存在,虽然Serial.println(yihuoyunsuan,HEX)会以大写方式打印出来
//但直接Serial.println(jianyan)就是小写的,这是啥情况?
//将其字母转换为大写,否则与GPS传输的校验码对比时大小写问题校验失败(GPS传输的校验码为大写的)
jianyan.toUpperCase();
///////////////////////////////////////////显示异或校验码,方便给GPS编程,虽然还没成功过

        /*
        Serial.print("jianyan= ");
        Serial.println(jianyan);
        Serial.print("jsq1= ");
        Serial.println(jsq1);
        Serial.println(GPRMC);
        */

if(jianyan==GPRMC && jianyan==GPRMC ){
//一致,则说明数据是有效的,输出校验结果
jiaoyanjieguo=1;
feiyuqileijiB=0;
ruanchuankouchongqi=0;//优先通过重启软串口解决校验不过的情况,不行能解决再冷启动GPS
}else{
//不一致
jiaoyanjieguo=0;
feiyuqileijiB++;
}
//对校验数组进行清零
jianyan="";

/*---------------------------异或运算,校验GPS输出字符串的准确性 end--------------------------*/


}


void tiqushijian()
{
   //提取时间,装入tempx, 存储格式如下 hhmmss,ddmmyy
   //并通过GPS命令操作,在信号不好时RMC、GGA的切换,GPS的重启
       
       
       
        if(jiaoyanjieguo){ //通过异或校验的情况下,检查定位情况
                jiaoyanjieguo=0;
               
               
                #ifdef tiaoshixinxi
                Serial.println(GPRMC);
                #endif
               
                //检查语句 RMC
                if(GPRMC=='M' && GPRMC=='C'){
                       
                        feiyuqileijiA=0;
                       
                        //RMC 已定位标志判断
                        //$GPRMC,044344.858,V,0000.0000,N,00000.0000,E,,,030116,,*19
                        //$GPRMC,044342.000,A,0000.0000,N,00000.0000,E,0.00,,030116,,*1D
                        if(GPRMC=='A'){
                                feiyuqileijiC=0;
                                dingweiok=1;
                        }else feiyuqileijiC++; //对应RMC长时间不能定位的情况
                       

                       
                               //对应RMC长时间不能定位的情况,900秒不定位,冷启动gps
               
                                if(feiyuqileijiC>900){
                                        feiyuqileijiC=0;
                                        gps.println("$PSRF101,0,0,0,000,0,0,12,4*10");//GPS COLD START
                                }
               

                        if(dingweiok || feiyuqileijiC>10){ //当GPS已定位,或虽未定位,但已经经过10秒
                                dingweiok=0;
                               
                               
                               
                                //提取GPS的时间到tempx数组中hhmmss,ddmmyy
                                //$GPRMC,044342.000,A,0000.0000,N,00000.0000,E,0.00,,030116,,*1D
                                for(int col=0;col<7;col++)tempx=GPRMC;//时间位置固定,可直接提取
                                //日期稍微麻烦点,计算标志位“,”这个符号的位置,来规避长度变换(实际航速、实际航迹向这2个不确定因素)
                               
                                int col2=0;
                                for(int col=0;col<jsq1-3;col++){
                                        if(GPRMC==',')col2++;
                                       
                                        if(col2==9){
                                                /*
                                                Serial.print("GPRMC=");
                                                Serial.print(GPRMC);
                                                Serial.print(" GPRMC= ");
                                                Serial.println(GPRMC);
                                                //当gps信号弱,不能定位,通过检查gps 给出的年月日,是否是默认的160406ddmmyy,来判断时间的可用性,即年十位不为0
                                                GPRMC 是年的10位,GPRMC 是年的个位,默认是06年,现在是16年,只要十位不是0(ascII大于48),那么就算时间可信
                                                */
                                                if(GPRMC>48){
                                                        feiyuqileijiC=0;
                                                        TimeOK=1;//时间可用标志
                                                        gps.end();//提取时间后关闭软串口
                                                        for(int col3=0;col3<7;col3++)tempx=GPRMC;//提取时间
                                                        col=jsq1-3;//跳出循环
                                                       
                                                }
                                               
                                       
                                        }
                                       
                                }
                               
                               
                                /*
                                //Serial.print(" TimeOK ");
                                Serial.print("tempx=");
                                Serial.println(tempx);
                                Serial.print("tempx=");
                                Serial.println(tempx);
                               
                                if(tempx==44)Serial.print("tempx=44 ");
                                if(tempx+2>44)Serial.print("tempx+2>44 ");
                                int col=tempx;
                                Serial.print("col=");
                                Serial.println(col);
                                */

                               
                               
                        }
                       
                }else feiyuqileijiA++;//对应gps输出不是 RMC时
                       
                       
               


       
        }

        if(feiyuqileijiA>30){ //对应gps输出不是 RMC时,累积到30次,定义GPS输出1次
                feiyuqileijiA=0;
                gps.println("$PSRF109,NMEA19200,NULL38400,GGA0,GLL0,GSA0,GSV0,RMC1,VTG0,USER0*32");       
               
        }
       
        if(feiyuqileijiB>30){ //对应异或验证不能通过的情况,累积到30次,重启软串口1次,无效时 冷启动GPS 1次
                feiyuqileijiB=0;
               
                if(!ruanchuankouchongqi){ //优先重启软串口,ruanchuankouchongqi默认为0
                        ruanchuankouchongqi=!ruanchuankouchongqi;
                        gps.end();
                       
                        gps.begin(19200);
                       
                }else{
                        ruanchuankouchongqi=!ruanchuankouchongqi;
                        gps.println("$PSRF101,0,0,0,000,0,0,12,4*10");//GPS COLD START
               
                }
               
        }
       


/*
        Serial.print("feiyuqileijiA=");
        Serial.print(feiyuqileijiA);
        Serial.print(" feiyuqileijiB= ");
        Serial.print(feiyuqileijiB);
        Serial.print(" feiyuqileijiC= ");
        Serial.print(feiyuqileijiC);
        Serial.println(GPRMC);
*/

        //收尾工作,清空GPS数组,jsq1归零
        for(int col=0;col<100;col++)GPRMC=0;
    jsq1=0;

}


void qidongjiaohuadepanduan()//启动浇花的判断
{
       
/*
EEPROM设置格式如下
hhmmss,ddmmyy,A, B,C, D,E
000000,010116,60,20,12,10,0
A=数字1(0-127) 为由存储时间开始,间隔多少个单位时间浇水一次,默认设置为60(60*120min=5天)
B=数字2(0-127) 每次浇水多少个单位体积,默认数值为20,(20*10L=200L),对应ASCII的字符是 DC4 (device control 4) 设备控制4
C=数字3(0-127) 1时间单位=x*10min,默认数值为12
D=数字4(0-127) 1单位体积=x*1L 默认数值是10,对应ASCII的字符是 LF (NL line feed, new line) 换行键
E=数字5(0-127) 索引,如果分每条分配25字节,那么撑死能记录39条浇水记录,默认为字符0,ascII=48


(浇水记录)程序存储格式如下

hhmmss,ddmmyy,A,B
A=数字1(48-49) 48未完毕 49已完毕
B=数字2(0-127) 已经浇水的单位体积
*/

        //进行浇花有2种情况, A、上次浇花因中断,现在继续 B、间隔时间到了,应该浇花
        //情况A
        /*对记录位进行初始化
        hhmmss,ddmmyy,A,B
        A=数字1(48-49) 48未完毕 49已完毕
        B=数字2(0-127) 已经浇水的单位体积
        */
        if(jilusuoyin > 0){//上次未完成的情况(索引大于0才可能有存在)
                               
                        //上次未完成,浇花开始
                        if(EEPROM.read(14+jilusuoyin*25)==48)jiaohuakaishi=1;
                       
        }else if(millis()-quanjujishu>3000){ //讨论因间隔时间到了的浇花,情况,另外的间隔是定义的多久打开串口读取gps 数据一次,为方便调试,这里取3秒
               
                                //情况B,一个全新的开始
                                //时间到了的情况,EEPROMtemp*EEPROMtemp 个10min就是间隔,最大127*127,约2688小时,最小10min
                               
                        quanjujishu=millis();
                               
                        gps.begin(19200);
                               
                        //shijijiangeshijian=计算上次浇水时间到现在,经理过多少个10min                               
                        long niancha=(tempx-EEPROMtemp)*10*365*24*6+(tempx-EEPROMtemp)*365*24*6;
                        long yuecha=(tempx-EEPROMtemp)*10*30*24*6+(tempx-EEPROMtemp)*30*24*6;
                        long richa=(tempx-EEPROMtemp)*10*24*6+(tempx-EEPROMtemp)*24*6;
                        long shicha=(tempx-EEPROMtemp)*10*6+(tempx-EEPROMtemp)*6;
                        shijijiangeshijian=niancha+yuecha+richa+shicha+tempx-EEPROMtemp;
                                               
                        //预设间隔时间 = 间隔多少个单位时间 X 每个单位代表的时间(X * 10min)
                        yushejiangeshijian=EEPROMtemp*EEPROMtemp;
               
                if(shijijiangeshijian > yushejiangeshijian){
                                                       
                        if(jilusuoyin<39)jilusuoyin++;
                        else jilusuoyin=1;
               
                        EEPROM.write(22, jilusuoyin+48);//更新EEPROM中的索引数值=原值+1,等于39的情况归0
               
                        for(int col=0;col<13;col++) EEPROMtemp = tempx;//更新预设数组中的时间
                        for(int col=0;col<13;col++) EEPROM.write(col+jilusuoyin*25, tempx);//更新EEPROM中的时间
                       
                        /*对记录位进行初始化
                        hhmmss,ddmmyy,A,B
                        A=数字1(48-49) 48未完毕 49已完毕
                        B=数字2(0-127) 已经浇水的单位体积
                        */
                                EEPROM.write(13+jilusuoyin*25, ',');//,
                                EEPROM.write(14+jilusuoyin*25, 48);//A
                                EEPROM.write(15+jilusuoyin*25, ',');//,
                                EEPROM.write(16+jilusuoyin*25, 0);//B

                        //浇花开始
                        jiaohuakaishi=1;
               
                       
                }
               
                                #ifdef tiaoshixinxi
                               
                                Serial.print(“Detection value=”);
                                Serial.println(shijijiangeshijian);
                                Serial.print(“set valuet=”);
                                Serial.println(yushejiangeshijian);
                               
                                Serial.println(tempx);
                               
                                for(int col=0;col<14;col++)Serial.print(EEPROMtemp);
                                int x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                Serial.println(EEPROMtemp);
               
                                #endif       

        }
               

       
}



void jiaohua()//具体浇花程序
{
               
                //读取已浇灌体积,与预设浇灌体积相减,计算待浇灌量
                daijiaoguanliang=EEPROMtemp-EEPROM.read(16+jilusuoyin*25);
                       
                       
                       
       
}






囧囧-科技大神粉 发表于 2016-1-4 23:38:02

以前写的浇花程序的一部分,肯定不能直接用,作为参考,后面就改这个程序了

//////////////////////////////////////////////////////////////////////////////////////////////
//浇花的一些定义
//////////////////////////////////////////////////////////////////////////////////////////////
int liuliangji=12;
int diancifa=13;
unsigned long meimiaoyilunhui=millis();//每秒一轮回

boolean chongfupanduanA=0;//重复判定A

int jsqLLx=0;
float shishiliuliang=0;//实时流量
float leijiliuliang=0;//累计流量
int shedingjiaoguanliang=0;//设定浇灌量

unsigned long guzhangjianceA=millis();//故障检测
int guzhangjiancejsq;//故障检测计数器



void setup() {



}


void loop() {

//浇花主程序///////////////////////////////////////////////////////////

jiaohuaA();//每秒频率测定,实时流量计算,累计流量叠加

jiaohuaB();//通过3秒的频率次数的累加,来判断是否停水了(防止电池阀在没水的时候长期运行)


if(leijiliuliang < shedingjiaoguanliang) { //流量控制,流量超了就关了
digitalWrite(diancifa, LOW);//累计流量小于设定流量,打开电磁阀

}else{
digitalWrite(diancifa, HIGH);//关闭电磁阀
shedingjiaoguanliang=0;//清空设定浇灌量
leijiliuliang=0;//清空累计流量

}

}



void jiaohuaA(){

if(millis()-meimiaoyilunhui>1000) {

meimiaoyilunhui=millis();//每一秒还原一次
shishiliuliang=jsqLLx/7.5;//计算实时流量(公式:频率=7.5*流量(L/min))
leijiliuliang=leijiliuliang+(shishiliuliang/60);//(每秒积分)计数累计流量



guzhangjiancejsq=guzhangjiancejsq+jsqLLx;//累加频率的数量,来确定是否故障(停水了)
jsqLLx=0;//清空每秒频率

}else{
   int liuliangjidianping =digitalRead(liuliangji);//读取流量计的电平

   if(liuliangjidianping == HIGH && !chongfupanduanA){ //高电平 且 本次没计数,就计数
jsqLLx++;
    chongfupanduanA=!chongfupanduanA;//本次已计数,则标记已计数
   }

    if(liuliangjidianping == LOW && chongfupanduanA)chongfupanduanA=!chongfupanduanA;//低电平,且 计数标记为1,则重置计数标记
}

}

void jiaohuaB(){

//停水状态的应急处理
if(millis()-guzhangjianceA>30000) {


if(guzhangjiancejsq<210){//3秒累计频率小于21,则说明流量小于1L/min,这个时候认定为停水了



//切换模式之后,对浇花部分进行操作(即停止浇花)
digitalWrite(diancifa, HIGH);//关闭电磁阀
shedingjiaoguanliang=0;//清空设定浇灌量
leijiliuliang=0;//清空累计流量
guzhangjianceA=millis();//同时清空故障检测的时间,否则一开始就是故障状态

}

guzhangjiancejsq=0;//累计频率置0



}

}


卓泰科技 发表于 2016-1-5 09:08:06

大神,为何用GPS?
RTC更简单啊:D

囧囧-科技大神粉 发表于 2016-1-9 09:13:37

卓泰科技 发表于 2016-1-5 09:08
大神,为何用GPS?
RTC更简单啊
用GPS的原因很简单啊

A、我有GPS模块,还不少(至少8个+),都是C3-470B拆下来的,GPS上电池是报废了的,所以我全部把电池去掉了(默认是2006年的货, SIRFIII芯片)

B、我同样有RTC,不过常年不用,估计电池同样也报废了,与其用时间不太可靠的RTC,还不如直接用精确的卫星时间呢


C、我还在考虑弄个小的,那种塑料的太阳能板,通过电压来区分白天黑夜,晚上单片机全部断电休息,这样即便是单片机奔溃导致浇水关不了,那么一段时间后也会重启的PS:说道这里,那么下个版本似乎该固定几个浇花时段,这样一旦出问题,浪费的水可以更少哦!

囧囧-科技大神粉 发表于 2016-1-9 09:15:42

融合浇花程序的草稿版

桌泰的GPS要是能设置只输出GPRMC,也可以来测试一下,这个,改几个参数就能用了

//输出控制:
//调试信息
#define tiaoshixinxi
#define tiaoshixinxi2

#include<EEPROM.h>
int EEPROMvalue; //EEPROM的值
char EEPROMtemp;
/*
设置格式如下
hhmmss,ddmmyy,A,B,C,D,E

A=数字1(0-127) 为由存储时间开始,间隔多少个单位时间浇水一次
B=数字2(0-127) 每次浇水多少个单位体积
C=数字3(0-127) 1单位时间=x*10min
D=数字4(0-127) 1单位体积=x*1L
D=数字5(0-127) 索引,如果分每条分配25字节,那么撑死能记录39条浇水记录

(浇水记录)程序存储格式如下

hhmmss,ddmmyy,A,B
A=数字1(48-49) 48未完毕 49已完毕
B=数字2(0-127) 已经浇水的单位体积

*/


#include <SoftwareSerial.h>
SoftwareSerial gps(8, 9); // RX, TX

char tempx;//提取GPS的时间到tempx数组中hhmmss,ddmmyy


char GPRMC;//临时数组1,放gps数据的
unsigned long gpstimes;//gps计时器,如果超过一定时间10ms,则证明gps数据已经发送完毕
unsigned long quanjujishu;//全局计数,计算1秒之内,循环了多少次,这个次数在一定程度上表示了剩余性能
boolean konghangpanduan=1;//空行判断,因为在读取串口数据后并没有延迟,完全依赖全局循环,那么,特定程序是否执行,就全靠布尔量来标记了
int jsq1=0;


String jianyan="";//GPS数据包的ASCII异或校验
int yihuoyunsuan;//异或运算——校验结果
boolean jiaoyanjieguo=0;//校验结果
boolean dingweiok=0;//定位有效
boolean ruanchuankouchongqi=0;//重启软串口1次,无效时 冷启动GPS
int feiyuqileijiA=0;//非预期累积A,对应gps输出不是GGA 或 RMC时,累积到30次,定义GPS输出1次
int feiyuqileijiB=0;//非预期累积B,对应异或验证不能通过的情况,累积到30次,重启软串口1次,无效时 冷启动GPS 1次
int feiyuqileijiC=0;//非预期累积C,对应RMC长时间不能定位的情况,累积到10次,通过检查年数10位是否为默认值,来确定时间是否可用

boolean TimeOK=0;
int jilusuoyin=0;//记录索引
long shijijiangeshijian=0;//实际间隔时间
long yushejiangeshijian=0;//预设间隔时间


int daijiaoguanliang=0;//待浇灌量
boolean jiaohuakaishi=0;//浇花开始

///////////////////////////////////////////////////////
//浇花的一些定义
///////////////////////////////////////////////////////
int liuliangji=10;
int diancifa=11;
unsigned long meimiaoyilunhui;//每秒一轮回

boolean chongfupanduanA=0;//重复判定A

int jsqLLx=0;
float shishiliuliang=0;//实时流量
float leijiliuliang=0;//累计流量


unsigned long guzhangjianceA;//故障检测
int guzhangjiancejsq;//故障检测计数器
//////////////////////////////////////////////////////////////////////



void setup() {
gps.begin(19200);
Serial.begin(19200);


//EEPROM预处理
/*
设置格式如下
hhmmss,ddmmyy,A,B,C,D,E
000000,010116,60,20,12,10,0
A=数字1(0-127) 为由存储时间开始,间隔多少个单位时间浇水一次,默认设置为60(60*120min=5天)
B=数字2(0-127) 每次浇水多少个单位体积,默认数值为20,(20*10L=200L),对应ASCII的字符是 DC4 (device control 4) 设备控制4
C=数字3(0-127) 1时间单位=x*10min,默认数值为12
D=数字4(0-127) 1单位体积=x*1L 默认数值是10,对应ASCII的字符是 LF (NL line feed, new line) 换行键
E=数字5(0-127) 索引,如果分每条分配25字节,那么撑死能记录39条浇水记录,默认为字符0,ascII=48


(浇水记录)程序存储格式如下

hhmmss,ddmmyy,A,B
A=数字1(48-49) 48未完毕 49已完毕
B=数字2(0-127) 已经浇水的单位体积

*/
        for(int col=0;col<24;col++) EEPROMtemp = EEPROM.read(col);//读取预设参数
       
        //打印预设参数
                                Serial.println();
                                Serial.println();
                                for(int col=0;col<14;col++)Serial.print(EEPROMtemp);
                                int x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                Serial.println(EEPROMtemp);
                               
       
        jilusuoyin=EEPROMtemp-48;//把索引数字化
       
        if(jilusuoyin<40 && jilusuoyin>0){
                //每条记录分配25字节空间,jilusuoyin为最近记录的首地址
                for(int col=0;col<13;col++) EEPROMtemp = EEPROM.read(col+jilusuoyin*25);//更新至最近一次的浇水时间
               
                                for(int col=0;col<13;col++)Serial.print(EEPROMtemp);
                               
                                //打印记录
                               
                                  Serial.write(EEPROM.read(13+jilusuoyin*25)); //直接打出数字对应的ASCII码
                                  Serial.write(EEPROM.read(14+jilusuoyin*25));
                                  Serial.write(EEPROM.read(15+jilusuoyin*25));
                               
                                x=EEPROM.read(16+jilusuoyin*25);
                                Serial.println(x);
                                Serial.println("setup end");
                               

       }
       
       
       
       
       

}



// the loop routine runs over and over again forever:
void loop() {

if(jiaohuakaishi){
       
                //具体浇花程序
                jiaohua();
                       
}else{
       
       
        while (gps.available() > 0 && !TimeOK) {
        gpstimes=millis();//重置gpstimes为millis()
        konghangpanduan=0;//因为串口有数据,所以空行判断为0,即不空行
        GPRMC = gps.read();//软串口读取GPS数据,并保存在临时数组GPRMC中
        if(jsq1<99)jsq1++;//确保GPS跑飞时,或设置不当时,单片机自身数组不溢出
        delayMicroseconds(500);
        }



        if(millis()-gpstimes>20 && !konghangpanduan){
        konghangpanduan=1;
        gpsyihuojianyan();//异或运算,校验GPS输出字符串的准确性
        tiqushijian();//提取时间,装入tempx, 存储格式如下 hhmmss,ddmmyy
        }
       


        //在取得时间的情况下,讨论是否启动浇花程序
        if(TimeOK){
        TimeOK=0;
       
        qidongjiaohuadepanduan();
        }


       
       
       
}







}






void gpsyihuojianyan()
{

//异或运算,校验GPS输出字符串的准确性



//然而最终的jsq1 与实际的GPRMC的关系究竟如何,还是以实际调试为准
//手中这个jsq1就比GPRMC实际长度大2,估摸着换行符占了一位,但打印不显示,而程序在
//GPS串口传输完毕后,还对jsq1加了1,$ *XX不参与异或运算,第一位$ 所在数组为0

/*

        Serial.print("jsq1= ");
        Serial.println(jsq1);
        Serial.println(GPRMC);
        */

for(int col=1;col<jsq1-5;col++){
if(col==1)yihuoyunsuan=GPRMC;
else yihuoyunsuan=yihuoyunsuan ^ GPRMC;
}
//因为定义int的时候,yihuoyunsuan的结果是以10进制DEC表示的,所以需转换为16进制HEX
//因为GPS校验数据0位也进行了传输,所以在转换的时候有必要将情况分类讨论
//(yihuoyunsuan=0)/(0<yihuoyunsuan<17)/(17<yihuoyunsuan)
if(yihuoyunsuan==0){
//校验数10进制为0,直接填充字符串00
jianyan="00";
}else if(yihuoyunsuan>15){
//此时转换为16进制以后,天然有2位,很理想,不用处理
jianyan = String(yihuoyunsuan,HEX);
}else{
//校验数10进制为1-15时,转换为16进制就只有1位数,所以需要在前面填0
jianyan = "0";
jianyan += String(yihuoyunsuan,HEX);
}
//实践中发现,jianyan中的字符是以小写方式存在,虽然Serial.println(yihuoyunsuan,HEX)会以大写方式打印出来
//但直接Serial.println(jianyan)就是小写的,这是啥情况?
//将其字母转换为大写,否则与GPS传输的校验码对比时大小写问题校验失败(GPS传输的校验码为大写的)
jianyan.toUpperCase();
///////////////////////////////////////////显示异或校验码,方便给GPS编程,虽然还没成功过

        /*
        Serial.print("jianyan= ");
        Serial.println(jianyan);
        Serial.print("jsq1= ");
        Serial.println(jsq1);
        Serial.println(GPRMC);
        */

if(jianyan==GPRMC && jianyan==GPRMC ){
//一致,则说明数据是有效的,输出校验结果
jiaoyanjieguo=1;
feiyuqileijiB=0;
ruanchuankouchongqi=0;//优先通过重启软串口解决校验不过的情况,不行能解决再冷启动GPS
}else{
//不一致
jiaoyanjieguo=0;
feiyuqileijiB++;
}
//对校验数组进行清零
jianyan="";

/*---------------------------异或运算,校验GPS输出字符串的准确性 end--------------------------*/


}


void tiqushijian()
{
   //提取时间,装入tempx, 存储格式如下 hhmmss,ddmmyy
   //并通过GPS命令操作,在信号不好时RMC、GGA的切换,GPS的重启
       
       
       
        if(jiaoyanjieguo){ //通过异或校验的情况下,检查定位情况
                jiaoyanjieguo=0;
               
               
                #ifdef tiaoshixinxi
                Serial.println(GPRMC);
                #endif
               
                //检查语句 RMC
                if(GPRMC=='M' && GPRMC=='C'){
                       
                        feiyuqileijiA=0;
                       
                        //RMC 已定位标志判断
                        //$GPRMC,044344.858,V,0000.0000,N,00000.0000,E,,,030116,,*19
                        //$GPRMC,044342.000,A,0000.0000,N,00000.0000,E,0.00,,030116,,*1D
                        if(GPRMC=='A'){
                                feiyuqileijiC=0;
                                dingweiok=1;
                        }else feiyuqileijiC++; //对应RMC长时间不能定位的情况
                       

                       
                               //对应RMC长时间不能定位的情况,900秒不定位,冷启动gps
               
                                if(feiyuqileijiC>900){
                                        feiyuqileijiC=0;
                                        gps.println("$PSRF101,0,0,0,000,0,0,12,4*10");//GPS COLD START
                                }
               

                        if(dingweiok || feiyuqileijiC>10){ //当GPS已定位,或虽未定位,但已经经过10秒
                                dingweiok=0;
                               
                               
                               
                                //提取GPS的时间到tempx数组中hhmmss,ddmmyy
                                //$GPRMC,044342.000,A,0000.0000,N,00000.0000,E,0.00,,030116,,*1D
                                for(int col=0;col<7;col++)tempx=GPRMC;//时间位置固定,可直接提取
                                //日期稍微麻烦点,计算标志位","这个符号的位置,来规避长度变换(实际航速、实际航迹向这2个不确定因素)
                               
                                int col2=0;
                                for(int col=0;col<jsq1-3;col++){
                                        if(GPRMC==',')col2++;
                                       
                                        if(col2==9){
                                                /*
                                                Serial.print("GPRMC=");
                                                Serial.print(GPRMC);
                                                Serial.print(" GPRMC= ");
                                                Serial.println(GPRMC);
                                                //当gps信号弱,不能定位,通过检查gps 给出的年月日,是否是默认的160406ddmmyy,来判断时间的可用性,即年十位不为0
                                                GPRMC 是年的10位,GPRMC 是年的个位,默认是06年,现在是16年,只要十位不是0(ascII大于48),那么就算时间可信
                                                */
                                                if(GPRMC>48){
                                                        feiyuqileijiC=0;
                                                        TimeOK=1;//时间可用标志
                                                        gps.end();//提取时间后关闭软串口
                                                        for(int col3=0;col3<7;col3++)tempx=GPRMC;//提取时间
                                                        col=jsq1-3;//跳出循环
                                                       
                                                }
                                               
                                       
                                        }
                                       
                                }
                               
                               
                                /*
                                //Serial.print(" TimeOK ");
                                Serial.print("tempx=");
                                Serial.println(tempx);
                                Serial.print("tempx=");
                                Serial.println(tempx);
                               
                                if(tempx==44)Serial.print("tempx=44 ");
                                if(tempx+2>44)Serial.print("tempx+2>44 ");
                                int col=tempx;
                                Serial.print("col=");
                                Serial.println(col);
                                */

                               
                               
                        }
                       
                }else feiyuqileijiA++;//对应gps输出不是 RMC时
                       
                       
               


       
        }

        if(feiyuqileijiA>30){ //对应gps输出不是 RMC时,累积到30次,定义GPS输出1次
                feiyuqileijiA=0;
                gps.println("$PSRF109,NMEA19200,NULL38400,GGA0,GLL0,GSA0,GSV0,RMC1,VTG0,USER0*32");       
               
        }
       
        if(feiyuqileijiB>30){ //对应异或验证不能通过的情况,累积到30次,重启软串口1次,无效时 冷启动GPS 1次
                feiyuqileijiB=0;
               
                if(!ruanchuankouchongqi){ //优先重启软串口,ruanchuankouchongqi默认为0
                        ruanchuankouchongqi=!ruanchuankouchongqi;
                        gps.end();
                       
                        gps.begin(19200);
                       
                }else{
                        ruanchuankouchongqi=!ruanchuankouchongqi;
                        gps.println("$PSRF101,0,0,0,000,0,0,12,4*10");//GPS COLD START
               
                }
               
        }
       


/*
        Serial.print("feiyuqileijiA=");
        Serial.print(feiyuqileijiA);
        Serial.print(" feiyuqileijiB= ");
        Serial.print(feiyuqileijiB);
        Serial.print(" feiyuqileijiC= ");
        Serial.print(feiyuqileijiC);
        Serial.println(GPRMC);
*/

        //收尾工作,清空GPS数组,jsq1归零
        for(int col=0;col<100;col++)GPRMC=0;
    jsq1=0;

}


void qidongjiaohuadepanduan()//启动浇花的判断
{
       
/*
EEPROM设置格式如下
hhmmss,ddmmyy,A, B,C, D,E
000000,010116,60,20,12,10,0
A=数字1(0-127) 为由存储时间开始,间隔多少个单位时间浇水一次,默认设置为60(60*120min=5天)
B=数字2(0-127) 每次浇水多少个单位体积,默认数值为20,(20*10L=200L),对应ASCII的字符是 DC4 (device control 4) 设备控制4
C=数字3(0-127) 1时间单位=x*10min,默认数值为12
D=数字4(0-127) 1单位体积=x*1L 默认数值是10,对应ASCII的字符是 LF (NL line feed, new line) 换行键
E=数字5(0-127) 索引,如果分每条分配25字节,那么撑死能记录39条浇水记录,默认为字符0,ascII=48


(浇水记录)程序存储格式如下

hhmmss,ddmmyy,A,B
A=数字1(48-49) 48未完毕 49已完毕
B=数字2(0-127) 已经浇水的单位体积
*/

        //进行浇花有2种情况, A、上次浇花因中断,现在继续 B、间隔时间到了,应该浇花
        //情况A
        /*对记录位进行初始化
        hhmmss,ddmmyy,A,B
        A=数字1(48-49) 48未完毕 49已完毕
        B=数字2(0-127) 已经浇水的单位体积
        */
        if(jilusuoyin > 0){//上次未完成的情况(索引大于0才可能有存在)
                               
                        //上次未完成,浇花开始
                        if(EEPROM.read(14+jilusuoyin*25)==48){
                       
                        jiaohuakaishi=1;
                       
                        //浇花开始前的一些准备工作
                        guzhangjianceA=millis();//清掉故障检测与millis间的时间差距,否则一开始就是故障状态
                        meimiaoyilunhui=millis();//每一秒还原一次
                        }
       
        }else if(millis()-quanjujishu>3000){ //讨论因间隔时间到了的浇花,情况,另外的间隔是定义的多久打开串口读取gps 数据一次,为方便调试,这里取3秒
               
                                //情况B,一个全新的开始
                                //时间到了的情况,EEPROMtemp*EEPROMtemp 个10min就是间隔,最大127*127,约2688小时,最小10min
                               
                        quanjujishu=millis();
                               
                        gps.begin(19200);
                               
                        //shijijiangeshijian=计算上次浇水时间到现在,经理过多少个10min                               
                        long niancha=(tempx-EEPROMtemp)*10*365*24*6+(tempx-EEPROMtemp)*365*24*6;
                        long yuecha=(tempx-EEPROMtemp)*10*30*24*6+(tempx-EEPROMtemp)*30*24*6;
                        long richa=(tempx-EEPROMtemp)*10*24*6+(tempx-EEPROMtemp)*24*6;
                        long shicha=(tempx-EEPROMtemp)*10*6+(tempx-EEPROMtemp)*6;
                        shijijiangeshijian=niancha+yuecha+richa+shicha+tempx-EEPROMtemp;
                                               
                        //预设间隔时间 = 间隔多少个单位时间 X 每个单位代表的时间(X * 10min)
                        yushejiangeshijian=EEPROMtemp*EEPROMtemp;
               
                if(shijijiangeshijian > yushejiangeshijian){
                                                       
                        if(jilusuoyin<39)jilusuoyin++;
                        else jilusuoyin=1;
               
                        EEPROM.write(22, jilusuoyin+48);//更新EEPROM中的索引数值=原值+1,等于39的情况归0
               
                        for(int col=0;col<13;col++) EEPROMtemp = tempx;//更新预设数组中的时间
                        for(int col=0;col<13;col++) EEPROM.write(col+jilusuoyin*25, tempx);//更新EEPROM中的时间
                       
                        /*对记录位进行初始化
                        hhmmss,ddmmyy,A,B
                        A=数字1(48-49) 48未完毕 49已完毕
                        B=数字2(0-127) 已经浇水的单位体积
                        */
                                EEPROM.write(13+jilusuoyin*25, ',');//,
                                EEPROM.write(14+jilusuoyin*25, 48);//A
                                EEPROM.write(15+jilusuoyin*25, ',');//,
                                EEPROM.write(16+jilusuoyin*25, 0);//B

                        //浇花开始
                        jiaohuakaishi=1;
                       
                        //浇花开始前的一些准备工作
                        guzhangjianceA=millis();//清掉故障检测与millis间的时间差距,否则一开始就是故障状态
                        meimiaoyilunhui=millis();//每一秒还原一次

                       
                }
               

               
               

               
               
                                #ifdef tiaoshixinxi
                               
                                Serial.print("Detection value=");
                                Serial.println(shijijiangeshijian);
                                Serial.print("   set valuet=");
                                Serial.println(yushejiangeshijian);
                               
                               
                                Serial.println(tempx); //now time
                               
                               
                                for(int col=0;col<14;col++)Serial.print(EEPROMtemp);//set time
                                int x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                Serial.print(EEPROMtemp);
                               
                                Serial.print("V=");
                                Serial.print(EEPROMtemp*EEPROMtemp);
                                Serial.print(" LTime =");
                                Serial.print(EEPROMtemp*EEPROMtemp/6/24);
                                Serial.println(" Day");
               
                                #endif       

        }
               

       
}



void jiaohua()//具体浇花程序
{
       
                        /*对记录位进行初始化
                        hhmmss,ddmmyy,A,B
                        A=数字1(48-49) 48未完毕 49已完毕
                        B=数字2(0-127) 已经浇水的单位体积
                        */
               
        //读取已浇灌体积,与预设浇灌体积相减,计算待浇灌量
        int yijiaoguanliang=EEPROM.read(16+jilusuoyin*25);
        daijiaoguanliang=EEPROMtemp-yijiaoguanliang;

       
       
        //累积流量达到一定值后,对EEPROM中的已浇灌量进行更新
        if(leijiliuliang>10){
                leijiliuliang=leijiliuliang-10;
                yijiaoguanliang++;
                EEPROM.write(16+jilusuoyin*25, yijiaoguanliang);
        }
       
               
        if(daijiaoguanliang<1){                       
                        jiaohuakaishi=0;//浇水完毕后跳出浇水循环
                        EEPROM.write(14+jilusuoyin*25, 49);//将本次浇花已完成写入EEPROM
                       
                        digitalWrite(diancifa, HIGH);//关闭电磁阀
                        leijiliuliang=0;//清空累计流量
                       
                       gps.begin(19200);//重新打开软串口

        }else digitalWrite(diancifa, LOW);//累计流量小于设定流量,打开电磁阀
               
               
//正常的浇花部分
//浇花主程序///////////////////////////////////////////////////////////

//每秒频率测定,实时流量计算,累计流量叠加
        if(millis()-meimiaoyilunhui>1000) {

                meimiaoyilunhui=millis();//每一秒还原一次
                shishiliuliang=jsqLLx/7.5;//计算实时流量(公式:频率=7.5*流量(L/min))
                leijiliuliang=leijiliuliang+(shishiliuliang/60);//(每秒积分)计数累计流量

                guzhangjiancejsq=guzhangjiancejsq+jsqLLx;//累加频率的数量,来确定是否故障(停水了)
                jsqLLx=0;//清空每秒频率
               
       
                #ifdef tiaoshixinxi2
                                Serial.print("yijiaoguanliang=");
                                Serial.print(yijiaoguanliang); //已浇灌量
                               
                                Serial.print(" daijiaoguanliang=");
                                Serial.print(daijiaoguanliang); //待浇灌量
                               
                                Serial.print(" shishiliuliang=");
                                Serial.print(shishiliuliang); //实时流量
                               
                                Serial.print(" leijiliuliang=");
                                Serial.println(leijiliuliang); //累计流量
               
                               
                                Serial.println(tempx); //now time
                               
                               
                               
                                for(int col=0;col<14;col++)Serial.print(EEPROMtemp);//set time
                                int x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp;
                                Serial.print(x);
                                Serial.print(",");
                                Serial.print(EEPROMtemp);
                               
                                Serial.print("V=");
                                Serial.print(EEPROMtemp*EEPROMtemp);
                                Serial.print(" LTime =");
                                Serial.print(EEPROMtemp*EEPROMtemp/6/24);
                                Serial.println(" Day");
                               
                                Serial.println();
                               
                               
                       
               
                                #endif       
               

        }else{
                int liuliangjidianping =digitalRead(liuliangji);//读取流量计的电平

                if(liuliangjidianping == HIGH && !chongfupanduanA){ //高电平 且 本次没计数,就计数
                        jsqLLx++;
                        chongfupanduanA=!chongfupanduanA;//本次已计数,则标记已计数
                }

                if(liuliangjidianping == LOW && chongfupanduanA)chongfupanduanA=!chongfupanduanA;//低电平,且 计数标记为1,则重置计数标记
        }



//通过3秒的频率次数的累加,来判断是否停水了(防止电池阀在没水的时候长期运行)
//停水状态的应急处理
        if(millis()-guzhangjianceA>9000) {
               
                guzhangjianceA=millis();//同时清空故障检测的时间,否则一开始就是故障状态

                if(guzhangjiancejsq<63){//3秒累计频率小于21,(9秒63),则说明流量小于1L/min,这个时候认定为停水了
               

               

                //对浇花部分进行操作(即停止浇花)
                digitalWrite(diancifa, HIGH);//关闭电磁阀
               
                //leijiliuliang=0;//清空累计流量,这步没必要,因为只要不断电,来水之后是可以接着计算的
               
                jiaohuakaishi=0;//跳出浇水循环
               
                                for(int col=0;col<12;col++){
                        Serial.println("GAME OVER");
                        delay(1000);//对应一个延迟,1小时
                }
               

                }

        guzhangjiancejsq=0;//累计频率置0
       
       gps.begin(19200);//重新打开软串口
       
        }



       
                       
                       


}






卓泰科技 发表于 2016-1-10 19:52:10

囧囧-科技大神粉 发表于 2016-1-9 09:13
用GPS的原因很简单啊

A、我有GPS模块,还不少(至少8个+),都是C3-470B拆下来的,GPS上电池是报废了的, ...


5555,我用RTC换你GPS,中不?:'(
页: [1]
查看完整版本: 重新玩GPS