请选择 进入手机版 | 继续访问电脑版

狗趴(GodPub),开源硬件学习与实践

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
热搜: 活动 交友 discuz
查看: 9464|回复: 7

重新玩GPS

[复制链接]

5

主题

36

帖子

141

积分

QQ群用户

积分
141
发表于 2016-1-4 23:34:15 | 显示全部楼层 |阅读模式
起因:20来好要滚去海南呆一阵子,家里没人,担心小花小草全灭,所以打算搞一个自动浇花的

原理非常简单

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

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

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

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

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




5

主题

36

帖子

141

积分

QQ群用户

积分
141
 楼主| 发表于 2016-1-4 23:36:12 | 显示全部楼层
先上EEPROM初始化化程序,写入最初始的设定

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

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

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

  15. */

  16. #include <EEPROM.h>

  17. char EEPROMtemp[25];

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


  31. //000000,010116,
  32.     EEPROM.write(0, '0');
  33.     EEPROM.write(1, '0');
  34.     EEPROM.write(2, '0');
  35.     EEPROM.write(3, '0');
  36.     EEPROM.write(4, '0');
  37.     EEPROM.write(5, '0');
  38.    
  39.         EEPROM.write(6, ',');

  40.     EEPROM.write(7, '0');
  41.     EEPROM.write(8, '1');
  42.     EEPROM.write(9, '0');
  43.     EEPROM.write(10, '1');
  44.     EEPROM.write(11, '1');
  45.     EEPROM.write(12, '6');
  46.        
  47.         EEPROM.write(13, ',');
  48.                        
  49. //60,20,12,10,0
  50. EEPROM.write(14,60);
  51. EEPROM.write(15, ',');

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

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

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

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


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

  62. void loop()
  63. {
  64.        
  65.                                         for(int col=0;col<14;col++)Serial.print(EEPROMtemp[col]);
  66.                                 int x=EEPROMtemp[14];
  67.                                 Serial.print(x);
  68.                                 Serial.print(",");
  69.                                 x=EEPROMtemp[16];
  70.                                 Serial.print(x);
  71.                                 Serial.print(",");
  72.                                 x=EEPROMtemp[18];
  73.                                 Serial.print(x);
  74.                                 Serial.print(",");
  75.                                 x=EEPROMtemp[20];
  76.                                 Serial.print(x);
  77.                                 Serial.print(",");
  78.                                 Serial.println(EEPROMtemp[22]);
  79.                                
  80.                                  delay(3000);
  81.                                
  82. }
复制代码


5

主题

36

帖子

141

积分

QQ群用户

积分
141
 楼主| 发表于 2016-1-4 23:37:00 | 显示全部楼层
