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