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