主程序来了,浇花部分还没上呢


  1. //输出控制:
  2. //调试信息
  3. //#define tiaoshixinxi


  4. #include<EEPROM.h>
  5. int EEPROMvalue; //EEPROM的值
  6. char EEPROMtemp[25];
  7. /*
  8. 设置格式如下
  9. hhmmss,ddmmyy,A,B,C,D,E

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

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

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

  19. */


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

  22. char tempx[15];//提取GPS的时间到tempx数组中  hhmmss,ddmmyy


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


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

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


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


  42. void setup() {
  43. gps.begin(19200);
  44. Serial.begin(19200);


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


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

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

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

  70. }



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

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



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


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


  100.        
  101. }







  102. }






  103. void gpsyihuojianyan()
  104. {

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



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

  109. /*

  110.         Serial.print("jsq1= ");
  111.         Serial.println(jsq1);
  112.         Serial.println(GPRMC);
  113.         */

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

  137.         /*
  138.         Serial.print("jianyan= ");
  139.         Serial.println(jianyan);
  140.         Serial.print("jsq1= ");
  141.         Serial.println(jsq1);
  142.         Serial.println(GPRMC);
  143.         */

  144. if(jianyan[0]==GPRMC[jsq1-4] && jianyan[1]==GPRMC[jsq1-3] ){
  145. //一致,则说明数据是有效的,输出校验结果
  146. jiaoyanjieguo=1;
  147. feiyuqileijiB=0;
  148. ruanchuankouchongqi=0;//优先通过重启软串口解决校验不过的情况,不行能解决再冷启动GPS
  149. }else{
  150. //不一致
  151. jiaoyanjieguo=0;
  152. feiyuqileijiB++;
  153. }
  154. //对校验数组进行清零
  155. jianyan="";

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


  157. }


  158. void tiqushijian()
  159. {
  160.    //提取时间,装入tempx, 存储格式如下 hhmmss,ddmmyy
  161.    //并通过GPS命令操作,在信号不好时RMC、GGA的切换,GPS的重启
  162.        
  163.        
  164.        
  165.         if(jiaoyanjieguo){ //通过异或校验的情况下,检查定位情况
  166.                 jiaoyanjieguo=0;
  167.                
  168.                
  169.                 #ifdef tiaoshixinxi
  170.                 Serial.println(GPRMC);
  171.                 #endif
  172.                
  173.                 //检查语句 RMC
  174.                 if(GPRMC[4]=='M' && GPRMC[5]=='C'){
  175.                        
  176.                         feiyuqileijiA=0;
  177.                        
  178.                         //RMC 已定位标志判断
  179.                         //$GPRMC,044344.858,V,0000.0000,N,00000.0000,E,,,030116,,*19
  180.                         //$GPRMC,044342.000,A,0000.0000,N,00000.0000,E,0.00,,030116,,*1D
  181.                         if(GPRMC[18]=='A'){
  182.                                 feiyuqileijiC=0;
  183.                                 dingweiok=1;
  184.                         }else feiyuqileijiC++; //对应RMC长时间不能定位的情况
  185.                        

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

  194.                         if(dingweiok || feiyuqileijiC>10){ //当GPS已定位,或虽未定位,但已经经过10秒
  195.                                 dingweiok=0;
  196.                                
  197.                                
  198.                                
  199.                                 //提取GPS的时间到tempx数组中  hhmmss,ddmmyy
  200.                                 //$GPRMC,044342.000,A,0000.0000,N,00000.0000,E,0.00,,030116,,*1D
  201.                                 for(int col=0;col<7;col++)tempx[col]=GPRMC[col+7];//时间位置固定,可直接提取
  202.                                 //日期稍微麻烦点,计算标志位“,”这个符号的位置,来规避长度变换(实际航速、实际航迹向这2个不确定因素)
  203.                                
  204.                                 int col2=0;
  205.                                 for(int col=0;col<jsq1-3;col++){
  206.                                         if(GPRMC[col]==',')col2++;
  207.                                        
  208.                                         if(col2==9){
  209.                                                 /*
  210.                                                 Serial.print("GPRMC[col+5]=");
  211.                                                 Serial.print(GPRMC[col+5]);
  212.                                                 Serial.print(" GPRMC[col+6]= ");
  213.                                                 Serial.println(GPRMC[col+6]);
  214.                                                 //当gps信号弱,不能定位,通过检查gps 给出的年月日,是否是默认的160406  ddmmyy  ,来判断时间的可用性,即年十位不为0
  215.                                                 GPRMC[col+5] 是年的10位,GPRMC[col+6] 是年的个位,默认是06年,现在是16年,只要十位不是0(ascII大于48),那么就算时间可信
  216.                                                 */
  217.                                                 if(GPRMC[col+5]>48){
  218.                                                         feiyuqileijiC=0;
  219.                                                         TimeOK=1;//时间可用标志
  220.                                                         gps.end();//提取时间后关闭软串口
  221.                                                         for(int col3=0;col3<7;col3++)tempx[6+col3]=GPRMC[col+col3];//提取时间
  222.                                                         col=jsq1-3;//跳出循环
  223.                                                        
  224.                                                 }
  225.                                                
  226.                                        
  227.                                         }
  228.                                        
  229.                                 }
  230.                                
  231.                                
  232.                                 /*
  233.                                 //Serial.print(" TimeOK ");
  234.                                 Serial.print("tempx=");
  235.                                 Serial.println(tempx);
  236.                                 Serial.print("tempx[6]=");
  237.                                 Serial.println(tempx[6]);
  238.                                
  239.                                 if(tempx[6]==44)Serial.print("tempx[6]=44 ");
  240.                                 if(tempx[6]+2>44)Serial.print("tempx[6]+2>44 ");
  241.                                 int col=tempx[6];
  242.                                 Serial.print("col=");
  243.                                 Serial.println(col);
  244.                                 */

  245.                                
  246.                                
  247.                         }
  248.                        
  249.                 }else feiyuqileijiA++;//对应gps输出不是 RMC时
  250.                        
  251.                        
  252.                


  253.        
  254.         }

  255.         if(feiyuqileijiA>30){ //对应gps输出不是 RMC时,累积到30次,定义GPS输出1次
  256.                 feiyuqileijiA=0;
  257.                 gps.println("$PSRF109,NMEA19200,NULL38400,GGA0,GLL0,GSA0,GSV0,RMC1,VTG0,USER0*32");       
  258.                
  259.         }
  260.        
  261.         if(feiyuqileijiB>30){ //对应异或验证不能通过的情况,累积到30次,重启软串口1次,无效时 冷启动GPS 1次
  262.                 feiyuqileijiB=0;
  263.                
  264.                 if(!ruanchuankouchongqi){ //优先重启软串口,ruanchuankouchongqi默认为0
  265.                         ruanchuankouchongqi=!ruanchuankouchongqi;
  266.                         gps.end();
  267.                        
  268.                         gps.begin(19200);
  269.                        
  270.                 }else{
  271.                         ruanchuankouchongqi=!ruanchuankouchongqi;
  272.                         gps.println("$PSRF101,0,0,0,000,0,0,12,4*10");//GPS COLD START
  273.                
  274.                 }
  275.                
  276.         }
  277.        


  278. /*
  279.         Serial.print("feiyuqileijiA=");
  280.         Serial.print(feiyuqileijiA);
  281.         Serial.print(" feiyuqileijiB= ");
  282.         Serial.print(feiyuqileijiB);
  283.         Serial.print(" feiyuqileijiC= ");
  284.         Serial.print(feiyuqileijiC);
  285.         Serial.println(GPRMC);
  286. */

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

  290. }


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


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

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

  308.         //进行浇花有2种情况, A、上次浇花因中断,现在继续 B、间隔时间到了,应该浇花
  309.         //情况A
  310.         /*对记录位进行初始化
  311.         hhmmss,ddmmyy,A,B
  312.         A=数字1(48-49) 48未完毕 49已完毕
  313.         B=数字2(0-127) 已经浇水的单位体积
  314.         */
  315.         if(jilusuoyin > 0){//上次未完成的情况(索引大于0才可能有存在)
  316.                                
  317.                         //上次未完成,浇花开始
  318.                         if(EEPROM.read(14+jilusuoyin*25)==48)jiaohuakaishi=1;
  319.                        
  320.         }else if(millis()-quanjujishu>3000){ //讨论因间隔时间到了的浇花,情况,另外的间隔是定义的多久打开串口读取gps 数据一次,为方便调试,这里取3秒
  321.                
  322.                                 //情况B,一个全新的开始
  323.                                 //时间到了的情况,EEPROMtemp[14]*EEPROMtemp[18] 个10min就是间隔,最大127*127,约2688小时,最小10min
  324.                                
  325.                         quanjujishu=millis();
  326.                                
  327.                         gps.begin(19200);
  328.                                
  329.                         //shijijiangeshijian=计算上次浇水时间到现在,经理过多少个10min                               
  330.                         long niancha=(tempx[11]-EEPROMtemp[11])*10*365*24*6+(tempx[12]-EEPROMtemp[12])*365*24*6;
  331.                         long yuecha=(tempx[9]-EEPROMtemp[9])*10*30*24*6+(tempx[10]-EEPROMtemp[10])*30*24*6;
  332.                         long richa=(tempx[7]-EEPROMtemp[7])*10*24*6+(tempx[8]-EEPROMtemp[8])*24*6;
  333.                         long shicha=(tempx[0]-EEPROMtemp[0])*10*6+(tempx[1]-EEPROMtemp[1])*6;
  334.                         shijijiangeshijian=niancha+yuecha+richa+shicha+tempx[2]-EEPROMtemp[2];
  335.                                                
  336.                         //预设间隔时间 = 间隔多少个单位时间 X 每个单位代表的时间(X * 10min)
  337.                         yushejiangeshijian=EEPROMtemp[14]*EEPROMtemp[18];
  338.                
  339.                 if(shijijiangeshijian > yushejiangeshijian){
  340.                                                        
  341.                         if(jilusuoyin<39)jilusuoyin++;
  342.                         else jilusuoyin=1;
  343.                
  344.                         EEPROM.write(22, jilusuoyin+48);//更新EEPROM中的索引数值=原值+1,等于39的情况归0
  345.                
  346.                         for(int col=0;col<13;col++) EEPROMtemp[col] = tempx[col];//更新预设数组中的时间
  347.                         for(int col=0;col<13;col++) EEPROM.write(col+jilusuoyin*25, tempx[col]);//更新EEPROM中的时间
  348.                        
  349.                         /*对记录位进行初始化
  350.                         hhmmss,ddmmyy,A,B
  351.                         A=数字1(48-49) 48未完毕 49已完毕
  352.                         B=数字2(0-127) 已经浇水的单位体积
  353.                         */
  354.                                 EEPROM.write(13+jilusuoyin*25, ',');//,
  355.                                 EEPROM.write(14+jilusuoyin*25, 48);//A
  356.                                 EEPROM.write(15+jilusuoyin*25, ',');//,
  357.                                 EEPROM.write(16+jilusuoyin*25, 0);//B

  358.                         //浇花开始
  359.                         jiaohuakaishi=1;
  360.                
  361.                        
  362.                 }
  363.                
  364.                                 #ifdef tiaoshixinxi
  365.                                
  366.                                 Serial.print(“Detection value=”);
  367.                                 Serial.println(shijijiangeshijian);
  368.                                 Serial.print(“  set valuet=”);
  369.                                 Serial.println(yushejiangeshijian);
  370.                                
  371.                                 Serial.println(tempx);
  372.                                
  373.                                 for(int col=0;col<14;col++)Serial.print(EEPROMtemp[col]);
  374.                                 int x=EEPROMtemp[14];
  375.                                 Serial.print(x);
  376.                                 Serial.print(",");
  377.                                 x=EEPROMtemp[16];
  378.                                 Serial.print(x);
  379.                                 Serial.print(",");
  380.                                 x=EEPROMtemp[18];
  381.                                 Serial.print(x);
  382.                                 Serial.print(",");
  383.                                 x=EEPROMtemp[20];
  384.                                 Serial.print(x);
  385.                                 Serial.print(",");
  386.                                 Serial.println(EEPROMtemp[22]);
  387.                
  388.                                 #endif       

  389.         }
  390.                

  391.        
  392. }



  393. void jiaohua()//具体浇花程序
  394. {
  395.                
  396.                 //读取已浇灌体积,与预设浇灌体积相减,计算待浇灌量
  397.                 daijiaoguanliang=EEPROMtemp[16]-EEPROM.read(16+jilusuoyin*25);
  398.                        
  399.                        
  400.                        
  401.        
  402. }




