DCCpp
This is the library version of a program for Arduino to control railroading DCC devices.
Sensor.cpp
1 /**********************************************************************
2 
3 Sensor.cpp
4 COPYRIGHT (c) 2013-2016 Gregg E. Berman
5 
6 Part of DCC++ BASE STATION for the Arduino
7 
8 **********************************************************************/
9 
10 #include "Sensor.h"
11 #ifdef USE_SENSOR
12 #include "DCCpp_Uno.h"
13 #include "EEStore.h"
14 #ifdef USE_EEPROM
15 #include "EEPROM.h"
16 #endif
17 #include "Comm.h"
18 
20 
21 void Sensor::begin(int snum, int pin, int pullUp) {
22 #ifdef DCCPP_DEBUG_MODE
23  if (EEStore::eeStore != NULL)
24  {
25  INTERFACE.println(F("Sensor::begin() must be called BEFORE DCCpp.begin() !"));
26  }
27 #endif
28 
29  if (firstSensor == NULL) {
30  firstSensor = this;
31  }
32  else if (get(snum) == NULL) {
33  Sensor *tt = firstSensor;
34  while (tt->nextSensor != NULL)
35  tt = tt->nextSensor;
36  tt->nextSensor = this;
37  }
38 
39  this->set(snum, pin, pullUp);
40 
41 #ifdef USE_TEXTCOMMAND
42  INTERFACE.print("<O>");
43 #if !defined(USE_ETHERNET)
44  INTERFACE.println("");
45 #endif
46 #endif
47 }
48 
50 
51 void Sensor::set(int snum, int pin, int pullUp) {
52  this->data.snum = snum;
53  this->data.pin = pin;
54  this->data.pullUp = (pullUp == 0 ? LOW : HIGH);
55  this->active = false;
56  this->signal = 1;
57 #ifdef VISUALSTUDIO
58  ArduiEmulator::Arduino::dontCheckNextPinAccess = true;
59 #endif
60  digitalWrite(pin, pullUp); // don't use Arduino's internal pull-up resistors for external infrared sensors --- each sensor must have its own 1K external pull-up resistor
61 #ifdef VISUALSTUDIO
62  ArduiEmulator::Arduino::dontCheckNextPinAccess = true;
63 #endif
64  pinMode(pin, INPUT); // force mode to input
65 }
66 
68 
69 Sensor* Sensor::get(int n) {
70  Sensor *tt;
71  for (tt = firstSensor; tt != NULL && tt->data.snum != n; tt = tt->nextSensor);
72  return(tt);
73 }
75 
76 void Sensor::remove(int n) {
77  Sensor *tt, *pp;
78 
79  for (tt = firstSensor; tt != NULL && tt->data.snum != n; pp = tt, tt = tt->nextSensor);
80 
81  if (tt == NULL) {
82 #ifdef USE_TEXTCOMMAND
83  INTERFACE.print("<X>");
84 #if !defined(USE_ETHERNET)
85  INTERFACE.println("");
86 #endif
87 #endif
88  return;
89  }
90 
91  if (tt == firstSensor)
92  firstSensor = tt->nextSensor;
93  else
94  pp->nextSensor = tt->nextSensor;
95 
96  free(tt);
97 
98 #ifdef USE_TEXTCOMMAND
99  INTERFACE.print("<O>");
100 #if !defined(USE_ETHERNET)
101  INTERFACE.println("");
102 #endif
103 #endif
104 }
105 
107 
108 int Sensor::count() {
109  int count = 0;
110  Sensor *tt;
111  for (tt = firstSensor; tt != NULL; tt = tt->nextSensor)
112  count++;
113  return count;
114 }
115 
117 
118 void Sensor::check(){
119  Sensor *tt;
120 
121  for(tt=firstSensor;tt!=NULL;tt=tt->nextSensor){
122  tt->signal=(float)(tt->signal*(1.0-SENSOR_DECAY)+digitalRead(tt->data.pin)*SENSOR_DECAY);
123 
124  if(!tt->active && tt->signal<0.5){
125  tt->active=true;
126  INTERFACE.print("<Q");
127  INTERFACE.print(tt->data.snum);
128  INTERFACE.print(">");
129  } else if(tt->active && tt->signal>0.9){
130  tt->active=false;
131  INTERFACE.print("<q");
132  INTERFACE.print(tt->data.snum);
133  INTERFACE.print(">");
134  }
135 #if !defined(USE_ETHERNET)
136  INTERFACE.println("");
137 #endif
138  } // loop over all sensors
139 
140 } // Sensor::check
141 
142 #ifdef DCCPP_PRINT_DCCPP
143 
145 void Sensor::show() {
146  Sensor *tt;
147 
148  if (firstSensor == NULL) {
149  INTERFACE.print("<X>");
150 #if !defined(USE_ETHERNET)
151  INTERFACE.println("");
152 #endif
153  return;
154  }
155 
156  for (tt = firstSensor; tt != NULL; tt = tt->nextSensor) {
157  INTERFACE.print("<Q");
158  INTERFACE.print(tt->data.snum);
159  INTERFACE.print(" ");
160  INTERFACE.print(tt->data.pin);
161  INTERFACE.print(" ");
162  INTERFACE.print(tt->data.pullUp);
163  INTERFACE.print(">");
164 #if !defined(USE_ETHERNET)
165  INTERFACE.println("");
166 #endif
167  }
168 }
169 
171 
172 void Sensor::status() {
173  Sensor *tt;
174 
175  if (firstSensor == NULL) {
176  INTERFACE.print("<X>");
177 #if !defined(USE_ETHERNET)
178  INTERFACE.println("");
179 #endif
180  return;
181  }
182 
183  for (tt = firstSensor; tt != NULL; tt = tt->nextSensor) {
184  INTERFACE.print(tt->active ? "<Q" : "<q");
185  INTERFACE.print(tt->data.snum);
186  INTERFACE.print(">");
187 #if !defined(USE_ETHERNET)
188  INTERFACE.println("");
189 #endif
190  }
191 }
192 
193 #endif
194 
195 #ifdef USE_EEPROM
196 
198 void Sensor::load() {
199  struct SensorData data;
200  Sensor *tt;
201 
202  for (int i = 0; i<EEStore::eeStore->data.nSensors; i++) {
203 #ifdef VISUALSTUDIO
204  EEPROM.get(EEStore::pointer(), (void *)&(data), sizeof(SensorData)); // ArduiEmulator version...
205 #else
206  EEPROM.get(EEStore::pointer(), data);
207 #endif
208 #if defined(USE_TEXTCOMMAND)
209  tt = create(data.snum, data.pin, data.pullUp);
210 #else
211  tt = get(data.snum);
212 #ifdef DCCPP_DEBUG_MODE
213  if (tt == NULL)
214  INTERFACE.println(F("Sensor::begin() must be called BEFORE Sensor::load() !"));
215  else
216 #endif
217  tt->set(data.snum, data.pin, data.pullUp);
218 #endif
219  EEStore::advance(sizeof(tt->data));
220  }
221 }
222 
224 
225 void Sensor::store() {
226  Sensor *tt;
227 
228  tt = firstSensor;
229  EEStore::eeStore->data.nSensors = 0;
230 
231  while (tt != NULL) {
232 #ifdef VISUALSTUDIO
233  EEPROM.put(EEStore::pointer(), (void *)&(tt->data), sizeof(SensorData)); // ArduiEmulator version...
234 #else
235  EEPROM.put(EEStore::pointer(), tt->data);
236 #endif
237  EEStore::advance(sizeof(tt->data));
238  tt = tt->nextSensor;
239  EEStore::eeStore->data.nSensors++;
240  }
241 }
242 #endif
243 
244 #if defined(USE_TEXTCOMMAND)
245 
247 void Sensor::parse(char *c) {
248  int n, s, m;
249  // Sensor *t;
250 
251  switch (sscanf(c, "%d %d %d", &n, &s, &m)) {
252 
253  case 3: // argument is string with id number of sensor followed by a pin number and pullUp indicator (0=LOW/1=HIGH)
254  create(n, s, m);
255  break;
256 
257  case 1: // argument is a string with id number only
258  remove(n);
259  break;
260 
261 #ifdef DCCPP_PRINT_DCCPP
262  case -1: // no arguments
263  show();
264  break;
265 #endif
266 #ifdef USE_TEXTCOMMAND
267  case 2: // invalid number of arguments
268  INTERFACE.print("<X>");
269 #if !defined(USE_ETHERNET)
270  INTERFACE.println("");
271 #endif
272  break;
273 #endif
274  }
275 }
276 
278 
279 Sensor *Sensor::create(int snum, int pin, int pullUp) {
280  Sensor *tt = new Sensor();
281 
282  if (tt == NULL) { // problem allocating memory
283 #ifdef USE_TEXTCOMMAND
284  INTERFACE.print("<X>");
285 #if !defined(USE_ETHERNET)
286  INTERFACE.println("");
287 #endif
288 #endif
289  return(tt);
290  }
291 
292  tt->begin(snum, pin, pullUp);
293 
294  return(tt);
295 }
296 
297 #endif
298 
300 
301 Sensor *Sensor::firstSensor=NULL;
302 
303 #endif
Definition: Sensor.h:84