复制代码


5

主题

36

帖子

141

积分

QQ群用户

积分
141
 楼主| 发表于 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



}

}


84

主题

143

帖子

725

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
725
QQ
发表于 2016-1-5 09:08:06 | 显示全部楼层
大神,为何用GPS?
RTC更简单啊
天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。

5

主题

36

帖子

141

积分

QQ群用户

积分
141
 楼主| 发表于 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:说道这里,那么下个版本似乎该固定几个浇花时段,这样一旦出问题,浪费的水可以更少哦!

5

主题

36

帖子

141

积分

QQ群用户

积分
141
 楼主| 发表于 2016-1-9 09:15:42 | 显示全部楼层
融合浇花程序的草稿版

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

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

#include<EEPROM.h>
int EEPROMvalue; //EEPROM的值
char EEPROMtemp[25];
/*
设置格式如下
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[15];//提取GPS的时间到tempx数组中  hhmmss,ddmmyy


char GPRMC[100];//临时数组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[col] = EEPROM.read(col);//读取预设参数
       
        //打印预设参数
                                Serial.println();
                                Serial.println();
                                for(int col=0;col<14;col++)Serial.print(EEPROMtemp[col]);
                                int x=EEPROMtemp[14];
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp[16];
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp[18];
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp[20];
                                Serial.print(x);
                                Serial.print(",");
                                Serial.println(EEPROMtemp[22]);
                               
         
        jilusuoyin=EEPROMtemp[22]-48;//把索引数字化
         
        if(jilusuoyin<40 && jilusuoyin>0){
                //每条记录分配25字节空间,jilusuoyin为最近记录的首地址
                for(int col=0;col<13;col++) EEPROMtemp[col] = EEPROM.read(col+jilusuoyin*25);//更新至最近一次的浇水时间
               
                                for(int col=0;col<13;col++)Serial.print(EEPROMtemp[col]);
                               
                                //打印记录
                               
                                  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[jsq1] = 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[col];
else yihuoyunsuan=yihuoyunsuan ^ GPRMC[col];
}
//因为定义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[0]==GPRMC[jsq1-4] && jianyan[1]==GPRMC[jsq1-3] ){
//一致,则说明数据是有效的,输出校验结果
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[4]=='M' && GPRMC[5]=='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[18]=='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[col]=GPRMC[col+7];//时间位置固定,可直接提取
                                //日期稍微麻烦点,计算标志位","这个符号的位置,来规避长度变换(实际航速、实际航迹向这2个不确定因素)
                               
                                int col2=0;
                                for(int col=0;col<jsq1-3;col++){
                                        if(GPRMC[col]==',')col2++;
                                       
                                        if(col2==9){
                                                /*
                                                Serial.print("GPRMC[col+5]=");
                                                Serial.print(GPRMC[col+5]);
                                                Serial.print(" GPRMC[col+6]= ");
                                                Serial.println(GPRMC[col+6]);
                                                //当gps信号弱,不能定位,通过检查gps 给出的年月日,是否是默认的160406  ddmmyy  ,来判断时间的可用性,即年十位不为0
                                                GPRMC[col+5] 是年的10位,GPRMC[col+6] 是年的个位,默认是06年,现在是16年,只要十位不是0(ascII大于48),那么就算时间可信
                                                */
                                                if(GPRMC[col+5]>48){
                                                        feiyuqileijiC=0;
                                                        TimeOK=1;//时间可用标志
                                                        gps.end();//提取时间后关闭软串口
                                                        for(int col3=0;col3<7;col3++)tempx[6+col3]=GPRMC[col+col3];//提取时间
                                                        col=jsq1-3;//跳出循环
                                                       
                                                }
                                               
                                       
                                        }
                                       
                                }
                               
                               
                                /*
                                //Serial.print(" TimeOK ");
                                Serial.print("tempx=");
                                Serial.println(tempx);
                                Serial.print("tempx[6]=");
                                Serial.println(tempx[6]);
                               
                                if(tempx[6]==44)Serial.print("tempx[6]=44 ");
                                if(tempx[6]+2>44)Serial.print("tempx[6]+2>44 ");
                                int col=tempx[6];
                                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[col]=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[14]*EEPROMtemp[18] 个10min就是间隔,最大127*127,约2688小时,最小10min
                               
                        quanjujishu=millis();
                               
                        gps.begin(19200);
                               
                        //shijijiangeshijian=计算上次浇水时间到现在,经理过多少个10min                               
                        long niancha=(tempx[11]-EEPROMtemp[11])*10*365*24*6+(tempx[12]-EEPROMtemp[12])*365*24*6;
                        long yuecha=(tempx[9]-EEPROMtemp[9])*10*30*24*6+(tempx[10]-EEPROMtemp[10])*30*24*6;
                        long richa=(tempx[7]-EEPROMtemp[7])*10*24*6+(tempx[8]-EEPROMtemp[8])*24*6;
                        long shicha=(tempx[0]-EEPROMtemp[0])*10*6+(tempx[1]-EEPROMtemp[1])*6;
                        shijijiangeshijian=niancha+yuecha+richa+shicha+tempx[2]-EEPROMtemp[2];
                                               
                        //预设间隔时间 = 间隔多少个单位时间 X 每个单位代表的时间(X * 10min)
                        yushejiangeshijian=EEPROMtemp[14]*EEPROMtemp[18];
               
                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[col] = tempx[col];//更新预设数组中的时间
                        for(int col=0;col<13;col++) EEPROM.write(col+jilusuoyin*25, tempx[col]);//更新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[col]);//set time
                                int x=EEPROMtemp[14];
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp[16];
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp[18];
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp[20];
                                Serial.print(x);
                                Serial.print(",");
                                Serial.print(EEPROMtemp[22]);
                               
                                Serial.print("  V=");
                                Serial.print(EEPROMtemp[16]*EEPROMtemp[20]);
                                Serial.print(" L  Time =");
                                Serial.print(EEPROMtemp[14]*EEPROMtemp[18]/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[16]-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[col]);//set time
                                int x=EEPROMtemp[14];
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp[16];
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp[18];
                                Serial.print(x);
                                Serial.print(",");
                                x=EEPROMtemp[20];
                                Serial.print(x);
                                Serial.print(",");
                                Serial.print(EEPROMtemp[22]);
                               
                                Serial.print("  V=");
                                Serial.print(EEPROMtemp[16]*EEPROMtemp[20]);
                                Serial.print(" L  Time =");
                                Serial.print(EEPROMtemp[14]*EEPROMtemp[18]/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);//重新打开软串口
       
        }



       
                         
                         


}


84

主题

143

帖子

725

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
725
QQ
发表于 2016-1-10 19:52:10 | 显示全部楼层
囧囧-科技大神粉 发表于 2016-1-9 09:13
用GPS的原因很简单啊

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


5555,我用RTC换你GPS,中不?
天理路上甚宽,稍游心,胸中便觉广大宏朗;
人欲路上甚窄,才寄迹,眼前俱是荆棘泥涂。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|狗趴(GodPub) Arduino&Raspberry Pi开源硬件学习与实践[QQ群:20085629]  

GMT+8, 2024-3-29 04:24 , Processed in 0.196781 second(s), 31 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表