├── .gitignore
├── LICENSE
├── README.md
├── data
├── README.md
├── examples
│ ├── add.php
│ └── data.csv
├── sck_sensor_data.php
└── sensors
│ └── db.json
├── enclosure
├── 3dmodel
│ └── SCK-1.1_model.stl
├── Basic_case-2013
│ ├── SCK-1.0
│ │ ├── SCK-1.0_acrylic.dxf
│ │ └── SCK-1.0_case.stl
│ ├── SCK-1.1
│ │ ├── SCK-1.1_acrylic.dxf
│ │ ├── SCK-1.1_case.3dm
│ │ └── SCK-1.1_case.stl
│ ├── SCK_basic-1.jpg
│ ├── SCK_basic-2.jpg
│ ├── SCK_basic-3.jpg
│ └── SCK_basic-4.jpg
├── Enclosure.jpg
├── Simple_base
│ └── SCK-1.1_simple_base.stl
├── Smart Citizen SCK Mock-Up
├── case
│ ├── SCK-1.1_case.stl
│ ├── SCK-1.1_case_acrylic.dxf
│ ├── SCK-1.1_case_clip.stl
│ ├── SCK-1.1_case_complete.stp
│ └── case.jpg
├── dummybaseplate2.stl
├── readme.md
└── simple.png
├── hardware
├── Goteo
│ ├── README.md
│ ├── v1.0
│ │ ├── Ambient_Board_v1.0
│ │ │ ├── SCK_Ambient_v1.0.brd
│ │ │ └── SCK_Ambient_v1.0.sch
│ │ ├── Base_Board_v1.0
│ │ │ ├── SCK_Base_v1.0.brd
│ │ │ └── SCK_Base_v1.0.sch
│ │ └── README.md
│ └── v1.01
│ │ ├── Ambient_Board_v1.0
│ │ ├── SCK_Ambient_v1.0.brd
│ │ └── SCK_Ambient_v1.0.sch
│ │ ├── Base_Board_v1.01
│ │ ├── SCK_Base_v1.01.brd
│ │ └── SCK_Base_v1.01.sch
│ │ └── README.md
├── Kickstarter
│ ├── README.md
│ └── v1.1b
│ │ ├── Ambient_Board_v1.1b
│ │ ├── Ambient_Board_v1.1b.brd
│ │ ├── Ambient_Board_v1.1b.pdf
│ │ └── Ambient_Board_v1.1b.sch
│ │ ├── Base_Board_v1.1b
│ │ ├── Base_Board_v1.1b.brd
│ │ ├── Base_Board_v1.1b.pdf
│ │ └── Base_Board_v1.1b.sch
│ │ └── README.md
├── LICENSE
└── README.md
├── sck-commands.md
├── sck_beta_v0_8_7_SDCARD
├── AccumulatorFilter.h
├── Constants.h
├── README.md
├── SCKAmbient.ino
├── SCKBase.ino
├── SDUpdate.ino
├── TemperatureDecoupler.h
└── sck_beta_v0_8_7_SDCARD.ino
├── sck_beta_v0_9
├── AccumulatorFilter.h
├── Constants.h
├── SCKAmbient.cpp
├── SCKAmbient.h
├── SCKBase.cpp
├── SCKBase.h
├── SCKServer.cpp
├── SCKServer.h
├── TemperatureDecoupler.h
└── sck_beta_v0_9.ino
└── utilities
├── README.md
├── SCK_check
├── SCK_check.ino
├── SCKlibs.cpp
└── SCKlibs.h
├── SCK_testing
├── SCKtester
├── readme.md
├── shot.png
└── wifly
│ └── wifly.ino
├── Wifly_Rescue
├── SCKBase.ino
└── Wifly_Rescue.ino
├── Wifly_Update
├── SCKBase.ino
└── Wifly_Update.ino
└── wifly_terminal
├── SCKBase.ino
└── wifly_terminal.ino
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 | *.obj
6 |
7 | # Precompiled Headers
8 | *.gch
9 | *.pch
10 |
11 |
12 | # Fortran module files
13 | *.mod
14 |
15 | # Compiled Static libraries
16 | *.lai
17 | *.la
18 | *.a
19 | *.lib
20 |
21 | # Mac OS
22 | .DS_Store
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Smart Citizen Kit
2 | =================
3 |
4 | **NOTE:** [Click here](https://github.com/fablabbcn/smartcitizen-kit-20) for the newer version of SCK 2.0+
5 |
6 | **Smart Citizen Kit BETA version for the Ambient Sensor Board.**
7 |
8 |
9 |
10 |
11 | ### Download
12 |
13 | * Download the latest firmware release [here](https://github.com/fablabbcn/Smart-Citizen-Kit/releases/latest).
14 |
15 | ### Hardware
16 |
17 | * Firmware for the [SmartCitizen Ambient Kit](http://smartcitizen.me/pages/sck) 1.0 and 1.1.
18 |
19 | * More hardware info [here](https://github.com/fablabbcn/Smart-Citizen-Kit/tree/master/hardware).
20 |
21 | ### Quick start
22 |
23 | * Visit the project main documentation [docs.smartcitizen.me](http://docs.smartcitizen.me)
24 |
25 | ### Loading Firmware
26 |
27 | **The firmware is totally compatible with Arduino. You can upload the firmware using the [Arduino IDE](http://arduino.cc/en/main/software).**
28 |
29 | * For SmartCitizen Kit version 1.0 select `Tools/Boards/Arduino Leonardo` on the Arduino IDE (ATmega 32U4 at 16Mhz)
30 |
31 | * For SmartCitizen Kit version 1.1 select `Tools/Boards/Lylipad Arduino USB` on the Arduino IDE (ATmega 32U4 at 8Mhz)
32 |
33 | ### Versions
34 |
35 | The current firmware version in use is `0.9.4`.
36 |
37 | We currently support the SD card version on as a diferent firmware `SDCARD`, currently `0.8.7 SDCARD`.
38 |
39 | You can see the release history [here](https://github.com/fablabbcn/Smart-Citizen-Kit/releases)
40 |
41 | You can see the hardware versions [here](https://github.com/fablabbcn/Smart-Citizen-Kit/blob/master/hardware/README.md)
42 |
43 | ### Advance References
44 |
45 | * Setup commands reference in [sck-commands.md](https://github.com/fablabbcn/Smart-Citizen-Kit/blob/master/sck-commands.md)
46 |
47 | * Basic documentation for creating your own Sensor Boards [here](https://github.com/fablabbcn/Smart-Citizen-Kit/wiki/Making-a-Shield)
48 |
49 | * [Slideshow](https://speakerdeck.com/pral2a/smart-citizen-hardware-and-software) with project technical details
50 |
51 | ### Support and issues
52 |
53 | * Forum [forum.smartcitizen.me](http://forum.smartcitizen.me)
54 |
55 | ### Contributions
56 |
57 | * We are working on improving the firmware documentation for developers but still we encourage you to Fork the project and do a Pull request with your contributions.
58 |
59 | ## License
60 |
61 | All the software unless stated is released under [GNU GPL v3.0](https://github.com/fablabbcn/smartcitizen-kit/blob/master/LICENSE) and the hardware design files under [CERN OHL v1.2](https://github.com/fablabbcn/smartcitizen-kit/blob/master/hardware/LICENSE)
62 |
--------------------------------------------------------------------------------
/data/README.md:
--------------------------------------------------------------------------------
1 | Smart Citizen Data
2 | ==================
3 |
4 | **This is a basic example for creating your custom server backend for smartcitizen**
5 |
6 | *Note this is aimed at learning, not production ready code.*
7 |
8 | Check the complete documentation at http://docs.smartcitizen.me/#/start/how-to-store-data-in-your-own-database
9 |
10 |
--------------------------------------------------------------------------------
/data/examples/add.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/data/examples/data.csv:
--------------------------------------------------------------------------------
1 | 2015-04-06 10:38:00, 25, 20, 0, 112.5, 200, 3000, 78.6, 0, 10
2 | 2015-04-06 10:38:00, 25, 20, 0, 112.5, 200, 3000, 78.6, 0, 10
3 | 2015-04-06 10:38:00, 25, 20, 0, 112.5, 200, 3000, 78.6, 0, 10
4 | 2015-04-06 10:38:00, 25, 20, 0, 112.5, 200, 3000, 78.6, 0, 10
5 |
--------------------------------------------------------------------------------
/data/sck_sensor_data.php:
--------------------------------------------------------------------------------
1 |
35 | *
36 | * SCKSensorData is free software: you can redistribute it and/or modify
37 | * it under the terms of the GNU Lesser General Public License as
38 | * published by the Free Software Foundation, either version 3 of
39 | * the License, or (at your option) any later version.
40 | *
41 | * SCKSensorData is distributed in the hope that it will be useful,
42 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
43 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44 | * GNU Lesser General Public License for more details.
45 | *
46 | * You should have received a copy of the GNU Lesser General Public
47 | * License along with SCKSensorData. If not, see
48 | * .
49 | *
50 | */
51 |
52 |
53 | class SCKSensorData
54 | {
55 |
56 |
57 | /**
58 | * SCK11Calibration
59 | *
60 | * Calibrates to propper SI units an SCK datapoint
61 | *
62 | * @param array $rawBat Indexed array containing a SCK 1.1 datapoint
63 | * @return array Indexed arrary with a SCK datapoint calibrated
64 | *
65 | */
66 |
67 | public function SCK11Convert($rawData)
68 | {
69 |
70 | $data = array();
71 |
72 | if (self::isValidDateTimeString($rawData['timestamp'])) { //Check calibration....
73 |
74 | $data['timestamp'] = $rawData['timestamp'];
75 |
76 | $data['temp'] = self::tempConversion($rawData['temp']);
77 | $data['hum'] = self::humConversion($rawData['hum']);
78 | $data['noise'] = self::noiseConversion($rawData['noise']);
79 | $data['co'] = self::coConversion($rawData['co']);
80 | $data['no2'] = self::no2Conversion($rawData['no2']);
81 | $data['light'] = self::lightConversion($rawData['light']);
82 | $data['bat'] = self::batConversion($rawData['bat']);
83 | $data['panel'] = self::panelConversion($rawData['panel']);
84 | $data['nets'] = $rawData['nets'];
85 |
86 | return $data;
87 |
88 | } else {
89 |
90 | return false;
91 |
92 | }
93 |
94 | }
95 |
96 | /**
97 | * tempConversion
98 | *
99 | * Temperature calibration for SHT21 based on the datasheet:
100 | * https://github.com/fablabbcn/Smart-Citizen-Kit/wiki/Datasheets/HTU-21D.pdf
101 | *
102 | * Formula can be tune depending on the SCK enclosure.
103 | *
104 | *
105 | * @param float $rawTemp
106 | * @return float Temperature in ºC
107 | *
108 | */
109 |
110 | public function tempConversion($rawTemp)
111 | {
112 | return round(-53 + 175.72 / 65536.0 * $rawTemp, 2);
113 | }
114 |
115 | /**
116 | * humConversion
117 | *
118 | * Humidity calibration for SHT21 based on the datasheet:
119 | * https://github.com/fablabbcn/Smart-Citizen-Kit/wiki/Datasheets/HTU-21D.pdf
120 | *
121 | * Formula can be tune depending on the SCK enclosure.
122 | *
123 | *
124 | * @param float $rawHum
125 | * @return float Rel. Humidity in %
126 | *
127 | */
128 |
129 | public function humConversion($rawHum)
130 | {
131 | return round(7 + 125.0 / 65536.0 * $rawHum, 2);
132 | }
133 |
134 | /**
135 | * noiseConversion
136 | *
137 | * Noise calibration for SCK1.1 sound sensor. Converts mV in to dBs.
138 | * Based on a linear regresion from a lookup table (db.json) obtained after real measurements from our test facility.
139 | *
140 | *
141 | * @param float $rawSound
142 | * @return float noise as sound pressure in dB
143 | *
144 | */
145 |
146 | public function noiseConversion($rawSound)
147 | {
148 | $dbTable = json_decode(file_get_contents("./sensors/db.json"), true);
149 | return round(self::tableCalibration($dbTable, $rawSound), 2);
150 | }
151 |
152 | /**
153 | * coConversion
154 | *
155 | * CO values rescaling. For obtaining ppm check:
156 | *
157 | * @param float $rawCO
158 | * @return float sensor resistance in KOhm
159 | *
160 | */
161 |
162 | public function coConversion($rawCO)
163 | {
164 | return round($rawCO / 1000, 2);
165 | }
166 |
167 | /**
168 | * no2Conversion
169 | *
170 | * NO2 values rescaling. For obtaining ppm check:
171 | *
172 | * returns k0hm
173 | * @param float $rawNO2
174 | * @return float sensor resistance in KOhm
175 | *
176 | */
177 |
178 | public function no2Conversion($rawNO2)
179 | {
180 | return round($rawNO2 / 1000, 2);
181 | }
182 |
183 | /**
184 | * lightConversion
185 | *
186 | * Light values rescaling.
187 | *
188 | * returns lux
189 | * @param float $rawLight
190 | * @return float light level in lux
191 | *
192 | */
193 |
194 | public function lightConversion($rawLight)
195 | {
196 | return round($rawLight / 10, 2);
197 | }
198 |
199 | /**
200 | * batConversion
201 | *
202 | * Battery values rescaling.
203 | *
204 | * @param float $rawBat
205 | * @return float battery level in %
206 | *
207 | */
208 |
209 |
210 | public function batConversion($rawBat)
211 | {
212 | return round($rawBat / 10, 2);
213 | }
214 |
215 | /**
216 | * panelConversion
217 | *
218 | * Solar panel values rescaling.
219 | *
220 | * @param float $rawBat
221 | * @return float Tension in volts
222 | *
223 | */
224 |
225 | public function panelConversion($rawBat)
226 | {
227 | return round($rawBat / 100, 2);
228 | }
229 |
230 | /**
231 | * isValidDateTimeString
232 | *
233 | * Check if a string is a valid time stamp
234 | *
235 | * @param string $str_dt
236 | * @return bool
237 | *
238 | */
239 |
240 | private function isValidDateTimeString($str_dt)
241 | {
242 | $date1 = DateTime::createFromFormat('Y-m-d G:i:s', $str_dt);
243 | $date2 = DateTime::createFromFormat('Y-m-d H:i:s', $str_dt);
244 | return $date1 && ($date1->format('Y-m-d G:i:s') == $str_dt || $date2->format('Y-m-d H:i:s') == $str_dt);
245 | }
246 |
247 | /**
248 | * tableCalibration
249 | *
250 | * Calculates a point based on a linear regresion from a look up table
251 | *
252 | * @param array $refTable
253 | * @param float $rawValue
254 | * @return float
255 | *
256 | */
257 |
258 | private function tableCalibration($refTable, $rawValue)
259 | {
260 | for ($i = 0; $i < sizeof($refTable) - 1; $i++) {
261 | $prevValueRef = $refTable[$i][0];
262 | $nextValueRef = $refTable[$i + 1][0];
263 | if ($rawValue >= $prevValueRef && $rawValue < $nextValueRef) {
264 | $prevValueOutput = $refTable[$i][1];
265 | $nextValueOutput = $refTable[$i + 1][1];
266 | $result = self::linearRegression($rawValue, $prevValueOutput, $nextValueOutput, $prevValueRef, $nextValueRef);
267 | return $result;
268 | }
269 | }
270 | }
271 |
272 | /**
273 | * linearRegression
274 | * *
275 | * @param float $valueInput
276 | * @param float $prevValueOutput
277 | * @param float $nextValueOutput
278 | * @param float $prevValueRef
279 | * @param float $nextValueRef
280 | * @return float
281 | *
282 | */
283 |
284 | private function linearRegression($valueInput, $prevValueOutput, $nextValueOutput, $prevValueRef, $nextValueRef)
285 | {
286 | $slope = ($nextValueOutput - $prevValueOutput) / ($nextValueRef - $prevValueRef);
287 | $result = $slope * ($valueInput - $prevValueRef) + $prevValueOutput;
288 | return $result;
289 | }
290 |
291 |
292 |
293 | }
294 |
295 | ?>
--------------------------------------------------------------------------------
/data/sensors/db.json:
--------------------------------------------------------------------------------
1 | [
2 | [
3 | 0,
4 | 50
5 | ],
6 | [
7 | 2,
8 | 55
9 | ],
10 | [
11 | 3,
12 | 57
13 | ],
14 | [
15 | 6,
16 | 58
17 | ],
18 | [
19 | 20,
20 | 59
21 | ],
22 | [
23 | 40,
24 | 60
25 | ],
26 | [
27 | 60,
28 | 61
29 | ],
30 | [
31 | 75,
32 | 62
33 | ],
34 | [
35 | 115,
36 | 63
37 | ],
38 | [
39 | 150,
40 | 64
41 | ],
42 | [
43 | 180,
44 | 65
45 | ],
46 | [
47 | 220,
48 | 66
49 | ],
50 | [
51 | 260,
52 | 67
53 | ],
54 | [
55 | 300,
56 | 68
57 | ],
58 | [
59 | 375,
60 | 69
61 | ],
62 | [
63 | 430,
64 | 70
65 | ],
66 | [
67 | 500,
68 | 71
69 | ],
70 | [
71 | 575,
72 | 72
73 | ],
74 | [
75 | 660,
76 | 73
77 | ],
78 | [
79 | 720,
80 | 74
81 | ],
82 | [
83 | 820,
84 | 75
85 | ],
86 | [
87 | 900,
88 | 76
89 | ],
90 | [
91 | 975,
92 | 77
93 | ],
94 | [
95 | 1050,
96 | 78
97 | ],
98 | [
99 | 1125,
100 | 79
101 | ],
102 | [
103 | 1200,
104 | 80
105 | ],
106 | [
107 | 1275,
108 | 81
109 | ],
110 | [
111 | 1320,
112 | 82
113 | ],
114 | [
115 | 1375,
116 | 83
117 | ],
118 | [
119 | 1400,
120 | 84
121 | ],
122 | [
123 | 1430,
124 | 85
125 | ],
126 | [
127 | 1450,
128 | 86
129 | ],
130 | [
131 | 1480,
132 | 87
133 | ],
134 | [
135 | 1500,
136 | 88
137 | ],
138 | [
139 | 1525,
140 | 89
141 | ],
142 | [
143 | 1540,
144 | 90
145 | ],
146 | [
147 | 1560,
148 | 91
149 | ],
150 | [
151 | 1580,
152 | 92
153 | ],
154 | [
155 | 1600,
156 | 93
157 | ],
158 | [
159 | 1620,
160 | 94
161 | ],
162 | [
163 | 1640,
164 | 95
165 | ],
166 | [
167 | 1660,
168 | 96
169 | ],
170 | [
171 | 1680,
172 | 97
173 | ],
174 | [
175 | 1690,
176 | 98
177 | ],
178 | [
179 | 1700,
180 | 99
181 | ],
182 | [
183 | 1710,
184 | 100
185 | ],
186 | [
187 | 1720,
188 | 101
189 | ],
190 | [
191 | 1745,
192 | 102
193 | ],
194 | [
195 | 1770,
196 | 103
197 | ],
198 | [
199 | 1785,
200 | 104
201 | ],
202 | [
203 | 1800,
204 | 105
205 | ],
206 | [
207 | 1815,
208 | 106
209 | ],
210 | [
211 | 1830,
212 | 107
213 | ],
214 | [
215 | 1845,
216 | 108
217 | ],
218 | [
219 | 1860,
220 | 109
221 | ],
222 | [
223 | 1875,
224 | 110
225 | ]
226 | ]
--------------------------------------------------------------------------------
/enclosure/3dmodel/SCK-1.1_model.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fablabbcn/smartcitizen-kit-10/5d343f7c37d714c69dcb57fa3f7c47099750bee6/enclosure/3dmodel/SCK-1.1_model.stl
--------------------------------------------------------------------------------
/enclosure/Basic_case-2013/SCK-1.0/SCK-1.0_case.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fablabbcn/smartcitizen-kit-10/5d343f7c37d714c69dcb57fa3f7c47099750bee6/enclosure/Basic_case-2013/SCK-1.0/SCK-1.0_case.stl
--------------------------------------------------------------------------------
/enclosure/Basic_case-2013/SCK-1.1/SCK-1.1_case.3dm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fablabbcn/smartcitizen-kit-10/5d343f7c37d714c69dcb57fa3f7c47099750bee6/enclosure/Basic_case-2013/SCK-1.1/SCK-1.1_case.3dm
--------------------------------------------------------------------------------
/enclosure/Basic_case-2013/SCK-1.1/SCK-1.1_case.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fablabbcn/smartcitizen-kit-10/5d343f7c37d714c69dcb57fa3f7c47099750bee6/enclosure/Basic_case-2013/SCK-1.1/SCK-1.1_case.stl
--------------------------------------------------------------------------------
/enclosure/Basic_case-2013/SCK_basic-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fablabbcn/smartcitizen-kit-10/5d343f7c37d714c69dcb57fa3f7c47099750bee6/enclosure/Basic_case-2013/SCK_basic-1.jpg
--------------------------------------------------------------------------------
/enclosure/Basic_case-2013/SCK_basic-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fablabbcn/smartcitizen-kit-10/5d343f7c37d714c69dcb57fa3f7c47099750bee6/enclosure/Basic_case-2013/SCK_basic-2.jpg
--------------------------------------------------------------------------------
/enclosure/Basic_case-2013/SCK_basic-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fablabbcn/smartcitizen-kit-10/5d343f7c37d714c69dcb57fa3f7c47099750bee6/enclosure/Basic_case-2013/SCK_basic-3.jpg
--------------------------------------------------------------------------------
/enclosure/Basic_case-2013/SCK_basic-4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fablabbcn/smartcitizen-kit-10/5d343f7c37d714c69dcb57fa3f7c47099750bee6/enclosure/Basic_case-2013/SCK_basic-4.jpg
--------------------------------------------------------------------------------
/enclosure/Enclosure.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fablabbcn/smartcitizen-kit-10/5d343f7c37d714c69dcb57fa3f7c47099750bee6/enclosure/Enclosure.jpg
--------------------------------------------------------------------------------
/enclosure/Simple_base/SCK-1.1_simple_base.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fablabbcn/smartcitizen-kit-10/5d343f7c37d714c69dcb57fa3f7c47099750bee6/enclosure/Simple_base/SCK-1.1_simple_base.stl
--------------------------------------------------------------------------------
/enclosure/Smart Citizen SCK Mock-Up:
--------------------------------------------------------------------------------
1 | Smart Citizen SCK Mock-Up that can be 3D printed for testing and fitting so the real hardware won't need to be used.
2 |
--------------------------------------------------------------------------------
/enclosure/case/SCK-1.1_case.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fablabbcn/smartcitizen-kit-10/5d343f7c37d714c69dcb57fa3f7c47099750bee6/enclosure/case/SCK-1.1_case.stl
--------------------------------------------------------------------------------
/enclosure/case/SCK-1.1_case_clip.stl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fablabbcn/smartcitizen-kit-10/5d343f7c37d714c69dcb57fa3f7c47099750bee6/enclosure/case/SCK-1.1_case_clip.stl
--------------------------------------------------------------------------------
/enclosure/case/SCK-1.1_case_complete.stp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fablabbcn/smartcitizen-kit-10/5d343f7c37d714c69dcb57fa3f7c47099750bee6/enclosure/case/SCK-1.1_case_complete.stp
--------------------------------------------------------------------------------
/enclosure/case/case.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fablabbcn/smartcitizen-kit-10/5d343f7c37d714c69dcb57fa3f7c47099750bee6/enclosure/case/case.jpg
--------------------------------------------------------------------------------
/enclosure/readme.md:
--------------------------------------------------------------------------------
1 | Smartcitizen Kit Enclosure
2 | ====
3 |
4 |
5 | ## Enclosure (info [video](https://vimeo.com/145620646))
6 | 
7 |
8 | ## Simple base
9 | 
--------------------------------------------------------------------------------
/enclosure/simple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fablabbcn/smartcitizen-kit-10/5d343f7c37d714c69dcb57fa3f7c47099750bee6/enclosure/simple.png
--------------------------------------------------------------------------------
/hardware/Goteo/README.md:
--------------------------------------------------------------------------------
1 | Smart-Citizen-Kit
2 | =================
--------------------------------------------------------------------------------
/hardware/Goteo/v1.0/README.md:
--------------------------------------------------------------------------------
1 | Smart-Citizen-Kit
2 | =================
3 |
4 | Eagles files of Goteo.org campaign
5 |
6 | [http://www.goteo.org/project/smart-citizen-sensores-ciudadanos?lang=en
7 | ](http://www.goteo.org/project/smart-citizen-sensores-ciudadanos?lang=en)
8 |
9 | Smart Citizen Kit BETA version
10 | - Base Board v1.0
11 | - Ambient Sensor Board v1.0
12 |
13 | The SCK is a piece of hardware comprised by two printed-circuit boards: an interchangeable daughterboard or shield, and an arduino-compatible data-processing board.
14 |
15 | The sensor board carries sensors that measure air composition (CO and NO2), temperature, light intensity, sound levels, and humidity. Once it's set up, the ambient board is able to stream data measured by the sensors over Wi-Fi using the FCC-certified, wireless module on the data-processing board.
16 |
17 | LICENSE: GPL v.0.3
--------------------------------------------------------------------------------
/hardware/Goteo/v1.01/README.md:
--------------------------------------------------------------------------------
1 | Smart-Citizen-Kit
2 | =================
3 |
4 | Eagles files of Goteo.org campaign, 2n release
5 |
6 | [http://www.goteo.org/project/smart-citizen-sensores-ciudadanos?lang=en
7 | ](http://www.goteo.org/project/smart-citizen-sensores-ciudadanos?lang=en)
8 |
9 | Smart Citizen Kit BETA version
10 | - Base Board v1.01
11 | - Ambient Sensor Board v1.01
12 |
13 | The SCK is a piece of hardware comprised by two printed-circuit boards: an interchangeable daughterboard or shield, and an arduino-compatible data-processing board.
14 |
15 | The sensor board carries sensors that measure air composition (CO and NO2), temperature, light intensity, sound levels, and humidity. Once it's set up, the ambient board is able to stream data measured by the sensors over Wi-Fi using the FCC-certified, wireless module on the data-processing board.
16 |
17 | LICENSE: GPL v.0.3
--------------------------------------------------------------------------------
/hardware/Kickstarter/README.md:
--------------------------------------------------------------------------------
1 | Smart-Citizen-Kit
2 | =================
--------------------------------------------------------------------------------
/hardware/Kickstarter/v1.1b/Ambient_Board_v1.1b/Ambient_Board_v1.1b.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fablabbcn/smartcitizen-kit-10/5d343f7c37d714c69dcb57fa3f7c47099750bee6/hardware/Kickstarter/v1.1b/Ambient_Board_v1.1b/Ambient_Board_v1.1b.pdf
--------------------------------------------------------------------------------
/hardware/Kickstarter/v1.1b/Base_Board_v1.1b/Base_Board_v1.1b.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fablabbcn/smartcitizen-kit-10/5d343f7c37d714c69dcb57fa3f7c47099750bee6/hardware/Kickstarter/v1.1b/Base_Board_v1.1b/Base_Board_v1.1b.pdf
--------------------------------------------------------------------------------
/hardware/Kickstarter/v1.1b/README.md:
--------------------------------------------------------------------------------
1 | Smart-Citizen-Kit
2 | =================
3 |
4 | Eagles files of the Kickstarter campaign
5 |
6 | [https://www.kickstarter.com/projects/acrobotic/the-smart-citizen-kit-crowdsourced-environmental-m
7 | ](https://www.kickstarter.com/projects/acrobotic/the-smart-citizen-kit-crowdsourced-environmental-m)
8 |
9 | Smart Citizen Kit BETA version
10 | - Base Board v1.1b
11 | - Ambient Sensor Board v1.1b
12 |
13 | The SCK is a piece of hardware comprised by two printed-circuit boards: an interchangeable daughterboard or shield, and an arduino-compatible data-processing board.
14 |
15 | The sensor board carries sensors that measure air composition (CO and NO2), temperature, light intensity, sound levels, and humidity. Once it's set up, the ambient board is able to stream data measured by the sensors over Wi-Fi using the FCC-certified, wireless module on the data-processing board.
16 |
17 | LICENSE: GPL v.0.3
--------------------------------------------------------------------------------
/hardware/LICENSE:
--------------------------------------------------------------------------------
1 | CERN Open Hardware Licence v1.2
2 |
3 | Preamble
4 |
5 | Through this CERN Open Hardware Licence ("CERN OHL") version 1.2, CERN
6 | wishes to provide a tool to foster collaboration and sharing among
7 | hardware designers. The CERN OHL is copyright CERN. Anyone is welcome
8 | to use the CERN OHL, in unmodified form only, for the distribution of
9 | their own Open Hardware designs. Any other right is reserved. Release
10 | of hardware designs under the CERN OHL does not constitute an
11 | endorsement of the licensor or its designs nor does it imply any
12 | involvement by CERN in the development of such designs.
13 |
14 | 1. Definitions
15 |
16 | In this Licence, the following terms have the following meanings:
17 |
18 | “Licence” means this CERN OHL.
19 |
20 | “Documentation” means schematic diagrams, designs, circuit or circuit
21 | board layouts, mechanical drawings, flow charts and descriptive text,
22 | and other explanatory material that is explicitly stated as being made
23 | available under the conditions of this Licence. The Documentation may
24 | be in any medium, including but not limited to computer files and
25 | representations on paper, film, or any other media.
26 |
27 | “Documentation Location” means a location where the Licensor has
28 | placed Documentation, and which he believes will be publicly
29 | accessible for at least three years from the first communication to
30 | the public or distribution of Documentation.
31 |
32 | “Product” means either an entire, or any part of a, device built using
33 | the Documentation or the modified Documentation.
34 |
35 | “Licensee” means any natural or legal person exercising rights under
36 | this Licence.
37 |
38 | “Licensor” means any natural or legal person that creates or modifies
39 | Documentation and subsequently communicates to the public and/ or
40 | distributes the resulting Documentation under the terms and conditions
41 | of this Licence.
42 |
43 | A Licensee may at the same time be a Licensor, and vice versa.
44 |
45 | Use of the masculine gender includes the feminine and neuter genders
46 | and is employed solely to facilitate reading.
47 |
48 | 2. Applicability
49 |
50 | 2.1. This Licence governs the use, copying, modification,
51 | communication to the public and distribution of the Documentation, and
52 | the manufacture and distribution of Products. By exercising any right
53 | granted under this Licence, the Licensee irrevocably accepts these
54 | terms and conditions.
55 |
56 | 2.2. This Licence is granted by the Licensor directly to the Licensee,
57 | and shall apply worldwide and without limitation in time. The Licensee
58 | may assign his licence rights or grant sub-licences.
59 |
60 | 2.3. This Licence does not extend to software, firmware, or code
61 | loaded into programmable devices which may be used in conjunction with
62 | the Documentation, the modified Documentation or with Products, unless
63 | such software, firmware, or code is explicitly expressed to be subject
64 | to this Licence. The use of such software, firmware, or code is
65 | otherwise subject to the applicable licence terms and conditions.
66 |
67 | 3. Copying, modification, communication to the public and distribution
68 | of the Documentation
69 |
70 | 3.1. The Licensee shall keep intact all copyright and trademarks
71 | notices, all notices referring to Documentation Location, and all
72 | notices that refer to this Licence and to the disclaimer of warranties
73 | that are included in the Documentation. He shall include a copy
74 | thereof in every copy of the Documentation or, as the case may be,
75 | modified Documentation, that he communicates to the public or
76 | distributes.
77 |
78 | 3.2. The Licensee may copy, communicate to the public and distribute
79 | verbatim copies of the Documentation, in any medium, subject to the
80 | requirements specified in section 3.1.
81 |
82 | 3.3. The Licensee may modify the Documentation or any portion thereof
83 | provided that upon modification of the Documentation, the Licensee
84 | shall make the modified Documentation available from a Documentation
85 | Location such that it can be easily located by an original Licensor
86 | once the Licensee communicates to the public or distributes the
87 | modified Documentation under section 3.4, and, where required by
88 | section 4.1, by a recipient of a Product. However, the Licensor shall
89 | not assert his rights under the foregoing proviso unless or until a
90 | Product is distributed.
91 |
92 | 3.4. The Licensee may communicate to the public and distribute the
93 | modified Documentation (thereby in addition to being a Licensee also
94 | becoming a Licensor), always provided that he shall:
95 |
96 | a) comply with section 3.1;
97 |
98 | b) cause the modified Documentation to carry prominent notices stating
99 | that the Licensee has modified the Documentation, with the date and
100 | description of the modifications;
101 |
102 | c) cause the modified Documentation to carry a new Documentation
103 | Location notice if the original Documentation provided for one;
104 |
105 | d) make available the modified Documentation at the same level of
106 | abstraction as that of the Documentation, in the preferred format for
107 | making modifications to it (e.g. the native format of the CAD tool as
108 | applicable), and in the event that format is proprietary, in a format
109 | viewable with a tool licensed under an OSI-approved license if the
110 | proprietary tool can create it; and
111 |
112 | e) license the modified Documentation under the terms and conditions
113 | of this Licence or, where applicable, a later version of this Licence
114 | as may be issued by CERN.
115 |
116 | 3.5. The Licence includes a non-exclusive licence to those patents or
117 | registered designs that are held by, under the control of, or
118 | sub-licensable by the Licensor, to the extent necessary to make use of
119 | the rights granted under this Licence. The scope of this section 3.5
120 | shall be strictly limited to the parts of the Documentation or
121 | modified Documentation created by the Licensor.
122 |
123 | 4. Manufacture and distribution of Products
124 |
125 | 4.1. The Licensee may manufacture or distribute Products always
126 | provided that, where such manufacture or distribution requires a
127 | licence under this Licence the Licensee provides to each recipient of
128 | such Products an easy means of accessing a copy of the Documentation
129 | or modified Documentation, as applicable, as set out in section 3.
130 |
131 | 4.2. The Licensee is invited to inform any Licensor who has indicated
132 | his wish to receive this information about the type, quantity and
133 | dates of production of Products the Licensee has (had) manufactured
134 |
135 | 5. Warranty and liability
136 |
137 | 5.1. DISCLAIMER – The Documentation and any modified Documentation are
138 | provided "as is" and any express or implied warranties, including, but
139 | not limited to, implied warranties of merchantability, of satisfactory
140 | quality, non-infringement of third party rights, and fitness for a
141 | particular purpose or use are disclaimed in respect of the
142 | Documentation, the modified Documentation or any Product. The Licensor
143 | makes no representation that the Documentation, modified
144 | Documentation, or any Product, does or will not infringe any patent,
145 | copyright, trade secret or other proprietary right. The entire risk as
146 | to the use, quality, and performance of a Product shall be with the
147 | Licensee and not the Licensor. This disclaimer of warranty is an
148 | essential part of this Licence and a condition for the grant of any
149 | rights granted under this Licence. The Licensee warrants that it does
150 | not act in a consumer capacity.
151 |
152 | 5.2. LIMITATION OF LIABILITY – The Licensor shall have no liability
153 | for direct, indirect, special, incidental, consequential, exemplary,
154 | punitive or other damages of any character including, without
155 | limitation, procurement of substitute goods or services, loss of use,
156 | data or profits, or business interruption, however caused and on any
157 | theory of contract, warranty, tort (including negligence), product
158 | liability or otherwise, arising in any way in relation to the
159 | Documentation, modified Documentation and/or the use, manufacture or
160 | distribution of a Product, even if advised of the possibility of such
161 | damages, and the Licensee shall hold the Licensor(s) free and harmless
162 | from any liability, costs, damages, fees and expenses, including
163 | claims by third parties, in relation to such use.
164 |
165 | 6. General
166 |
167 | 6.1. Except for the rights explicitly granted hereunder, this Licence
168 | does not imply or represent any transfer or assignment of intellectual
169 | property rights to the Licensee.
170 |
171 | 6.2. The Licensee shall not use or make reference to any of the names
172 | (including acronyms and abbreviations), images, or logos under which
173 | the Licensor is known, save in so far as required to comply with
174 | section 3. Any such permitted use or reference shall be factual and
175 | shall in no event suggest any kind of endorsement by the Licensor or
176 | its personnel of the modified Documentation or any Product, or any
177 | kind of implication by the Licensor or its personnel in the
178 | preparation of the modified Documentation or Product.
179 |
180 | 6.3. CERN may publish updated versions of this Licence which retain
181 | the same general provisions as this version, but differ in detail so
182 | far this is required and reasonable. New versions will be published
183 | with a unique version number.
184 |
185 | 6.4. This Licence shall terminate with immediate effect, upon written
186 | notice and without involvement of a court if the Licensee fails to
187 | comply with any of its terms and conditions, or if the Licensee
188 | initiates legal action against Licensor in relation to this
189 | Licence. Section 5 shall continue to apply.
190 |
--------------------------------------------------------------------------------
/hardware/README.md:
--------------------------------------------------------------------------------
1 | Smart Citizen Kit
2 | =================
3 |
4 | ###Smart Citizen Kit Ambient Sensor Board versions
5 |
6 |
7 | | Smart Citizen Kit | | SCK 1.0 (Goteo Board) | SCK 1.1 (Kickstarter Board) |
8 | |:-----------|:---------:|:---------------------------:|:---------------------------:|
9 | | **Data Board** | | | |
10 | | **MCU** | | ATMEGA32U4 | ATMEGA32U4 |
11 | | **Clock** | | 16Mhz | 8Mhz |
12 | | **WiFi** | | Microchip RN-131 802.11 b/g | Microchip RN-131 802.11 b/g |
13 | | **Firmware** | | https://github.com/fablabbcn/Smart-Citizen-Kit | https://github.com/fablabbcn/Smart-Citizen-Kit |
14 | | **Design files** | | https://github.com/fablabbcn/Smart-Citizen-Kit/tree/master/hardware/Goteo/v1.01 | https://github.com/fablabbcn/Smart-Citizen-Kit/tree/master/hardware/Kickstarter |
15 | | **Ambient Board** | | | |
16 | | **Light** | *Part* | PVD-P8001 | BH1730FVC |
17 | | | *Type* | LDR Analog Light Sensor | Digital Ambient Light Sensor |
18 | | | *Units* | % | Lux |
19 | | | *Datasheet* | https://github.com/fablabbcn/Smart-Citizen-Kit/wiki/Datasheets/PDV-P8001.pdf | https://github.com/fablabbcn/Smart-Citizen-Kit/wiki/Datasheets/BH-1730FCV.pdf |
20 | | | Firmware | `SCKAmbient::getLight();` | `SCKAmbient::getLight():` |
21 | | **Temp** | *Part* | DHT22 | HPP828E031 (SHT21) |
22 | | | *Type* | Digital Temperature and Relative Humidity Sensor | Digital Temperature and Relative Humidity Sensor |
23 | | | *Units* | ºC | ºC |
24 | | | *Datasheet* | https://github.com/fablabbcn/Smart-Citizen-Kit/wiki/Datasheets/DHT22.pdf | https://github.com/fablabbcn/Smart-Citizen-Kit/wiki/Datasheets/HTU-21D.pdf |
25 | | | Firmware | `SCKAmbient::getDHT22();` `SCKAmbient::getHumidity();` | `SCKAmbient::getSHT21();` `SCKAmbient::getTemperature();` |
26 | | **Humidity** | *Part* | DHT22 | HPP828E031 (SHT21) |
27 | | | *Type* | Digital Temperature and Relative Humidity Sensor | Digital Temperature and Relative Humidity Sensor |
28 | | | *Units* | % Rel | % Rel |
29 | | | *Datasheet* | https://github.com/fablabbcn/Smart-Citizen-Kit/wiki/Datasheets/DHT22.pdf | https://github.com/fablabbcn/Smart-Citizen-Kit/wiki/Datasheets/HTU-21D.pdf |
30 | | | Firmware | `SCKAmbient::getDHT22();` `SCKAmbient::getHumidity();` | `SCKAmbient::getSHT21();` `SCKAmbient::getHumidity();` |
31 | | **Noise** | *Part* | POM-3044P-R | POM-3044P-R |
32 | | | *Type* | Electret microphone with envelop follower sound pressure sensor | Electret microphone with envelop follower sound pressure sensor |
33 | | | *Units* | dB | dB |
34 | | | *Datasheet* | https://github.com/fablabbcn/Smart-Citizen-Kit/wiki/Datasheets/POM-3044P-R.pdf | https://github.com/fablabbcn/Smart-Citizen-Kit/wiki/Datasheets/POM-3044P-R.pdf |
35 | | | *Firmware* | `SCKAmbient::getNoise();` | `SCKAmbient::getNoise();` |
36 | | **CO** | *Part* | MICS-5525 | MiCS-4514 |
37 | | | *Type* | MOS CO gas sensor | MOS CO and NO2 gas sensor |
38 | | | *Units* | kOhm (ppm) | kOhm (ppm) |
39 | | | *Datasheet* | https://github.com/fablabbcn/Smart-Citizen-Kit/wiki/Datasheets/MICS-5525_CO.pdf | https://github.com/fablabbcn/Smart-Citizen-Kit/wiki/Datasheets/MiCS-4514_CO_NO2.pdf |
40 | | | *Firmware* | `SCKAmbient::getMICS();` | `SCKAmbient::getMICS();` |
41 | | **NO2** | *Part* | MICS-2710 | MiCS-4514 |
42 | | | *Type* | MOS NO2 gas sensor | MOS CO and NO2 gas sensor |
43 | | | *Units* | kOhm (ppm) | kOhm (ppm) |
44 | | | *Datasheet* | https://github.com/fablabbcn/Smart-Citizen-Kit/wiki/Datasheets/MICS-2710_NO2.pdf | https://github.com/fablabbcn/Smart-Citizen-Kit/wiki/Datasheets/MiCS-4514_CO_NO2.pdf |
45 | | | *Firmware* | `SCKAmbient::getMICS();` | `SCKAmbient::getMICS();` |
46 |
--------------------------------------------------------------------------------
/sck-commands.md:
--------------------------------------------------------------------------------
1 | ## SCK Serial Commands
2 |
3 | The Smart Citizen Kit can be managed over a basic serial protocol. You just need the **Arduino IDE Serial Monitor** or any other **Serial Utility** like **Screen** in order to use it.
4 |
5 | #### How to use it.
6 |
7 | * Connect to your kit using any serial utility, any baud-rate should work but `115200` is recommendable.
8 | * Send the starting commands.
9 | * Notice all the commands except the starting commands require a carriage return at the end: `CR` or `\r` .
10 | * Call any command you want, change `XXX` with the corresponding value.
11 |
12 | ### Basic SCK setup commands
13 |
14 | This commands are commands to talk directly to the Wi-Fi module (RN-XV WiFly) own interface.
15 |
16 | * `$$$` Wake up the module and enter WiFly commands mode
17 | * `set wlan ssid XXX\r` Add a new SSID to memory
18 | * `set wlan phrase XXX\r` Add a new phrase to memory
19 | * `set wlan key XXX\r` Add a new key to memory
20 | * `set wlan auth XXX\r` Add an authentication method into memory
21 | * `set wlan ext_antenna XXX\r` Add an antenna type into memory
22 | * `set sys iofunc 0x7` Disable the Wi-Fi module blue LED's
23 | * `exit\r` Go back to normal operational mode
24 |
25 | ### Special SCK commands
26 |
27 | This commands are commands to talk talk to the SCK configuration interface.
28 |
29 | * `###` Wake up the module and enter SCK commands mode
30 | * `get mac\r` Get the MAC address of the kit
31 | * `get time update\r` Retrieve the sensor update interval
32 | * `set time update XXX\r` Update the sensor update interval
33 | * `get number updates\r` Retrieve the max number of bulk updates allowed
34 | * `set number updates XXX\r` Update the max number of bulk updates allowed
35 | * `get apikey\r` Retrieve the kit APIKEY
36 | * `set apikey XXX\r` Update the kit APIKEY
37 | * `get wlan ssid\r` Retrieve the SSID saved on the kit
38 | * `get wlan phrase\r` Retrieve the phrase and KEY saved on the kit
39 | * `get wlan auth\r` Retrieve the authentication methods saved on the kit
40 | * `get wlan ext_antenna\r` Retrieve the antenna types saved on the kit
41 | * `get all\r` Retrieve all config saved on the kit in a single line (`|version|MAC|ssid1 ssid2,pass1 pass2,auth1 auth2,ant1 ant2|hardcodedNets|timeUpdate|numPosts|`)
42 | * `post data\r` Retrieve sensor readings and post them to server if network connection is available.
43 | * `clear nets\r` Remove all saved Wi-Fi configuration information (except hardcoded)
44 | * `clear memory\r` Remove all configuration information
45 | * `exit\r` Goes back to normal operational mode
46 | * `#data\r` Retrieves sensor readings stored in memory
47 |
--------------------------------------------------------------------------------
/sck_beta_v0_8_7_SDCARD/AccumulatorFilter.h:
--------------------------------------------------------------------------------
1 | //
2 | // AccumulatorFilter.h
3 | // AccumulatorFilter
4 | //
5 | // Created by Oriol Ferrer Mesià on 09/06/13.
6 | //
7 | //
8 |
9 | #ifndef AccumulatorFilter_AccumulatorFilter_h
10 | #define AccumulatorFilter_AccumulatorFilter_h
11 |
12 | #define GHETTO_VAL 0.02f
13 | class AccumulatorFilter{
14 |
15 | public:
16 |
17 | AccumulatorFilter(){
18 | val = GHETTO_VAL;
19 | upSpeed = 0.5f;
20 | }
21 |
22 | void setup(float upSpeed_){
23 | val = 0.0f;
24 | upSpeed = upSpeed_;
25 | }
26 |
27 | void goUp(){
28 | //Serial.println( "goUP!");
29 | if (val <= GHETTO_VAL){
30 | val = GHETTO_VAL;
31 | }
32 | val *= (1.0f + upSpeed * 2.0f * (1.0f - val) );
33 | }
34 |
35 | void goDown(){
36 | //Serial.println( "goDown!");
37 | if (val >= 1.0f - GHETTO_VAL){
38 | val = 1.0f - GHETTO_VAL;
39 | }
40 | val /= (1.0f + upSpeed * 2.0f * (1.0f - val) );
41 | }
42 |
43 | float getVal(){
44 | return val;
45 | }
46 |
47 | float getSpeed(){
48 | return upSpeed;
49 | }
50 |
51 | float upSpeed;
52 | float val;
53 | };
54 |
55 | #endif
56 |
--------------------------------------------------------------------------------
/sck_beta_v0_8_7_SDCARD/Constants.h:
--------------------------------------------------------------------------------
1 | #define debuggSCK false
2 | #define decouplerComp true
3 | #define DataRaw false
4 |
5 | #define AWAKE 4 //Despertar WIFI
6 | #define PANEL A8 //Entrada panel
7 | #define BAT A7 //Entrada bateria
8 |
9 | #define IO0 5 //MICS5525_HEATHER
10 | #define IO1 13 //MICS2710_HEATHER
11 | #define IO2 9 //MICS2710_ALTAIMPEDANCIA
12 | #define IO3 10 //MICS2710_ALTAIMPEDANCIA
13 | #define FACTORY 7 //factory RESET/AP RN131
14 | #define CONTROL 12 //Control Mode
15 |
16 | #define S0 A4 //MICS_5525
17 | #define S1 A5 //MICS_2710
18 | #define S2 A2 //SENS_5525
19 | #define S3 A3 //SENS_2710
20 | #define S4 A0 //MICRO
21 | #define S5 A1 //LDR
22 |
23 | #define DEFAULT_TIME_UPDATE "30" //Tiempo entre actualizacion y actualizacion
24 | #define DEFAULT_MIN_UPDATES "1" //Minimo numero de actualizaciones antes de postear
25 |
26 | #define POST_MAX 20 //Maximo numero de posteos a la vez
27 |
28 | //Direcciones I2C
29 | #define RTC_ADDRESS 0x68 // Direcion de la RTC
30 | #define E2PROM 0x50 // Direcion de la EEPROM
31 |
32 | #if F_CPU == 8000000
33 | #define MCP1 0x2E // Direcion del mcp1 Potenciometros que controlan los MICS
34 | #define MCP2 0x2F // Direcion del mcp2 Potenciometros que controlan la ganancia del microfono
35 | #define MCP3 0x2D // Direcion del mcp3 Ajuste carga bateria
36 | #define bh1730 0x29 // Direcion del sensor de luz
37 | #define Temperature 0x40 // Direcion del sht21
38 | #define ADXL 0x53 //ADXL345 device address
39 | #else
40 | #define MCP1 0x2F // Direcion del mcp1 MICS
41 | #define MCP2 0x2E // Direcion del mcp2 REGULADORES
42 | #endif
43 |
44 | //Espacio reservado para los parametros de configuracion del SCK
45 | #define EE_ADDR_TIME_VERSION 0 //32BYTES
46 | #define EE_ADDR_TIME_UPDATE 32 //16BYTES Tiempo entre actualizacion y actualizacion de los sensores en segundos
47 | #define EE_ADDR_NUMBER_UPDATES 48 //4BYTES Numero de actualizaciones antes de postear
48 |
49 |
50 | #define MICS_5525 0x00
51 | #define MICS_2710 0x01
52 |
53 | #define Rc0 10. //Ohm Resistencia medica de corriente en el sensor MICS_5525/MICS_5524
54 |
55 | #if F_CPU == 8000000
56 | #define Rc1 39. //Ohm Resistencia medica de corriente en el sensor MICS_2714
57 | #else
58 | #define Rc1 10. //Ohm Resistencia medica de corriente en el sensor MICS_2710
59 | #endif
60 |
61 | #if F_CPU == 8000000
62 | float Vcc = 3300.; //mV
63 | #define VMIC0 2734.
64 | #define VMIC1 2734.
65 | #else
66 | float Vcc = 5000.; //mV
67 | #define VMIC0 5000.
68 | #define VMIC1 2500.
69 | #endif
70 |
71 | #define reference 2560.
72 |
73 | #if F_CPU == 8000000
74 | #define VAL_MAX_BATTERY 4200
75 | #define VAL_MIN_BATTERY 3000
76 | #else
77 | #define VAL_MAX_BATTERY 4050
78 | #define VAL_MIN_BATTERY 3000
79 | #endif
80 |
81 |
82 | #define DHTLIB_INVALID_VALUE -999
83 |
84 |
--------------------------------------------------------------------------------
/sck_beta_v0_8_7_SDCARD/README.md:
--------------------------------------------------------------------------------
1 | Smart Citizen Kit firmware for SD
2 | =================================
3 |
4 | **Smart Citizen Kit SD firmware version for the Ambient Sensor Board.**
5 |
6 | This firmware is aimed to people wanting to log data in off-line mode, without internet connectivity, storing data on the built-in micro SD.
7 |
8 |
9 | ##Steps
10 |
11 | 1. **microSD**: We recomend formating **micro SD** cards using the official SD tool you can download [here](https://www.sdcard.org/downloads/formatter_4/).
12 |
13 | 2. **RTC**: Place a **CR1220** cell battery on your kit. Before uploading the SD firmware use the on-line configuration tool at [smartcitizen.me](https://smartcitizen.me) to set your Wi-Fi credentials. Your kit will connect to the internet and sync its the internal clock with our remote servers.
14 |
15 | 3. You can now install the **SD firmware** using the Arduino IDE. Ready!
16 |
17 |
18 | ##Installation
19 |
20 |
21 | **The firmware is totally compatible with Arduino. You can upload the firmware using the [Arduino IDE](http://arduino.cc/en/main/software).**
22 |
23 | ####Dependencies:
24 |
25 | In order to compile and upload the firmware you will need to install the **SdFat** library for Arduino.
26 |
27 | Download the library [here](https://github.com/greiman/SdFat) and install the library following the [instructions](http://arduino.cc/en/Guide/Libraries).
28 |
29 | ####Boards:
30 |
31 | * For SmartCitizen Kit version 1.0 select `Tools/Boards/Arduino Leonardo` on the Arduino IDE (ATmega 32U4 at 16Mhz)
32 |
33 | * For SmartCitizen Kit version 1.1 select `Tools/Boards/Lylipad Arduino USB` on the Arduino IDE (ATmega 32U4 at 8Mhz)
34 |
35 | ##SD data format
36 |
37 |
38 | When using the **SD firmware** on the SCK, data is stored as **CSV** (comma separated) file on the SD card.
39 |
40 | This is an example of the output file once opened on a spreadsheet application:
41 |
42 | | Temperature | Humidity| Light | Battery | Solar Panel | CO | NO2 | Noise| UTC |
43 | |-------------|---------|---------|---------|-------------|--------|------|------|----------------------|
44 | | 2821.20 | 4072.00 | 4413.10 | 96.40 | 0.00 | 94.67 | 0.65 | 5.23 | 2000-01-01 00:00:02 |
45 | | 2784.40 | 4236.80 | 5936.70 | 96.10 | 0.00 | 278.27 | 1.05 | 2.39 | 2000-01-01 00:00:02 |
46 |
47 | ###Data Import
48 |
49 | You can import the recorded data in to [smartcitizen.me](http://smartcitizen.me).
50 |
51 | In your device page you will find the **Import SD** along with the Edit and Configure options.
52 |
53 | 
54 |
55 | Using a microSD card reader get the **post.csv** file from your card, select it and click import. Data will be imported in to your device, data existing on the file already imported will be skipped. Your kit should be running the latest SD firmware and the SCK time (RTC) should be set in order data can be imported.
56 |
57 | ###Data Conversions
58 |
59 | The data stored is automatically converted to the proper units in firmware.
60 |
61 | If you prefer to do the conversions manually set `DataRaw false` in the `Constants.h` file and apply the formulas on the following table:
62 |
63 |
64 | | ID | Sensor | Units | Conversion Formula
65 | |-----|--------------|-------|---------------------------------------------|
66 | | 0 | Temperature | ºC | T = -53 + 175.72 / 65536.0 * ( Traw * 10 ) |
67 | | 1 | Humidity | %Rel | H = 7 + 125.0 / 65536.0 * ( Hraw * 10 ) |
68 | | 2 | Light | Lux | L = Lraw / 10 |
69 | | 3 | Battery | % | Not required |
70 | | 4 | Panel | mV | Not required |
71 | | 5 | CO | kOhm | Not required |
72 | | 6 | NO2 | kOhm | Not required |
73 | | 7 | Noise | dB | Apply the conversion table from mV to dB: [CSV](https://gist.github.com/pral2a/d767cc45874361fd38bf)
74 | | 8 | Date | DD:MM:YY | Not required |
75 | | 9 | Time | hh:mm:ss | Not required |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/sck_beta_v0_8_7_SDCARD/SCKAmbient.ino:
--------------------------------------------------------------------------------
1 |
2 | //Valores por defecto de la resistencia en vacio de los MICS
3 | float RoCO = 750000;
4 | float RoNO2 = 2200;
5 |
6 | #if ((decouplerComp)&&(F_CPU > 8000000 ))
7 | #include "TemperatureDecoupler.h"
8 | TemperatureDecoupler decoupler; //use this object to compensate for charger generated heat affecting temp values
9 | #endif
10 |
11 | float RsCO = 0;
12 | float RsNO2 = 0;
13 |
14 | #define RES 256 //Resolucion de los potenciometros digitales
15 |
16 | #if F_CPU == 8000000
17 | #define R1 12 //Kohm
18 | #else
19 | #define R1 82 //Kohm
20 | #endif
21 |
22 | #define P1 100 //Kohm
23 |
24 | float k= (RES*(float)R1/100)/1000; //Constante de conversion a tension de los reguladores
25 | float kr= ((float)P1*1000)/RES; //Constante de conversion a resistencia de potenciometrosen ohmios
26 |
27 | #if F_CPU == 8000000
28 | uint16_t lastHumidity;
29 | uint16_t lastTemperature;
30 | int accel_x=0;
31 | int accel_y=0;
32 | int accel_z=0;
33 | #else
34 | int lastHumidity;
35 | int lastTemperature;
36 | #endif
37 |
38 |
39 |
40 | void sckWriteVH(byte device, long voltage ) {
41 | int data=0;
42 |
43 | #if F_CPU == 8000000
44 | int temp = (int)(((voltage/0.41)-1000)*k);
45 | #else
46 | int temp = (int)(((voltage/1.2)-1000)*k);
47 | #endif
48 |
49 | if (temp>RES) data = RES;
50 | else if (temp<0) data=0;
51 | else data = temp;
52 | #if F_CPU == 8000000
53 | sckWriteMCP(MCP1, device, data);
54 | #else
55 | sckWriteMCP(MCP2, device, data);
56 | #endif
57 | }
58 |
59 |
60 | float sckReadVH(byte device) {
61 | int data;
62 | #if F_CPU == 8000000
63 | data=sckReadMCP(MCP1, device);
64 | float voltage = (data/k + 1000)*0.41;
65 | #else
66 | data=sckReadMCP(MCP2, device);
67 | float voltage = (data/k + 1000)*1.2;
68 | #endif
69 |
70 | return(voltage);
71 | }
72 |
73 | void sckWriteRL(byte device, long resistor) {
74 | int data=0x00;
75 | data = (int)(resistor/kr);
76 | #if F_CPU == 8000000
77 | sckWriteMCP(MCP1, device + 6, data);
78 | #else
79 | sckWriteMCP(MCP1, device, data);
80 | #endif
81 | }
82 |
83 | float sckReadRL(byte device)
84 | {
85 | #if F_CPU == 8000000
86 | return (kr*sckReadMCP(MCP1, device + 6)); //Devuelve en Ohms
87 | #else
88 | return (kr*sckReadMCP(MCP1, device)); //Devuelve en Ohms
89 | #endif
90 | }
91 |
92 | void sckWriteRGAIN(byte device, long resistor) {
93 | int data=0x00;
94 | data = (int)(resistor/kr);
95 | sckWriteMCP(MCP2, device, data);
96 | }
97 |
98 | float sckReadRGAIN(byte device)
99 | {
100 | return (kr*sckReadMCP(MCP2, device)); //Devuelve en Ohms
101 | }
102 |
103 | void sckWriteGAIN(long value)
104 | {
105 | if (value == 100)
106 | {
107 | sckWriteRGAIN(0x00, 10000);
108 | sckWriteRGAIN(0x01, 10000);
109 | }
110 | else if (value == 1000)
111 | {
112 | sckWriteRGAIN(0x00, 10000);
113 | sckWriteRGAIN(0x01, 100000);
114 | }
115 | else if (value == 10000)
116 | {
117 | sckWriteRGAIN(0x00, 100000);
118 | sckWriteRGAIN(0x01, 100000);
119 | }
120 | delay(100);
121 | }
122 |
123 | float sckReadGAIN()
124 | {
125 | return (sckReadRGAIN(0x00)/1000)*(sckReadRGAIN(0x01)/1000);
126 | }
127 |
128 | void sckGetVcc()
129 | {
130 | float temp = average(S3);
131 | analogReference(INTERNAL);
132 | delay(100);
133 | Vcc = (float)(average(S3)/temp)*reference;
134 | analogReference(DEFAULT);
135 | delay(100);
136 | }
137 |
138 | void sckHeat(byte device, int current)
139 | {
140 | float Rc=Rc0;
141 | byte Sensor = S2;
142 | if (device == MICS_2710) { Rc=Rc1; Sensor = S3;}
143 |
144 | float Vc = (float)average(Sensor)*Vcc/1023; //mV
145 | float current_measure = Vc/Rc; //mA
146 | float Rh = (sckReadVH(device)- Vc)/current_measure;
147 | float Vh = (Rh + Rc)*current;
148 |
149 | sckWriteVH(device, Vh);
150 | #if debuggSCK
151 | if (device == MICS_2710) Serial.print("MICS2710 corriente: ");
152 | else Serial.print("MICS5525 corriente: ");
153 | Serial.print(current_measure);
154 | Serial.println(" mA");
155 | if (device == MICS_2710) Serial.print("MICS2710 correccion VH: ");
156 | else Serial.print("MICS5525 correccion VH: ");
157 | Serial.print(sckReadVH(device));
158 | Serial.println(" mV");
159 | Vc = (float)average(Sensor)*Vcc/1023; //mV
160 | current_measure = Vc/Rc; //mA
161 | if (device == MICS_2710) Serial.print("MICS2710 corriente corregida: ");
162 | else Serial.print("MICS5525 corriente corregida: ");
163 | Serial.print(current_measure);
164 | Serial.println(" mA");
165 | Serial.println("Heating...");
166 | #endif
167 |
168 | }
169 |
170 | float sckReadRs(byte device)
171 | {
172 | byte Sensor = S0;
173 | float VMICS = VMIC0;
174 | if (device == MICS_2710) {Sensor = S1; VMICS = VMIC1;}
175 | float RL = sckReadRL(device); //Ohm
176 | float VL = ((float)average(Sensor)*Vcc)/1023; //mV
177 | if (VL > VMICS) VL = VMICS;
178 | float Rs = ((VMICS-VL)/VL)*RL; //Ohm
179 | #if debuggSCK
180 | if (device == MICS_5525) Serial.print("MICS5525 Rs: ");
181 | else Serial.print("MICS2710 Rs: ");
182 | Serial.print(VL);
183 | Serial.print(" mV, ");
184 | Serial.print(Rs);
185 | Serial.println(" Ohm");
186 | #endif;
187 | return Rs;
188 | }
189 |
190 | float sckReadMICS(byte device)
191 | {
192 | float Rs = sckReadRs(device);
193 | float RL = sckReadRL(device); //Ohm
194 |
195 | /*Correccion de impedancia de carga*/
196 | if ((Rs <= (RL - 1000))||(Rs >= (RL + 1000)))
197 | {
198 | if (Rs < 2000) sckWriteRL(device, 2000);
199 | else sckWriteRL(device, Rs);
200 | delay(100);
201 | Rs = sckReadRs(device);
202 | }
203 | return Rs;
204 | }
205 |
206 | void sckGetMICS(){
207 |
208 | /*Correccion de la tension del Heather*/
209 | sckHeat(MICS_5525, 32); //Corriente en mA
210 | sckHeat(MICS_2710, 26); //Corriente en mA
211 |
212 | RsCO = sckReadMICS(MICS_5525);
213 | RsNO2 = sckReadMICS(MICS_2710);
214 |
215 | }
216 |
217 | #if F_CPU == 8000000
218 | uint16_t sckReadSHT21(uint8_t type){
219 | uint16_t DATA = 0;
220 | Wire.beginTransmission(Temperature);
221 | Wire.write(type);
222 | Wire.endTransmission();
223 | Wire.requestFrom(Temperature,2);
224 | unsigned long time = millis();
225 | while (!Wire.available()) if ((millis() - time)>500) return 0x00;
226 | DATA = Wire.read()<<8;
227 | while (!Wire.available());
228 | DATA = (DATA|Wire.read());
229 | DATA &= ~0x0003;
230 | return DATA;
231 | }
232 |
233 | void sckGetSHT21()
234 | {
235 | #if DataRaw
236 | lastTemperature = sckReadSHT21(0xE3); // Datos en RAW para conversion por plataforma
237 | lastHumidity = sckReadSHT21(0xE5); // Datos en RAW para conversion por plataforma
238 | #else
239 | //T = -53 + 175.72 / 65536.0 * ( Traw * 10 )
240 | lastTemperature = (-50 + 175.72 / 65536.0 * ( sckReadSHT21(0xE3))) * 10 ;
241 | //H = 7 + 125.0 / 65536.0 * ( Hraw * 10 )
242 | lastHumidity = (4 + 125.0 / 65536.0 * ( sckReadSHT21(0xE5))) * 10 ;
243 | #endif
244 |
245 | #if debuggSCK
246 | Serial.print("SHT21: ");
247 | Serial.print("Temperatura: ");
248 | Serial.print(lastTemperature/10.);
249 | Serial.print(" C, Humedad: ");
250 | Serial.print(lastHumidity/10.);
251 | Serial.println(" %");
252 | #endif
253 | }
254 |
255 | void sckWriteADXL(byte address, byte val) {
256 | Wire.beginTransmission(ADXL); //start transmission to device
257 | Wire.write(address); // write register address
258 | Wire.write(val); // write value to write
259 | Wire.endTransmission(); //end transmission
260 | }
261 |
262 | //reads num bytes starting from address register on device in to buff array
263 | void sckrReadADXL(byte address, int num, byte buff[]) {
264 | Wire.beginTransmission(ADXL); //start transmission to device
265 | Wire.write(address); //writes address to read from
266 | Wire.endTransmission(); //end transmission
267 |
268 | Wire.beginTransmission(ADXL); //start transmission to device
269 | Wire.requestFrom(ADXL, num); // request 6 bytes from device
270 |
271 | int i = 0;
272 | unsigned long time = millis();
273 | while (!Wire.available())
274 | {
275 | if ((millis() - time)>500)
276 | {
277 | for(int i=0; i 5 BYTES
392 | for (int i=0; i<40; i++)
393 | {
394 | loopCnt = TIMEOUT;
395 | while(digitalRead(pin) == LOW)
396 | if (loopCnt-- == 0) return false;
397 |
398 | unsigned long t = micros();
399 |
400 | loopCnt = TIMEOUT;
401 | while(digitalRead(pin) == HIGH)
402 | if (loopCnt-- == 0) return false;
403 |
404 | if ((micros() - t) > 40) bits[idx] |= (1 << cnt);
405 | if (cnt == 0) // next byte?
406 | {
407 | cnt = 7;
408 | idx++;
409 | }
410 | else cnt--;
411 | }
412 |
413 | return true;
414 | }
415 | #endif
416 |
417 | uint16_t sckGetLight(){
418 | #if F_CPU == 8000000
419 | uint8_t TIME0 = 0xDA;
420 | uint8_t GAIN0 = 0x00;
421 | uint8_t DATA [8] = {0x03, TIME0, 0x00 ,0x00, 0x00, 0xFF, 0xFF ,GAIN0} ;
422 |
423 | uint16_t DATA0 = 0;
424 | uint16_t DATA1 = 0;
425 |
426 | Wire.beginTransmission(bh1730);
427 | Wire.write(0x80|0x00);
428 | for(int i= 0; i<8; i++) Wire.write(DATA[i]);
429 | Wire.endTransmission();
430 | delay(100);
431 | Wire.beginTransmission(bh1730);
432 | Wire.write(0x94);
433 | Wire.endTransmission();
434 | Wire.requestFrom(bh1730, 4);
435 | DATA0 = Wire.read();
436 | DATA0=DATA0|(Wire.read()<<8);
437 | DATA1 = Wire.read();
438 | DATA1=DATA1|(Wire.read()<<8);
439 |
440 | uint8_t Gain = 0x00;
441 | if (GAIN0 == 0x00) Gain = 1;
442 | else if (GAIN0 == 0x01) Gain = 2;
443 | else if (GAIN0 == 0x02) Gain = 64;
444 | else if (GAIN0 == 0x03) Gain = 128;
445 |
446 | float ITIME = (256- TIME0)*2.7;
447 |
448 | float Lx = 0;
449 | float cons = (Gain * 100) / ITIME;
450 | float comp = (float)DATA1/DATA0;
451 |
452 |
453 | if (comp<0.26) Lx = ( 1.290*DATA0 - 2.733*DATA1 ) / cons;
454 | else if (comp < 0.55) Lx = ( 0.795*DATA0 - 0.859*DATA1 ) / cons;
455 | else if (comp < 1.09) Lx = ( 0.510*DATA0 - 0.345*DATA1 ) / cons;
456 | else if (comp < 2.13) Lx = ( 0.276*DATA0 - 0.130*DATA1 ) / cons;
457 | else Lx=0;
458 |
459 | #if debuggSCK
460 | Serial.print("BH1730: ");
461 | Serial.print(Lx);
462 | Serial.println(" Lx");
463 | #endif
464 | return Lx*10;
465 | #else
466 | int temp = map(average(S5), 0, 1023, 0, 1000);
467 | if (temp>1000) temp=1000;
468 | if (temp<0) temp=0;
469 | return temp;
470 | #endif
471 | }
472 |
473 |
474 | unsigned int sckGetNoise() {
475 |
476 | #if F_CPU == 8000000
477 | #define GAIN 10000
478 | sckWriteGAIN(GAIN);
479 | delay(100);
480 | #endif
481 |
482 | float mVRaw = (float)((average(S4))/1023.)*Vcc;
483 | float dB = 0;
484 |
485 | #if F_CPU == 8000000
486 | #if DataRaw==false
487 | //dB = 0.0222*mVRaw + 58.006;
488 | //aplicar aqui conversion
489 | if(mVRaw<=5){
490 | dB = (5+44*mVRaw)/5;
491 | }else if(mVRaw<=15){
492 | dB = (195 + 8*mVRaw)/5;
493 | }else if(mVRaw<=40){
494 | dB = (1220 + 4*mVRaw)/20;
495 | }else if(mVRaw <= 300){
496 | //y=69.242283950617+0.038618827160494x
497 | dB = (69.242283950617 + 0.038618827160494*mVRaw);
498 | }else if(mVRaw <= 950){
499 | //y=76.744423542059+0.013363343187315x
500 | dB = (76.744423542059+0.013363343187315*mVRaw);
501 | } else {
502 | //y=80.167357356927+0.0085240259833374x
503 | dB = (80.167357356927+0.0085240259833374*mVRaw);
504 | }
505 | #endif
506 | #else
507 | #if DataRaw==false
508 | dB = 9.7*log( (mVRaw*200)/1000. ) + 40; // calibracion para ruido rosa // energia constante por octava
509 | if (dB<50) dB = 50; // minimo con la resolucion actual!
510 | #endif
511 | #endif
512 |
513 | #if debuggSCK
514 | Serial.print("nOISE = ");
515 | Serial.print(mVRaw);
516 | #if DataRaw==false
517 | Serial.print(" mV nOISE = ");
518 | Serial.print(dB);
519 | Serial.print(" dB, GAIN = ");
520 | #else
521 | Serial.print(" mV GAIN = ");
522 | #endif
523 | Serial.println(GAIN);
524 | #endif
525 |
526 | #if DataRaw
527 | return mVRaw;
528 | #else
529 | return dB*100;
530 | #endif
531 | }
532 |
533 | unsigned long sckGetCO()
534 | {
535 | return RsCO;
536 | }
537 |
538 | unsigned long sckGetNO2()
539 | {
540 | return RsNO2;
541 | }
542 |
543 |
544 |
--------------------------------------------------------------------------------
/sck_beta_v0_8_7_SDCARD/SCKBase.ino:
--------------------------------------------------------------------------------
1 | boolean connected;
2 |
3 | #define buffer_length 32
4 | static char buffer[buffer_length];
5 |
6 | #define TWI_FREQ 400000L //Frecuencia bus I2C
7 |
8 | void sckBegin() {
9 | Wire.begin();
10 | TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
11 | Serial.begin(115200);
12 | Serial1.begin(9600);
13 | pinMode(IO0, OUTPUT); //VH_MICS5525
14 | pinMode(IO1, OUTPUT); //VH_MICS2710
15 | pinMode(IO2, OUTPUT); //MICS2710_ALTAIMPEDANCIA
16 | pinMode(AWAKE, OUTPUT);
17 | pinMode(MOSI, OUTPUT);
18 | pinMode(SCK, OUTPUT);
19 | pinMode(FACTORY, OUTPUT);
20 | pinMode(CONTROL, INPUT);
21 | digitalWrite(AWAKE, HIGH);
22 | digitalWrite(FACTORY, LOW);
23 | #if ((decouplerComp)&&(F_CPU > 8000000 ))
24 | decoupler.setup();
25 | #endif
26 | #if F_CPU == 8000000
27 | sckWriteCharge(350);
28 |
29 | sckWriteVH(MICS_5525, 2700); //VH_MICS5525 Inicial
30 | digitalWrite(IO0, HIGH); //VH_MICS5525
31 |
32 | sckWriteVH(MICS_2710, 1700); //VH_MICS5525 Inicial
33 | digitalWrite(IO1, HIGH); //VH_MICS2710
34 | digitalWrite(IO2, LOW); //RADJ_MICS2710 PIN ALTA IMPEDANCIA
35 |
36 | pinMode(IO3, OUTPUT);
37 | digitalWrite(IO3, HIGH); //Alimentacion de los MICS
38 |
39 | #if ADXLEnabled
40 | sckWriteADXL(0x2D, 0x08);
41 | // sckWriteADXL(0x31, 0x00); //2g
42 | // sckWriteADXL(0x31, 0x01); //4g
43 | sckWriteADXL(0x31, 0x02); //8g
44 | // sckWriteADXL(0x31, 0x03); //16g
45 | #endif
46 |
47 | #else
48 | sckWriteVH(MICS_5525, 2400); //VH_MICS5525 Inicial
49 | digitalWrite(IO0, HIGH); //VH_MICS5525
50 |
51 | sckWriteVH(MICS_2710, 1700); //VH_MICS5525 Inicial
52 | digitalWrite(IO1, HIGH); //VH_MICS2710
53 | digitalWrite(IO2, LOW); //RADJ_MICS2710 PIN ALTA IMPEDANCIA
54 | #endif
55 |
56 | sckWriteRL(MICS_5525, 100000); //Inicializacion de la carga del MICS5525
57 | sckWriteRL(MICS_2710, 100000); //Inicializacion de la carga del MICS2710
58 | }
59 |
60 | void sckConfig(){
61 |
62 | if (!sckCompareDate(__TIME__, sckReadData(EE_ADDR_TIME_VERSION, 0, 0)))
63 | {
64 | sckRTCadjust(sckDate(__DATE__,__TIME__));
65 | #if debuggEnabled
66 | Serial.println(F("Resetting..."));
67 | #endif
68 | for(uint16_t i=0; i<60; i++) sckWriteEEPROM(i, 0x00); //Borrado de la memoria
69 | sckWriteData(EE_ADDR_TIME_VERSION, 0, __TIME__);
70 | sckWriteData(EE_ADDR_TIME_UPDATE, 0, DEFAULT_TIME_UPDATE);
71 | sckWriteData(EE_ADDR_NUMBER_UPDATES, 0, DEFAULT_MIN_UPDATES);
72 | }
73 |
74 | }
75 |
76 | float average(int anaPin) {
77 | int lecturas = 100;
78 | long total = 0;
79 | float average = 0;
80 | for(int i=0; iRES) data=RES;
106 | Wire.beginTransmission(deviceaddress);
107 | address=(address<<4)|bitRead(data, 8) ;
108 | Wire.write(address);
109 | Wire.write(lowByte(data));
110 | Wire.endTransmission();
111 | delay(4);
112 | }
113 |
114 | int sckReadMCP(int deviceaddress, uint16_t address ) {
115 | byte rdata = 0xFF;
116 | int data = 0x0000;
117 | Wire.beginTransmission(deviceaddress);
118 | address=(address<<4)|B00001100;
119 | Wire.write(address);
120 | Wire.endTransmission();
121 | Wire.requestFrom(deviceaddress,2);
122 | unsigned long time = millis();
123 | while (!Wire.available()) if ((millis() - time)>500) return 0x00;
124 | rdata = Wire.read();
125 | data=rdata<<8;
126 | while (!Wire.available());
127 | rdata = Wire.read();
128 | data=data|rdata;
129 | return data;
130 | }
131 |
132 | #if F_CPU == 8000000
133 | float sckReadCharge() {
134 | float resistor = kr*sckReadMCP(MCP3, 0x00)/1000;
135 | float current = 1000./(2+((resistor * 10)/(resistor + 10)));
136 | #if debuggSCK
137 | Serial.print("Resistor : ");
138 | Serial.print(resistor);
139 | Serial.print(" kOhm, ");
140 | Serial.print("Current : ");
141 | Serial.print(current);
142 | Serial.println(" mA");
143 | #endif
144 | return(current);
145 | }
146 |
147 | void sckWriteCharge(int current) {
148 | if (current < 100) current = 100;
149 | else if (current > 500) current = 500;
150 | float Rp = (1000./current)-2;
151 | float resistor = Rp*10/(10-Rp);
152 | sckWriteMCP(MCP3, 0x00, (uint8_t)(resistor*1000/kr));
153 | #if debuggSCK
154 | Serial.print("Rc : ");
155 | Serial.print(Rp + 2);
156 | Serial.print(" kOhm, ");
157 | Serial.print("Rpot : ");
158 | Serial.print(resistor);
159 | Serial.print(" kOhm, ");
160 | Serial.print("Current : ");
161 | Serial.print(current);
162 | Serial.println(" mA");
163 | #endif
164 | }
165 | #endif
166 |
167 | void sckWriteEEPROM(uint16_t eeaddress, uint8_t data ) {
168 | uint8_t retry = 0;
169 | while ((sckReadEEPROM(eeaddress)!=data)&&(retry<10))
170 | {
171 | EEPROM.write(eeaddress, data);
172 | delay(6);
173 | retry++;
174 | }
175 | }
176 |
177 | byte sckReadEEPROM(uint16_t eeaddress ) {
178 | return EEPROM.read(eeaddress);
179 | }
180 |
181 |
182 | void sckWriteintEEPROM(uint16_t eeaddress, uint16_t data )
183 | {
184 | sckWriteEEPROM(eeaddress , highByte(data));
185 | sckWriteEEPROM(eeaddress + 1, lowByte(data));
186 | }
187 |
188 | uint16_t sckReadintEEPROM(uint16_t eeaddress)
189 | {
190 | return (sckReadEEPROM(eeaddress)<<8)+ sckReadEEPROM(eeaddress + 1);
191 | }
192 |
193 | char* sckReadData(uint16_t eeaddress, uint16_t pos, uint8_t dec)
194 | {
195 | eeaddress = eeaddress + buffer_length * pos;
196 | uint8_t temp = sckReadEEPROM(eeaddress);
197 | uint16_t i;
198 | for ( i = eeaddress; ((temp!= 0x00)&&(temp<0x7E)&&(temp>0x1F)&&((i - eeaddress)0))
204 | {
205 | if ((i - eeaddress)500) return false;
235 | Wire.read();
236 | return true;
237 | }
238 |
239 |
240 | char* sckDate(const char* date, const char* time){
241 | int j = 0;
242 | for (int i = 7; date[i]!=0x00; i++)
243 | {
244 | buffer[j] = date[i];
245 | j++;
246 | }
247 | buffer[j] = '-';
248 | j++;
249 | // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
250 | switch (date[0]) {
251 | case 'J':
252 | if (date[1] == 'a') buffer[j] = '1';
253 | else if (date[2] == 'n') buffer[j] = '6';
254 | else buffer[j] = '7';
255 | break;
256 | case 'F':
257 | buffer[j] = '2';
258 | break;
259 | case 'A':
260 | if (date[1] == 'p') buffer[j] = '4';
261 | else buffer[j] = '8';
262 | break;
263 | case 'M':
264 | if (date[2] == 'r') buffer[j] = '3';
265 | else buffer[j] = '5';
266 | break;
267 | case 'S':
268 | buffer[j] = '9';
269 | break;
270 | case 'O':
271 | buffer[j] = '1';
272 | buffer[j+1] = '0';
273 | j++;
274 | break;
275 | case 'N':
276 | buffer[j] = '1';
277 | buffer[j+1] = '1';
278 | j++;
279 | break;
280 | case 'D':
281 | buffer[j] = '1';
282 | buffer[j+1] = '2';
283 | j++;
284 | break;
285 | }
286 | j++;
287 | buffer[j] = '-';
288 | j++;
289 | for (int i = 4; date[i]!=' '; i++)
290 | {
291 | buffer[j] = date[i];
292 | j++;
293 | }
294 | buffer[j] = ' ';
295 | j++;
296 | for (int i = 0; time[i]!=0x00; i++)
297 | {
298 | buffer[j] = time[i];
299 | j++;
300 | }
301 | buffer[j]=0x00;
302 | return buffer;
303 | }
304 |
305 | boolean sckRTCadjust(char *time) {
306 | byte rtc[6] = {
307 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
308 | };
309 | byte count = 0x00;
310 | byte data_count=0;
311 | while (time[count]!=0x00)
312 | {
313 | if(time[count] == '-') data_count++;
314 | else if(time[count] == ' ') data_count++;
315 | else if(time[count] == ':') data_count++;
316 | else if ((time[count] >= '0')&&(time[count] <= '9'))
317 | {
318 | rtc[data_count] =(rtc[data_count]<<4)|(0x0F&time[count]);
319 | }
320 | else break;
321 | count++;
322 | }
323 | if (data_count == 5)
324 | {
325 | #if F_CPU == 8000000
326 | Wire.beginTransmission(RTC_ADDRESS);
327 | Wire.write((int)0);
328 | Wire.write(rtc[5]);
329 | Wire.write(rtc[4]);
330 | Wire.write(rtc[3]);
331 | Wire.write(0x00);
332 | Wire.write(rtc[2]);
333 | Wire.write(rtc[1]);
334 | Wire.write(rtc[0]);
335 | Wire.endTransmission();
336 | delay(4);
337 | Wire.beginTransmission(RTC_ADDRESS);
338 | Wire.write(0x0E); //Address
339 | Wire.write(0x00); //Value
340 | Wire.endTransmission();
341 | #else
342 | Wire.beginTransmission(RTC_ADDRESS);
343 | Wire.write((int)0);
344 | Wire.write(rtc[5]);
345 | Wire.write(rtc[4]);
346 | Wire.write(rtc[3]);
347 | Wire.write(0x00);
348 | Wire.write(rtc[2]);
349 | Wire.write(rtc[1]);
350 | Wire.write(rtc[0]);
351 | Wire.write((int)0);
352 | Wire.endTransmission();
353 | return true;
354 | #endif
355 | return true;
356 | }
357 | return false;
358 | }
359 |
360 | char* sckRTCtime() {
361 | Wire.beginTransmission(RTC_ADDRESS);
362 | Wire.write((int)0);
363 | Wire.endTransmission();
364 | Wire.requestFrom(RTC_ADDRESS, 7);
365 | uint8_t seconds = (Wire.read() & 0x7F);
366 | uint8_t minutes = Wire.read();
367 | uint8_t hours = Wire.read();
368 | Wire.read();
369 | uint8_t day = Wire.read();
370 | uint8_t month = Wire.read();
371 | uint8_t year = Wire.read();
372 | buffer[0] = '2';
373 | buffer[1] = '0';
374 | buffer[2] = (year>>4) + '0';
375 | buffer[3] = (year&0x0F) + '0';
376 | buffer[4] = '-';
377 | buffer[5] = (month>>4) + '0';
378 | buffer[6] = (month&0x0F) + '0';
379 | buffer[7] = '-';
380 | buffer[8] = (day>>4) + '0';
381 | buffer[9] = (day&0x0F) + '0';
382 | buffer[10] = ' ';
383 | buffer[11] = (hours>>4) + '0';
384 | buffer[12] = (hours&0x0F) + '0';
385 | buffer[13] = ':';
386 | buffer[14] = (minutes>>4) + '0';
387 | buffer[15] = (minutes&0x0F) + '0';
388 | buffer[16] = ':';
389 | buffer[17] = (seconds>>4) + '0';
390 | buffer[18] = (seconds&0x0F) + '0';
391 | buffer[19] = 0x00;
392 | return buffer;
393 | }
394 |
395 |
396 | uint16_t sckGetPanel(){
397 | #if F_CPU == 8000000
398 | uint16_t value = 11*average(PANEL)*Vcc/1023.;
399 | if (value > 500) value = value + 120; //Tension del diodo de proteccion
400 | else value = 0;
401 | #else
402 | uint16_t value = 3*average(PANEL)*Vcc/1023.;
403 | if (value > 500) value = value + 750; //Tension del diodo de proteccion
404 | else value = 0;
405 | #endif
406 | #if debuggSCK
407 | Serial.print("Panel = ");
408 | Serial.print(value);
409 | Serial.println(" mV");
410 | #endif
411 | return value;
412 | }
413 |
414 | uint16_t sckGetBattery() {
415 | uint16_t temp = average(BAT);
416 | #if F_CPU == 8000000
417 | float voltage = Vcc*temp/1023.;
418 | voltage = voltage + (voltage/180)*100;
419 | #else
420 | float voltage = Vcc*temp/1023.;
421 | #endif
422 | temp = map(voltage, VAL_MIN_BATTERY, VAL_MAX_BATTERY, 0, 1000);
423 | if (temp>1000) temp=1000;
424 | if (temp<0) temp=0;
425 | #if debuggSCK
426 | Serial.print("Vbat: ");
427 | Serial.print(voltage);
428 | Serial.print(" mV, ");
429 | Serial.print("Battery level: ");
430 | Serial.print(temp/10.);
431 | Serial.println(" %");
432 | #endif
433 | return temp;
434 | }
435 |
436 | #define COMMAND_MODE_GUARD_TIME 250 // in milliseconds
437 |
438 | boolean sckSleep() {
439 | delay(COMMAND_MODE_GUARD_TIME);
440 | Serial1.print(F("$$$"));
441 | delay(COMMAND_MODE_GUARD_TIME);
442 | Serial1.println();
443 | Serial1.println();
444 | Serial1.println(F("sleep"));
445 | }
446 |
447 | char* itoa(int32_t number)
448 | {
449 | byte count = 0;
450 | uint32_t temp;
451 | if (number < 0) {
452 | temp = number*(-1);
453 | count++;
454 | }
455 | while ((temp/10)!=0)
456 | {
457 | temp = temp/10;
458 | count++;
459 | }
460 | int i;
461 | if (number < 0) {
462 | temp = number*(-1);
463 | }
464 | else temp = number;
465 | for (i = count; i>=0; i--)
466 | {
467 | buffer[i] = temp%10 + '0';
468 | temp = temp/10;
469 | }
470 | if (number < 0) {
471 | buffer[0] = '-';
472 | }
473 | buffer[count + 1] = 0x00;
474 | return buffer;
475 | }
476 |
477 |
478 |
479 |
480 |
481 |
482 |
483 |
484 |
485 |
486 |
487 |
488 |
489 |
490 |
491 |
492 |
493 |
--------------------------------------------------------------------------------
/sck_beta_v0_8_7_SDCARD/SDUpdate.ino:
--------------------------------------------------------------------------------
1 | void txSD() {
2 | Serial.println("*** txSD ***");
3 | // if the file opened okay, write to it:
4 | if (myFile.open("post.csv", FILE_WRITE)) {
5 | #if debuggEnabled
6 | Serial.println(F("Writing..."));
7 | #endif
8 | float dec = 0;
9 | for (int i=0; i<8; i++)
10 | {
11 | if (i<4) dec = 10;
12 | else if (i<7) dec = 1000;
13 | else if (i<8) dec = 100;
14 | else dec = 1;
15 |
16 | //myFile.print(i);
17 | //myFile.print(" ");
18 | myFile.print(SENSORvalue[i]/dec);
19 | myFile.print(",");
20 | }
21 | myFile.print(sckRTCtime());
22 | myFile.println();
23 | // close the file:
24 | myFile.close();
25 | #if debuggEnabled
26 | Serial.println(F("Closing..."));
27 | #endif
28 | }
29 | }
30 |
31 | char* SENSOR[10]={
32 | "Temperature",
33 | "Humidity",
34 | "Light",
35 | "Battery",
36 | "Solar Panel",
37 | "Carbon Monxide",
38 | "Nitrogen Dioxide",
39 | "Noise",
40 | "Wifi Spots",
41 | "UTC"
42 | };
43 |
44 | char* UNITS[10]={
45 | #if F_CPU == 8000000
46 | #if DataRaw
47 | " C RAW",
48 | " % RAW",
49 | #else
50 | " C",
51 | " %",
52 | #endif
53 | #else
54 | " C",
55 | " %",
56 | #endif
57 | #if F_CPU == 8000000
58 | " lx",
59 | #else
60 | " %",
61 | #endif
62 | " %",
63 | " V",
64 | " kOhm",
65 | " kOhm",
66 | #if DataRaw
67 | " mV",
68 | #else
69 | " dB",
70 | #endif
71 | "",
72 | ""
73 | };
74 |
75 | void updateSensorsSD() {
76 | #if F_CPU == 8000000
77 | sckGetVcc();
78 | sckGetSHT21();
79 | SENSORvalue[0] = lastTemperature; // C
80 | SENSORvalue[1] = lastHumidity; // %
81 | #else
82 | if (sckDHT22(IO3))
83 | {
84 | SENSORvalue[0] = lastTemperature; // C
85 | SENSORvalue[1] = lastHumidity; // %
86 | }
87 | #endif
88 | sckGetMICS();
89 | SENSORvalue[2] = sckGetLight(); // %
90 | SENSORvalue[3] = sckGetBattery(); //%
91 | SENSORvalue[4] = sckGetPanel(); // %
92 | SENSORvalue[5] = sckGetCO(); //Ohm
93 | SENSORvalue[6] = sckGetNO2(); //Ohm
94 | SENSORvalue[7] = sckGetNoise(); //dB
95 | }
96 |
97 | void txDebugSD() {
98 | Serial.println("*** txDebugSD ***");
99 | float dec = 0;
100 | for(int i=0; i<8; i++)
101 | {
102 | if (i<4) dec = 10;
103 | else if (i<7) dec = 1000;
104 | else if (i<8) dec = 100;
105 | else dec = 1;
106 | Serial.print(SENSOR[i]);
107 | Serial.print(": ");
108 | Serial.print((SENSORvalue[i])/dec);
109 | Serial.println(UNITS[i]);
110 | }
111 | Serial.print(SENSOR[9]);
112 | Serial.print(": ");
113 | Serial.println(sckRTCtime());
114 | Serial.println(F("*******************"));
115 | }
116 |
117 | void txHeader() {
118 | Serial.println("*** txHeader ***");
119 | // if the file opened okay, write to it:
120 | if (myFile.open("post.csv", FILE_WRITE)) {
121 | #if debuggEnabled
122 | Serial.println(F("Writing..."));
123 | #endif
124 | for (int i=0; i<8; i++)
125 | {
126 | myFile.print(SENSOR[i]);
127 | myFile.print(" (");
128 | myFile.print(UNITS[i]);
129 | myFile.print(") ");
130 | myFile.print(", ");
131 | }
132 | myFile.print(SENSOR[9]);
133 | myFile.println();
134 | // close the file:
135 | myFile.close();
136 | #if debuggEnabled
137 | Serial.println(F("Closing..."));
138 | #endif
139 | }
140 | }
141 |
142 |
143 |
--------------------------------------------------------------------------------
/sck_beta_v0_8_7_SDCARD/TemperatureDecoupler.h:
--------------------------------------------------------------------------------
1 | //
2 | // TemperatureDecoupler.h
3 | // SmartCitizen
4 | //
5 | // Created by Oriol Ferrer Mesià on 03/06/13.
6 | //
7 | //
8 |
9 | #ifndef SmartCitizen_TemperatureDecoupler_h
10 | #define SmartCitizen_TemperatureDecoupler_h
11 |
12 | #define BATTERY_HEATUP_MAX 11
13 | #define BATTERY_CHARGE_THRESHOLD 980
14 | #include
15 | #include "AccumulatorFilter.h"
16 |
17 |
18 | class TemperatureDecoupler{
19 |
20 | public:
21 |
22 | void setup(){
23 | _prevBattery = 0;
24 | filter.setup(0.3);
25 | }
26 |
27 | void update( uint16_t battery ){
28 |
29 | //Serial.println( "# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #" );
30 |
31 | bool charging = false;
32 | bool doNothing = false;
33 | if (battery == _prevBattery){
34 | //doNothing;
35 | if ( battery > BATTERY_CHARGE_THRESHOLD ){
36 | charging = true;
37 | //Serial.println( "Battery same val > 980! charging!");
38 | }else{
39 | charging = false;
40 | //Serial.println( "Battery same val < 980! NOT charging!");
41 | }
42 | }else{
43 | if ( battery > _prevBattery || battery > BATTERY_CHARGE_THRESHOLD ){ //battery is charging!
44 | //Serial.println( "Battery charging!");
45 | charging = true;
46 | }else{ //battery is being drained
47 | //Serial.println( "Battery dis-charging!");
48 | charging = false;
49 | }
50 | }
51 |
52 | if (!doNothing){
53 | if(charging)
54 | filter.goUp();
55 | else
56 | filter.goDown();
57 | }
58 |
59 | //Serial.print(F("battery: ")); Serial.println( battery );
60 | //Serial.print(F("_prevBattery: ")); Serial.println( _prevBattery );
61 | //Serial.print(F("filter: ")); Serial.println( filter.getVal() );
62 |
63 | //Serial.println( "# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #" );
64 | //store last bat reading for future comparing
65 | _prevBattery = battery;
66 | lastChargingState = charging;
67 | }
68 |
69 | short int getCompensation(){
70 | return (short int) (filter.getVal() * BATTERY_HEATUP_MAX);
71 | }
72 |
73 | short int _prevBattery;
74 | AccumulatorFilter filter;
75 | bool lastChargingState; //true == up, false == down
76 |
77 | };
78 |
79 |
80 | #endif
81 |
--------------------------------------------------------------------------------
/sck_beta_v0_8_7_SDCARD/sck_beta_v0_8_7_SDCARD.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include "Constants.h"
6 |
7 | #define USBEnabled true
8 | #define sensorEnabled true
9 | #define debuggEnabled true
10 | #define ADXLEnabled false
11 |
12 | uint32_t timetransmit = 0;
13 | uint32_t TimeUpdate = 0; //Variable temporal de tiempo entre actualizacion y actualizacion de los sensensores
14 | uint32_t NumUpdates = 0; //Numero de actualizaciones antes de postear
15 |
16 | SdFat sd;
17 | SdFile myFile;
18 | long SENSORvalue[8];
19 | boolean csvInit = false;
20 |
21 | void setup() {
22 |
23 | delay(5000);
24 |
25 | sckBegin();
26 | sckConfig();
27 | sckSleep();
28 | #if debuggEnabled
29 | Serial.print(F("Initializing SD card..."));
30 | #endif
31 | if (!sd.begin(11)) {
32 | #if debuggEnabled
33 | Serial.println(F("initialization failed!"));
34 | #endif
35 | return;
36 | }
37 | #if debuggEnabled
38 | Serial.println(F("initialization done."));
39 | #endif
40 | if (!sd.exists("post.csv")) {
41 | #if debuggEnabled
42 | Serial.println(F("Creating post.csv..."));
43 | #endif
44 | myFile.open("post.csv", FILE_WRITE);
45 | myFile.close();
46 | delay(1000);
47 | txHeader();
48 |
49 | } else{
50 | #if debuggEnabled
51 | Serial.println(F("post.csv exists ..."));
52 | #endif
53 | }
54 |
55 | timetransmit = millis();
56 | TimeUpdate = atol(sckReadData(EE_ADDR_TIME_UPDATE, 0, 0)); //Tiempo entre transmision y transmision en segundos
57 | }
58 |
59 | void loop() {
60 | #if sensorEnabled
61 | if ((millis()-timetransmit) >= (unsigned long)TimeUpdate*1000)
62 | {
63 | Serial.println("*** loop ***");
64 | timetransmit = millis();
65 | TimeUpdate = atol(sckReadData(EE_ADDR_TIME_UPDATE, 0, 0));
66 | updateSensorsSD();
67 | txSD();
68 | #if USBEnabled
69 | txDebugSD();
70 | #endif
71 | }
72 | #endif
73 | }
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/sck_beta_v0_9/AccumulatorFilter.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | AccumulatorFilter.h
4 | AccumulatorFilter
5 | Created by Oriol Ferrer Mesià on 09/06/13.
6 |
7 | */
8 |
9 | #ifndef AccumulatorFilter_AccumulatorFilter_h
10 | #define AccumulatorFilter_AccumulatorFilter_h
11 |
12 | #define GHETTO_VAL 0.02f
13 | class AccumulatorFilter{
14 |
15 | public:
16 |
17 | AccumulatorFilter(){
18 | val = GHETTO_VAL;
19 | upSpeed = 0.5f;
20 | }
21 |
22 | void setup(float upSpeed_){
23 | val = 0.0f;
24 | upSpeed = upSpeed_;
25 | }
26 |
27 | void goUp(){
28 | //Serial.println( "goUP!");
29 | if (val <= GHETTO_VAL){
30 | val = GHETTO_VAL;
31 | }
32 | val *= (1.0f + upSpeed * 2.0f * (1.0f - val) );
33 | }
34 |
35 | void goDown(){
36 | //Serial.println( "goDown!");
37 | if (val >= 1.0f - GHETTO_VAL){
38 | val = 1.0f - GHETTO_VAL;
39 | }
40 | val /= (1.0f + upSpeed * 2.0f * (1.0f - val) );
41 | }
42 |
43 | float getVal(){
44 | return val;
45 | }
46 |
47 | float getSpeed(){
48 | return upSpeed;
49 | }
50 |
51 | float upSpeed;
52 | float val;
53 | };
54 |
55 | #endif
56 |
--------------------------------------------------------------------------------
/sck_beta_v0_9/Constants.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Constants.h
4 | Defines ATMEGA32U4 pins and other SENSORS and COMUNICATIONS static parameters.
5 |
6 | */
7 |
8 | #define debugEnabled true
9 | #define decouplerComp true //Only for version Goteo 1.0
10 |
11 | #if F_CPU == 8000000
12 | #define FirmWare "1.1-0.9.4"
13 | #else
14 | #define FirmWare "1.0-0.9.4"
15 | #endif
16 |
17 | /*
18 |
19 | WIFI AND SERVER STATICS - WiFly, Http server parameters.
20 |
21 | */
22 | // WiFly Auth Modes
23 | #define OPEN "0"
24 | #define WEP "1"
25 | #define WPA "2"
26 | #define MIXED "3"
27 | #define WPA2 "4"
28 | #define WEP64 "8"
29 |
30 | #define EXT_ANT "1" // External Antenna
31 | #define INT_ANT "0" // Internal Antenna
32 |
33 | /*
34 |
35 | WIFLY Firmware Setting
36 |
37 | */
38 |
39 | #define networks 0
40 | #if (networks > 0)
41 | static char* mySSID[networks] = {
42 | "SSID1" , "SSID2" };
43 | static char* myPassword[networks] = {
44 | "PASS1" , "PASS2" };
45 | static char* wifiEncript[networks] = {
46 | WPA2 , WPA2 };
47 | static char* antennaExt[networks] = {
48 | INT_ANT , INT_ANT };
49 | #endif
50 |
51 | #define TWI_FREQ 400000L //Frecuencia bus I2C
52 |
53 | #define WIFLY_LATEST_VERSION 475
54 | #define DEFAULT_WIFLY_FIRMWARE "ftp update wifly3-475.img"
55 | #define DEFAULT_WIFLY_FTP_UPDATE "set ftp address 198.175.253.161"
56 |
57 | /*
58 |
59 | ARDUINO ports definitions - GPIOS and ADCs
60 |
61 | */
62 |
63 | #define AWAKE 4 // WIFLY AWAKE
64 | #define PANEL A8 // PANEL LEVEL
65 | #define BAT A7 // BAT LEVEL
66 |
67 | #define IO0 5 // MICS5525_HEATHER
68 | #define IO1 13 // MICS2710_HEATHER
69 | #define IO2 9 // MICS2710_HIGH_IMPEDANCE
70 | #define IO3 10 // MICS2710_HIGH_IMPEDANCE
71 | #define FACTORY 7 // WIFLY - Factory RESET/AP RN131
72 | #define CONTROL 12 // WIFLY - CONTROL
73 |
74 | #define S0 A4 //MICS_5525
75 | #define S1 A5 //MICS_2710
76 | #define S2 A2 //SENS_5525
77 | #define S3 A3 //SENS_2710
78 | #define S4 A0 //MICRO
79 | #define S5 A1 //LDR
80 |
81 |
82 | /*
83 |
84 | SENSOR READINGS - Defaults
85 |
86 | */
87 |
88 | #define DEFAULT_TIME_UPDATE 60 //Time between update and update
89 | #define MIN_TIME_UPDATE 10 //Minimum time between updates (minimum time to read all the sensors)
90 | #define MAX_TIME_UPDATE 3600 //Max time between updates (one hour)
91 | #define DEFAULT_MIN_UPDATES 1 //Minimum number of updates before posting
92 | #define POST_MAX 20 //Max number of postings at a time
93 | #define DEFAULT_MODE_SENSOR NORMAL //Type sensors capture (OFFLINE, NOWIFI, NORMAL, ECONOMIC)
94 |
95 | /*
96 |
97 | i2c ADDRESSES
98 |
99 | */
100 | #define RTC_ADDRESS 0x68 // Direction of the RTC
101 | #define E2PROM 0x50 // Direction of the EEPROM
102 |
103 | #if F_CPU == 8000000
104 | #define MCP1 0x2E // Direction of the mcp1 Potenciometers that control the MICS
105 | #define MCP2 0x2F // Direction of the mcp2 Potenciometers that control the microfone pickup
106 | #define bh1730 0x29 // Direction of the light sensor
107 | #define Temperature 0x40 // Direction of the sht21
108 | #define ADXL 0x53 //ADXL345 device address
109 | #else
110 | #define MCP1 0x2F // Direction of the mcp1 MICS
111 | #define MCP2 0x2E // Direction of the mcp2 REGULATORS
112 | #endif
113 |
114 | #if F_CPU == 8000000
115 | #define R1 12 //Kohm
116 | #else
117 | #define R1 82 //Kohm
118 | #endif
119 |
120 | #define P1 100 //Kohm
121 |
122 |
123 | /*
124 |
125 | Internal EEPROM Memory Addresses
126 |
127 | */
128 |
129 | #define MAX_MEMORY 571 //Memory size
130 |
131 | // SCK Configuration Parameters
132 | #define EE_ADDR_TIME_VERSION 0 //32BYTES
133 | #define EE_ADDR_TIME_UPDATE 32 //4BYTES Time between update and update of the sensors in seconds
134 | #define EE_ADDR_SENSOR_MODE 36 //4BYTES Type sensors capture
135 | #define EE_ADDR_NUMBER_UPDATES 40 //4BYTES Number of updates before posting
136 | #define EE_ADDR_NUMBER_READ_MEASURE 44 //4BYTES Number of updates before posting
137 | #define EE_ADDR_NUMBER_WRITE_MEASURE 48 //4BYTES Number of updates before posting
138 | #define EE_ADDR_NUMBER_NETS 52 //4BYTES Number of networks in the memory
139 | #define EE_ADDR_APIKEY 56 //32BYTES Apikey of the device
140 | #define EE_ADDR_MAC 100 //32BYTES MAC of the device
141 |
142 | // SCK WIFI SETTINGS Parameters
143 | #define DEFAULT_ADDR_SSID 150 //160 BYTES
144 | #define DEFAULT_ADDR_PASS 310 //160 BYTES
145 | #define DEFAULT_ADDR_AUTH 470 //160 BYTES
146 | #define DEFAULT_ADDR_ANTENNA 630 //160 BYTES
147 |
148 |
149 | /*
150 |
151 | External EEPROM Memory Addresses
152 |
153 | */
154 |
155 | // SCK DATA SPACE (Sensor readings can be stored here to do batch updates)
156 | #define DEFAULT_ADDR_MEASURES 0
157 |
158 |
159 | /*
160 |
161 | MICS PARAMETERS - Gas Sensor Addresses and Defaults
162 |
163 | */
164 |
165 | #define MICS_5525 0x00
166 | #define MICS_2710 0x01
167 |
168 | #define RES 256 // Digital pot. resolution
169 | #define P1 100 //Digital potentiometer resistance 100Kohm
170 |
171 | #define Rc0 10. //Ohm. Average current resistance for sensor MICS_5525/MICS_5524
172 |
173 | #if F_CPU == 8000000
174 | #define Rc1 39. //Ohm. Average current resistance for sensor MICS_2714
175 | #else
176 | #define Rc1 10. //Ohm. Average current resistance for sensor MICS_2710
177 | #endif
178 |
179 | #if F_CPU == 8000000
180 | #define VMIC0 2734.
181 | #define VMIC1 2734.
182 | #else
183 | #define VMIC0 5000.
184 | #define VMIC1 2500.
185 | #endif
186 |
187 | #define reference 2560.
188 | #define second 1000
189 | #define minute 60000
190 |
191 | /*
192 |
193 | BATTERY PARAMETERS - Battery sensing calibration parameters
194 |
195 | */
196 |
197 | #if F_CPU == 8000000
198 | #define VAL_MAX_BATTERY 4200
199 | #define VAL_MIN_BATTERY 3000
200 | #else
201 | #define VAL_MAX_BATTERY 4050
202 | #define VAL_MIN_BATTERY 3000
203 | #endif
204 |
205 |
206 | #define DHTLIB_INVALID_VALUE -999
207 |
208 | #define OFFLINE 0 //No connect to server
209 | #define NOWIFI 1 //No connect arduino to wifi module
210 | #define NORMAL 2 //Nomal mode o real time
211 | #define ECONOMIC 3 //Economic mode, sensor gas active one time for hour
212 |
213 | #define SENSORS 9 //Numbers of sensors in the board
214 |
215 | #define buffer_length 32
216 | static char buffer[buffer_length];
217 |
218 | // Basic Server Posts to the SmartCitizen Platform - EndPoint: http://data.smartcitizen.me/add
219 | static char* WEB[8]={
220 | "data.smartcitizen.me",
221 | "PUT /add HTTP/1.1\n",
222 | "Host: data.smartcitizen.me \n",
223 | "User-Agent: SmartCitizen \n",
224 | "X-SmartCitizenMacADDR: ",
225 | "X-SmartCitizenApiKey: ",
226 | "X-SmartCitizenVersion: ",
227 | "X-SmartCitizenData: "};
228 |
229 | // Time server request - EndPoint: http://data.smartcitizen.me/datetime
230 | static char* WEBTIME[3]={
231 | /*Servidor de tiempo*/
232 | "GET /datetime HTTP/1.1\n",
233 | "Host: data.smartcitizen.me \n",
234 | "User-Agent: SmartCitizen \n\n"
235 | };
236 |
237 | // Data JSON structure
238 | static char* SERVER[11]={
239 | "{\"temp\":\"",
240 | "\",\"hum\":\"",
241 | "\",\"light\":\"",
242 | "\",\"bat\":\"",
243 | "\",\"panel\":\"",
244 | "\",\"co\":\"",
245 | "\",\"no2\":\"",
246 | "\",\"noise\":\"",
247 | "\",\"nets\":\"",
248 | "\",\"timestamp\":\"",
249 | "\"}"
250 | };
251 |
252 | static char* SENSOR[10]={
253 | "Temperature: ",
254 | "Humidity: ",
255 | "Light: ",
256 | "Battery: ",
257 | "Solar Panel: ",
258 | "Carbon Monxide: ",
259 | "Nitrogen Dioxide: ",
260 | "Noise: ",
261 | "Wifi Spots: ",
262 | "UTC: "
263 | };
264 |
265 | static char* UNITS[9]={
266 | #if F_CPU == 8000000
267 | " C RAW",
268 | " % RAW",
269 | #else
270 | " C",
271 | " %",
272 | #endif
273 | #if F_CPU == 8000000
274 | " lx",
275 | #else
276 | " %",
277 | #endif
278 | " %",
279 | " mV",
280 | " kOhm",
281 | " kOhm",
282 | " mV",
283 | "",
284 | };
285 |
--------------------------------------------------------------------------------
/sck_beta_v0_9/SCKAmbient.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | SCKAmbient.h
4 | Supports the sensor reading and calibration functions.
5 |
6 | - Sensors supported (sensors use on board custom peripherials):
7 |
8 | - TEMP / HUM (DHT22 and HPP828E031)
9 | - NOISE
10 | - LIGHT (LDR and BH1730FVC)
11 | - CO (MICS5525 and MICS4514)
12 | - NO2 (MiCS2710 and MICS4514)
13 |
14 | */
15 |
16 |
17 | /*
18 |
19 | SENSOR Contants and Defaults
20 |
21 | */
22 |
23 | #ifndef __SCKAMBIENT_H__
24 | #define __SCKAMBIENT_H__
25 |
26 | #include
27 |
28 | #define TIME_BUFFER_SIZE 20
29 |
30 | class SCKAmbient {
31 | public:
32 | void begin();
33 | void ini();
34 | void execute(boolean instant);
35 | void writeGAIN(long value);
36 | float readGAIN();
37 | void GasSensor(boolean active);
38 | void getMICS();
39 | unsigned long getCO();
40 | unsigned long getNO2();
41 |
42 | void getSHT21();
43 | boolean getDHT22();
44 | #if F_CPU == 8000000
45 | uint32_t getTemperature();
46 | uint32_t getHumidity();
47 | #else
48 | int getTemperature();
49 | int getHumidity();
50 | #endif
51 |
52 | void readADXL(byte address, int num, byte buff[]);
53 | uint16_t getLight();
54 | unsigned int getNoise();
55 |
56 | void txDebug();
57 | boolean debug_state();
58 |
59 | void serialRequests();
60 | private:
61 | void writeVH(byte device, long voltage );
62 | float readVH(byte device);
63 | void writeRL(byte device, long resistor);
64 | float readRL(byte device);
65 | void writeRGAIN(byte device, long resistor);
66 | float readRGAIN(byte device);
67 | void getVcc();
68 | void heat(byte device, int current);
69 | float readRs(byte device);
70 | float readMICS(byte device);
71 | void writeADXL(byte address, byte val);
72 | void averageADXL();
73 | void updateSensors(byte mode);
74 | uint16_t readSHT21(uint8_t type);
75 | boolean DhtRead(uint8_t pin);
76 | int addData(byte inByte);
77 | boolean printNetWorks(unsigned int address_eeprom, boolean endLine);
78 | void addNetWork(unsigned int address_eeprom, char* text);
79 | };
80 | #endif
81 |
--------------------------------------------------------------------------------
/sck_beta_v0_9/SCKBase.cpp:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | SCKBase.cpp
4 | Supports core and data management functions (Power, WiFi, SD storage, RTClock and EEPROM storage)
5 |
6 | - Modules supported:
7 |
8 | - WIFI (Microchip RN131 (WiFly))
9 | - RTC (DS1339U and DS1307Z)
10 | - EEPROM (24LC256)
11 | - POWER MANAGEMENT IC's
12 |
13 | */
14 |
15 | #include "Constants.h"
16 | #include "SCKBase.h"
17 | #include
18 | #include
19 |
20 | #define debugBASE false
21 |
22 |
23 |
24 | void SCKBase::begin() {
25 | Wire.begin();
26 | TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
27 | Serial.begin(115200);
28 | Serial1.begin(9600);
29 | pinMode(IO0, OUTPUT); //VH_MICS5525
30 | pinMode(IO1, OUTPUT); //VH_MICS2710
31 | pinMode(IO2, OUTPUT); //MICS2710_HIGH_IMPEDANCE
32 | pinMode(AWAKE, OUTPUT);
33 | pinMode(MOSI, OUTPUT);
34 | pinMode(SCK, OUTPUT);
35 | pinMode(FACTORY, OUTPUT);
36 | pinMode(CONTROL, INPUT);
37 | digitalWrite(AWAKE, LOW);
38 | digitalWrite(FACTORY, LOW);
39 | }
40 |
41 | void SCKBase::config(){
42 | eepromCheck();
43 | timer1Initialize();
44 | }
45 |
46 | void SCKBase::eepromCheck() {
47 | //do a clearmemory only if needed
48 | digitalWrite(AWAKE, HIGH);
49 | boolean doClearMemory = false;
50 | char temp[17];
51 | strncpy(temp, MAC(), 18);
52 | while (compareData(temp, "-1")){
53 | #if debugBASE
54 | Serial.println(F("Can't get MAC from Wifly!!!"));
55 | #endif
56 | strncpy(temp, MAC(), 18);
57 | }
58 | if (!compareData(temp, readData(EE_ADDR_MAC, 0, INTERNAL))) doClearMemory = true;
59 | uint32_t intTemp;
60 | intTemp = readData(EE_ADDR_SENSOR_MODE, INTERNAL);
61 | if (intTemp < 0 || intTemp > 3) doClearMemory = true;
62 | intTemp = readData(EE_ADDR_TIME_UPDATE, INTERNAL);
63 | if (intTemp < MIN_TIME_UPDATE || intTemp > MAX_TIME_UPDATE) doClearMemory = true;
64 | intTemp = readData(EE_ADDR_NUMBER_UPDATES, INTERNAL);
65 | if (intTemp < DEFAULT_MIN_UPDATES || intTemp > POST_MAX) doClearMemory = true;
66 | if (doClearMemory) clearmemory();
67 |
68 | //if there are hardcoded networks write them without clearing memory
69 | //so the user can add more networks after hardcoded one's
70 | #if (networks > 0)
71 | intTemp = readData(EE_ADDR_NUMBER_NETS, INTERNAL);
72 | if (intTemp < networks || intTemp > 5) writeData(EE_ADDR_NUMBER_NETS, networks, INTERNAL);
73 | for (byte i=0; iRES) data=RES;
146 | Wire.beginTransmission(deviceaddress);
147 | address=(address<<4)|bitRead(data, 8) ;
148 | Wire.write(address);
149 | Wire.write(lowByte(data));
150 | Wire.endTransmission();
151 | delay(4);
152 | }
153 |
154 | int SCKBase::readMCP(int deviceaddress, uint16_t address ) {
155 | byte rdata = 0xFF;
156 | int data = 0x0000;
157 | Wire.beginTransmission(deviceaddress);
158 | address=(address<<4)|B00001100;
159 | Wire.write(address);
160 | Wire.endTransmission();
161 | Wire.requestFrom(deviceaddress,2);
162 | unsigned long time = millis();
163 | while (!Wire.available()) if ((millis() - time)>500) return 0x00;
164 | rdata = Wire.read();
165 | data=rdata<<8;
166 | while (!Wire.available());
167 | rdata = Wire.read();
168 | data=data|rdata;
169 | return data;
170 | }
171 |
172 | #if F_CPU == 8000000
173 | #define MCP3 0x2D // Direction of the mcp3 Ajust the battary charge
174 | float SCKBase::readCharge() {
175 | float resistor = kr*readMCP(MCP3, 0x00)/1000;
176 | float current = 1000./(2+((resistor * 10)/(resistor + 10)));
177 | #if debugBASE
178 | Serial.print("Resistor : ");
179 | Serial.print(resistor);
180 | Serial.print(" kOhm, ");
181 | Serial.print("Current : ");
182 | Serial.print(current);
183 | Serial.println(" mA");
184 | #endif
185 | return(current);
186 | }
187 |
188 | void SCKBase::writeCharge(int current) {
189 | if (current < 100) current = 100;
190 | else if (current > 500) current = 500;
191 | float Rp = (1000./current)-2;
192 | float resistor = Rp*10/(10-Rp);
193 | writeMCP(MCP3, 0x00, (uint8_t)(resistor*1000/kr));
194 | #if debugBASE
195 | Serial.print("Rc : ");
196 | Serial.print(Rp + 2);
197 | Serial.print(" kOhm, ");
198 | Serial.print("Rpot : ");
199 | Serial.print(resistor);
200 | Serial.print(" kOhm, ");
201 | Serial.print("Current : ");
202 | Serial.print(current);
203 | Serial.println(" mA");
204 | #endif
205 | }
206 | #endif
207 |
208 | void SCKBase::writeEEPROM(uint16_t eeaddress, uint8_t data) {
209 | uint8_t retry = 0;
210 | while ((readEEPROM(eeaddress)!=data)&&(retry<10))
211 | {
212 | Wire.beginTransmission(E2PROM);
213 | Wire.write((byte)(eeaddress >> 8)); // MSB
214 | Wire.write((byte)(eeaddress & 0xFF)); // LSB
215 | Wire.write(data);
216 | Wire.endTransmission();
217 | delay(6);
218 | retry++;
219 | }
220 | }
221 |
222 | byte SCKBase::readEEPROM(uint16_t eeaddress) {
223 | byte rdata = 0xFF;
224 | Wire.beginTransmission(E2PROM);
225 | Wire.write((byte)(eeaddress >> 8)); // MSB
226 | Wire.write((byte)(eeaddress & 0xFF)); // LSB
227 | Wire.endTransmission();
228 | Wire.requestFrom(E2PROM,1);
229 | while (!Wire.available());
230 | rdata = Wire.read();
231 | return rdata;
232 | }
233 |
234 | void SCKBase::writeData(uint32_t eeaddress, long data, uint8_t location)
235 | {
236 | for (int i =0; i<4; i++)
237 | {
238 | if (location == EXTERNAL) writeEEPROM(eeaddress + (3 -i) , data>>(i*8));
239 | else EEPROM.write(eeaddress + (3 -i), data>>(i*8));
240 | }
241 |
242 | }
243 |
244 | void SCKBase::writeData(uint32_t eeaddress, uint16_t pos, char* text, uint8_t location)
245 | {
246 | uint16_t eeaddressfree = eeaddress + buffer_length * pos;
247 | if (location == EXTERNAL)
248 | {
249 | for (uint16_t i = eeaddressfree; i< (eeaddressfree + buffer_length); i++) writeEEPROM(i, 0x00);
250 | for (uint16_t i = eeaddressfree; text[i - eeaddressfree]!= 0x00; i++) writeEEPROM(i, text[i - eeaddressfree]);
251 | }
252 | else
253 | {
254 |
255 | for (uint16_t i = eeaddressfree; i< (eeaddressfree + buffer_length); i++) EEPROM.write(i, 0x00);
256 | for (uint16_t i = eeaddressfree; text[i - eeaddressfree]!= 0x00; i++)
257 | {
258 | if (eeaddressfree>=DEFAULT_ADDR_SSID) if (text[i - eeaddressfree]==' ') text[i - eeaddressfree]='$';
259 | EEPROM.write(i, text[i - eeaddressfree]);
260 | }
261 | }
262 | }
263 |
264 | uint32_t SCKBase::readData(uint16_t eeaddress, uint8_t location)
265 | {
266 | uint32_t data = 0;
267 | for (int i =0; i<4; i++)
268 | {
269 | if (location == EXTERNAL) data = data + (uint32_t)((uint32_t)readEEPROM(eeaddress + i)<<((3-i)*8));
270 | else data = data + (uint32_t)((uint32_t)EEPROM.read(eeaddress + i)<<((3-i)*8));
271 | }
272 | return data;
273 | }
274 |
275 | char* SCKBase::readData(uint16_t eeaddress, uint16_t pos, uint8_t location)
276 | {
277 | eeaddress = eeaddress + buffer_length * pos;
278 | uint16_t i;
279 | if (location == EXTERNAL)
280 | {
281 | uint8_t temp = readEEPROM(eeaddress);
282 | for ( i = eeaddress; ((temp!= 0x00)&&(temp<0x7E)&&(temp>0x1F)&&((i - eeaddress)0x1F)&&((i - eeaddress)500) return false;
309 | Wire.read();
310 | return true;
311 | }
312 |
313 | boolean SCKBase::RTCadjust(char *time) {
314 | byte rtc[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
315 | byte count = 0x00;
316 | byte data_count=0;
317 | while (time[count]!=0x00)
318 | {
319 | if(time[count] == '-') data_count++;
320 | else if(time[count] == ' ') data_count++;
321 | else if(time[count] == ':') data_count++;
322 | else if ((time[count] >= '0')&&(time[count] <= '9'))
323 | {
324 | rtc[data_count] =(rtc[data_count]<<4)|(0x0F&time[count]);
325 | }
326 | else break;
327 | count++;
328 | }
329 | if (data_count == 5)
330 | {
331 | #if F_CPU == 8000000
332 | Wire.beginTransmission(RTC_ADDRESS);
333 | Wire.write((int)0);
334 | Wire.write(rtc[5]);
335 | Wire.write(rtc[4]);
336 | Wire.write(rtc[3]);
337 | Wire.write(0x00);
338 | Wire.write(rtc[2]);
339 | Wire.write(rtc[1]);
340 | Wire.write(rtc[0]);
341 | Wire.endTransmission();
342 | delay(4);
343 | Wire.beginTransmission(RTC_ADDRESS);
344 | Wire.write(0x0E); //Address
345 | Wire.write(0x00); //Value
346 | Wire.endTransmission();
347 | #else
348 | Wire.beginTransmission(RTC_ADDRESS);
349 | Wire.write((int)0);
350 | Wire.write(rtc[5]);
351 | Wire.write(rtc[4]);
352 | Wire.write(rtc[3]);
353 | Wire.write(0x00);
354 | Wire.write(rtc[2]);
355 | Wire.write(rtc[1]);
356 | Wire.write(rtc[0]);
357 | Wire.write((int)0);
358 | Wire.endTransmission();
359 | return true;
360 | #endif
361 | return true;
362 | }
363 | return false;
364 | }
365 |
366 | boolean SCKBase::RTCtime(char *time) {
367 | Wire.beginTransmission(RTC_ADDRESS);
368 | Wire.write((int)0);
369 | Wire.endTransmission();
370 | Wire.requestFrom(RTC_ADDRESS, 7);
371 | uint8_t seconds = (Wire.read() & 0x7F);
372 | uint8_t minutes = Wire.read();
373 | uint8_t hours = Wire.read();
374 | Wire.read();
375 | uint8_t day = Wire.read();
376 | uint8_t month = Wire.read();
377 | uint8_t year = Wire.read();
378 | time[0] = '2';
379 | time[1] = '0';
380 | time[2] = (year>>4) + '0';
381 | time[3] = (year&0x0F) + '0';
382 | time[4] = '-';
383 | time[5] = (month>>4) + '0';
384 | time[6] = (month&0x0F) + '0';
385 | time[7] = '-';
386 | time[8] = (day>>4) + '0';
387 | time[9] = (day&0x0F) + '0';
388 | time[10] = ' ';
389 | time[11] = (hours>>4) + '0';
390 | time[12] = (hours&0x0F) + '0';
391 | time[13] = ':';
392 | time[14] = (minutes>>4) + '0';
393 | time[15] = (minutes&0x0F) + '0';
394 | time[16] = ':';
395 | time[17] = (seconds>>4) + '0';
396 | time[18] = (seconds&0x0F) + '0';
397 | time[19] = 0x00;
398 | return true;
399 | }
400 |
401 | boolean SCKBase::RTCisValid(char *time) {
402 | RTCtime(time);
403 | //If year is 2016 we consider rtc data to ba a valid date (without update RTC starts in year 2000)
404 | if (time[0] == '2' && time[1] == '0' && time[2] == '1' && time[3] == '6') return true;
405 | return false;
406 | }
407 |
408 | uint16_t SCKBase::getPanel(float Vref){
409 | #if F_CPU == 8000000
410 | uint16_t value = 11*average(PANEL)*Vref/1023.;
411 | if (value > 500) value = value + 120; //Voltage protection diode
412 | else value = 0;
413 | #else
414 | uint16_t value = 3*average(PANEL)*Vref/1023.;
415 | if (value > 500) value = value + 750; //Voltage protection diode
416 | else value = 0;
417 | #endif
418 | #if debugBASE
419 | Serial.print("Panel = ");
420 | Serial.print(value);
421 | Serial.println(" mV");
422 | #endif
423 | return value;
424 | }
425 |
426 | const uint16_t batTable[] = {
427 | 3078,
428 | 3364,
429 | 3468,
430 | 3540,
431 | 3600,
432 | 3641,
433 | 3682,
434 | 3701,
435 | 3710,
436 | 3716,
437 | 3716,
438 | 3716,
439 | 3720,
440 | 3714,
441 | 3720,
442 | 3725,
443 | 3732,
444 | 3742,
445 | 3739,
446 | 3744,
447 | 3744,
448 | 3754,
449 | 3760,
450 | 3762,
451 | 3770,
452 | 3768,
453 | 3774,
454 | 3774,
455 | 3774,
456 | 3779,
457 | 3784,
458 | 3790,
459 | 3788,
460 | 3794,
461 | 3798,
462 | 3798,
463 | 3804,
464 | 3809,
465 | 3809,
466 | 3812,
467 | 3817,
468 | 3817,
469 | 3822,
470 | 3823,
471 | 3828,
472 | 3828,
473 | 3828,
474 | 3833,
475 | 3838,
476 | 3838,
477 | 3842,
478 | 3847,
479 | 3852,
480 | 3859,
481 | 3858,
482 | 3864,
483 | 3862,
484 | 3869,
485 | 3877,
486 | 3877,
487 | 3883,
488 | 3888,
489 | 3894,
490 | 3898,
491 | 3902,
492 | 3906,
493 | 3912,
494 | 3923,
495 | 3926,
496 | 3936,
497 | 3942,
498 | 3946,
499 | 3960,
500 | 3972,
501 | 3979,
502 | 3982,
503 | 3991,
504 | 3997,
505 | 4002,
506 | 4002,
507 | 4012,
508 | 4018,
509 | 4028,
510 | 4043,
511 | 4057,
512 | 4074,
513 | 4084,
514 | 4094,
515 | 4098,
516 | 4098,
517 | 4109,
518 | 4115,
519 | 4123,
520 | 4134,
521 | 4142,
522 | 4153,
523 | 4158,
524 | 4170,
525 | 4180,
526 | 4188
527 | };
528 |
529 | uint16_t SCKBase::getBattery(float Vref) {
530 | uint16_t temp = average(BAT);
531 | #if F_CPU == 8000000
532 | float voltage = Vref*temp/1023.;
533 | voltage = voltage + (voltage/180)*100;
534 | #else
535 | float voltage = Vref*temp/1023.;
536 | #endif
537 | uint16_t percent = 1000;
538 | for(uint16_t i = 0; i < 100; i++) {
539 | if(voltage < batTable[i]) {
540 | percent = i * 10;
541 | break;
542 | }
543 | }
544 | if(percent < 10) percent = 10;
545 | #if debugBASE
546 | Serial.print("Vbat: ");
547 | Serial.print(voltage);
548 | Serial.print(" mV, ");
549 | Serial.print("Battery level: ");
550 | Serial.print(percent/10);
551 | Serial.println(" %");
552 | #endif
553 | return percent;
554 | }
555 |
556 | boolean SCKBase::findInResponse(const char *toMatch,
557 | unsigned int timeOut = 1000) {
558 | int byteRead;
559 |
560 | unsigned long timeOutTarget; // in milliseconds
561 |
562 | for (unsigned int offset = 0; offset < strlen(toMatch); offset++) {
563 | timeOutTarget = millis() + timeOut; // Doesn't handle timer wrapping
564 | while (!Serial1.available()) {
565 | // Wait, with optional time out.
566 | if (timeOut > 0) {
567 | if (millis() > timeOutTarget) {
568 | return false;
569 | }
570 | }
571 | delay(1); // This seems to improve reliability slightly
572 | }
573 | byteRead = Serial1.read();
574 | //Serial.print((char)byteRead);
575 | delay(1); // Removing logging may affect timing slightly
576 |
577 | if (byteRead != toMatch[offset]) {
578 | offset = 0;
579 | // Ignore character read if it's not a match for the start of the string
580 | if (byteRead != toMatch[offset]) {
581 | offset = -1;
582 | }
583 | continue;
584 | }
585 | }
586 |
587 | return true;
588 | }
589 |
590 | void SCKBase::skipRemainderOfResponse(unsigned int timeOut) {
591 | unsigned long time = millis();
592 | while (((millis()-time) // Specify the channel to create network
737 | sendCommand(F("set wlan ssid "), true); // Set up network broadcast SSID
738 | sendCommand(ssid);
739 |
740 | buffer[6] = 0x00;
741 | sendCommand(F("set opt device_id "), true); // Set up network broadcast SSID
742 | sendCommand(ssid);
743 |
744 | sendCommand(F("set ip dhcp 4")); // Enable DHCP server
745 | sendCommand(F("set ip address 1.2.3.4")); // Specify the IP address
746 | sendCommand(F("set ip net 255.255.255.0")); // Specify the subnet mask
747 | sendCommand(F("set ip gateway 1.2.3.4")); // Specify the gateway
748 | sendCommand(F("save"), false, "Storing in config"); // Store settings
749 | sendCommand(F("reboot"), false, "*READY*"); // Reboot the module in AP mode
750 | }
751 | }
752 |
753 | boolean SCKBase::ready()
754 | {
755 | if(!enterCommandMode())
756 | {
757 | repair();
758 | return(false);
759 | }
760 | else
761 | {
762 | Serial1.println(F("join"));
763 | if (findInResponse("Associated!", 8000))
764 | {
765 | skipRemainderOfResponse(3000);
766 | exitCommandMode();
767 | return(true);
768 | }
769 | }
770 |
771 | }
772 |
773 | boolean connected = false;
774 |
775 | boolean SCKBase::open(const char *addr, int port) {
776 |
777 | if (connected) {
778 | close();
779 | }
780 | if (enterCommandMode())
781 | {
782 | sendCommand(F("open "), true);
783 | sendCommand(addr, true);
784 | Serial1.print(F(" "));
785 | Serial1.print(port);
786 | if (sendCommand("", false, "*OPEN*"))
787 | {
788 | connected = true;
789 | return true;
790 | }
791 | else return false;
792 | }
793 | enterCommandMode();
794 | return false;
795 | }
796 |
797 | boolean SCKBase::close() {
798 | if (!connected) {
799 | return true;
800 | }
801 | if (sendCommand(F("close"), false, "*CLOS*")) {
802 | connected = false;
803 | return true;
804 | }
805 | connected = false;
806 | return false;
807 | }
808 |
809 | #define MAC_ADDRESS_BUFFER_SIZE 18 // "FF:FF:FF:FF:FF:FF\0"
810 |
811 | char* SCKBase::MAC() {
812 | if (enterCommandMode())
813 | {
814 | if (sendCommand(F("get mac"), false, "Mac Addr="))
815 | {
816 | char newChar;
817 | byte offset = 0;
818 |
819 | while (offset < MAC_ADDRESS_BUFFER_SIZE) {
820 | if (Serial1.available())
821 | {
822 | newChar = Serial1.read();
823 | if ((newChar == '\n')||(newChar < '0')) {
824 | buffer[offset] = '\x00';
825 | return buffer;
826 | }
827 | else if (newChar != -1) {
828 | buffer[offset] = newChar;
829 | offset++;
830 | }
831 | }
832 | }
833 | buffer[MAC_ADDRESS_BUFFER_SIZE-1] = '\x00';
834 | exitCommandMode();
835 | }
836 | }
837 | return "-1";
838 | }
839 |
840 | char* SCKBase::id() {
841 | char* temp = MAC();
842 | byte len = strlen(temp);
843 | byte j = 4;
844 | buffer[0] = 'S';
845 | buffer[1] = 'C';
846 | buffer[2] = 'K';
847 | buffer[3] = '_';
848 | for(byte i=12; i 0)
894 | {
895 | if (ver < WIFLY_LATEST_VERSION)
896 | {
897 | byte state = 1;
898 | if(update()); //Wifly Updated.
899 | else state = 2; //Update Fail.
900 | reset();
901 | return state;
902 | }
903 | else return 0; //WiFly up to date.
904 | }
905 | else return -1; //Error reading the wifi version.
906 | }
907 |
908 | int SCKBase::getWiFlyVersion() {
909 | if (enterCommandMode())
910 | {
911 | if (sendCommand(F("ver"), false, "wifly-GSX Ver"))
912 | {
913 | char newChar;
914 | byte offset = 0;
915 | boolean prevWasNumber = false;
916 | while (offset < 3) {
917 | if (Serial1.available())
918 | {
919 | newChar = Serial1.read();
920 | if ((newChar != -1 && isdigit(newChar)) || newChar == '.') {
921 | if (newChar != '.') {
922 | buffer[offset] = newChar;
923 | offset++;
924 | }
925 | prevWasNumber = true;
926 | }
927 | else {
928 | if (prevWasNumber){
929 | break;
930 | }
931 | prevWasNumber = false;
932 | }
933 | }
934 | }
935 | exitCommandMode();
936 | buffer[offset] = 0x00;
937 | return atoi(buffer);
938 | }
939 | return 0;
940 | }
941 | return 0;
942 | }
943 |
944 |
945 | boolean SCKBase::update() {
946 | if (enterCommandMode())
947 | {
948 | sendCommand(F(DEFAULT_WIFLY_FIRMWARE));
949 | delay(1000);
950 | if (findInResponse("FTP OK.", 60000))
951 | {
952 | return true;
953 | }
954 | }
955 | else return false;
956 | }
957 |
958 | uint32_t baud[7]={
959 | 2400, 4800, 9600, 19200, 38400, 57600, 115200};
960 |
961 | void SCKBase::repair()
962 | {
963 | if(!enterCommandMode())
964 | {
965 | boolean repair = true;
966 | for (int i=6; ((i>=0)&&repair); i--)
967 | {
968 | Serial1.begin(baud[i]);
969 | if(enterCommandMode())
970 | {
971 | reset();
972 | repair = false;
973 | }
974 | Serial1.begin(9600);
975 | }
976 | }
977 | }
978 |
979 | /*TIMER*/
980 |
981 | #define RESOLUTION 65536 // Timer1 is 16 bit
982 | unsigned int pwmPeriod;
983 | unsigned char clockSelectBits;
984 | char oldSREG; // To hold Status
985 |
986 | void SCKBase::timer1SetPeriod(long microseconds) // AR modified for atomic access
987 | {
988 |
989 | long cycles = (F_CPU / 2000000) * microseconds; // the counter runs backwards after TOP, interrupt is at BOTTOM so divide microseconds by 2
990 | if(cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no prescale, full xtal
991 | else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11); // prescale by /8
992 | else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11) | _BV(CS10); // prescale by /64
993 | else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12); // prescale by /256
994 | else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12) | _BV(CS10); // prescale by /1024
995 | else cycles = RESOLUTION - 1, clockSelectBits = _BV(CS12) | _BV(CS10); // request was out of bounds, set as maximum
996 |
997 | oldSREG = SREG;
998 | cli(); // Disable interrupts for 16 bit register access
999 | ICR1 = pwmPeriod = cycles; // ICR1 is TOP in p & f correct pwm mode
1000 | SREG = oldSREG;
1001 |
1002 | TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));
1003 | TCCR1B |= clockSelectBits; // reset clock select register, and starts the clock
1004 | }
1005 |
1006 | void SCKBase::timer1Initialize()
1007 | {
1008 | TCCR1A = 0; // clear control register A
1009 | TCCR1B = _BV(WGM13); // set mode 8: phase and frequency correct pwm, stop the timer
1010 | timer1SetPeriod(1500);
1011 | TIMSK1 = _BV(TOIE1);
1012 | }
1013 |
1014 | void SCKBase::timer1Stop()
1015 | {
1016 | TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); // clears all clock selects bits
1017 | TIMSK1 &= ~(_BV(TOIE1));
1018 |
1019 | }
1020 |
1021 |
1022 |
1023 |
1024 |
1025 |
1026 |
1027 |
1028 |
1029 |
1030 |
1031 |
1032 |
--------------------------------------------------------------------------------
/sck_beta_v0_9/SCKBase.h:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | SCKBase.h
4 | Supports core and data management functions (Power, WiFi, SD storage, RTClock and EEPROM storage)
5 |
6 | - Modules supported:
7 |
8 | - WIFI (Microchip RN131 (WiFly))
9 | - RTC (DS1339U and DS1307Z)
10 | - EEPROM (24LC256)
11 | - POWER MANAGEMENT IC's
12 |
13 | */
14 |
15 | #ifndef __SCKBASE_H__
16 | #define __SCKBASE_H__
17 |
18 | #include
19 |
20 | class SCKBase {
21 | public:
22 | void begin();
23 | void config();
24 | void eepromCheck();
25 | void clearmemory();
26 | float average(int anaPin);
27 | boolean checkText(char* text, char* text1);
28 | boolean compareData(char* text, char* text1);
29 | void writeMCP(byte deviceaddress, byte address, int data );
30 | int readMCP(int deviceaddress, uint16_t address );
31 | float readCharge();
32 | void writeCharge(int current);
33 | void writeEEPROM(uint16_t eeaddress, uint8_t data);
34 | byte readEEPROM(uint16_t eeaddress);
35 | void writeData(uint32_t eeaddress, long data, uint8_t location);
36 | void writeData(uint32_t eeaddress, uint16_t pos, char* text, uint8_t location);
37 | char* readData(uint16_t eeaddress, uint16_t pos, uint8_t location);
38 | uint32_t readData(uint16_t eeaddress, uint8_t location);
39 |
40 | uint16_t getPanel(float Vref);
41 | uint16_t getBattery(float Vref);
42 |
43 | /*RTC commands*/
44 | boolean checkRTC();
45 | boolean RTCadjust(char *time);
46 | boolean RTCtime(char *time);
47 | boolean RTCisValid(char *time);
48 |
49 | /*Wifi commands*/
50 | boolean findInResponse(const char *toMatch,
51 | unsigned int timeOut);
52 | void skipRemainderOfResponse(unsigned int timeOut);
53 | boolean sendCommand(const __FlashStringHelper *command,
54 | boolean isMultipartCommand,
55 | const char *expectedResponse);
56 | boolean sendCommand(const char *command,
57 | boolean isMultipartCommand,
58 | const char *expectedResponse);
59 | boolean enterCommandMode();
60 | boolean sleep();
61 | boolean reset();
62 | boolean exitCommandMode();
63 | boolean connect();
64 | void APmode(char* ssid);
65 | boolean ready();
66 | boolean open(const char *addr, int port);
67 | boolean close();
68 | char* MAC();
69 | char* id();
70 | uint32_t scan();
71 | int checkWiFly();
72 | int getWiFlyVersion();
73 | boolean update();
74 | void repair();
75 |
76 | /*Timer commands*/
77 | void timer1SetPeriod(long microseconds);
78 | void timer1Initialize();
79 | void timer1Stop();
80 | private:
81 |
82 | };
83 | #endif
84 |
--------------------------------------------------------------------------------
/sck_beta_v0_9/SCKServer.cpp:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | SCKServer.cpp
4 |
5 | */
6 |
7 |
8 | #include "Constants.h"
9 | #include "SCKServer.h"
10 | #include "SCKBase.h"
11 | #include "SCKAmbient.h"
12 | #include
13 | #include
14 |
15 | #define debugServer false
16 |
17 | SCKBase base__;
18 | SCKServer server__;
19 | SCKAmbient ambient__;
20 |
21 | #define TIME_BUFFER_SIZE 20
22 |
23 | boolean SCKServer::time(char *time_) {
24 | boolean ok=false;
25 | uint8_t count = 0;
26 | byte retry=0;
27 | while ((retry<5)&&(!ok))
28 | {
29 | retry++;
30 | if (base__.enterCommandMode())
31 | {
32 | if (base__.open(WEB[0], 80))
33 | {
34 | for(byte i = 0; i<3; i++) Serial1.print(WEBTIME[i]); //Requests to the server time
35 | if (base__.findInResponse("UTC:", 2000))
36 | {
37 | char newChar;
38 | byte offset = 0;
39 | unsigned long time = millis();
40 | while (offset < TIME_BUFFER_SIZE) {
41 | if (Serial1.available())
42 | {
43 | newChar = Serial1.read();
44 | time = millis();
45 | if (newChar == '#') {
46 | ok = true;
47 | time_[offset] = '\x00';
48 | break;
49 | }
50 | else if (newChar != -1) {
51 | if (newChar==',')
52 | {
53 | if (count<2) time_[offset]='-';
54 | else if (count>2) time_[offset]=':';
55 | else time_[offset]=' ';
56 | count++;
57 | }
58 | else time_[offset] = newChar;
59 | offset++;
60 | }
61 | }
62 | else if((millis()-time)>1000)
63 | {
64 | ok = false;
65 | break;
66 | }
67 | }
68 | }
69 | else {
70 | #if debugServer
71 | Serial.println("FAIL:(");
72 | #endif
73 | }
74 | base__.close();
75 | }
76 | }
77 | }
78 | if (!ok)
79 | {
80 | time_[0] = '#';
81 | time_[1] = 0x00;
82 | }
83 | base__.exitCommandMode();
84 | return ok;
85 | }
86 |
87 | boolean SCKServer::RTCupdate(char *time_){
88 | byte retry = 0;
89 | if (base__.checkRTC()){
90 | if (time(time_)) {
91 | while (retry<5) {
92 | retry++;
93 | if(base__.RTCadjust(time_)) {
94 | return true;
95 | }
96 | }
97 | }
98 | }
99 | return false;
100 | }
101 |
102 | void SCKServer::json_update(uint16_t updates, long *value, char *time, boolean isMultipart)
103 | {
104 | #if debugServer
105 | Serial.print(F("["));
106 | #endif
107 | Serial1.print(F("["));
108 | for (int i = 0; i< updates;i++)
109 | {
110 | readFIFO();
111 | if ((i< (updates - 1)) || (isMultipart))
112 | {
113 | Serial1.print(F(","));
114 | #if debugServer
115 | Serial.print(F(","));
116 | #endif
117 | }
118 | }
119 |
120 | if (isMultipart)
121 | {
122 | byte i;
123 | for (i = 0; i<9; i++)
124 | {
125 | Serial1.print(SERVER[i]);
126 | Serial1.print(value[i]);
127 | }
128 | Serial1.print(SERVER[i]);
129 | Serial1.print(time);
130 | Serial1.print(SERVER[i+1]);
131 | Serial1.println(F("]"));
132 | Serial1.println();
133 |
134 | #if debugServer
135 | for (i = 0; i<9; i++)
136 | {
137 | Serial.print(SERVER[i]);
138 | Serial.print(value[i]);
139 | }
140 | Serial.print(SERVER[i]);
141 | Serial.print(time);
142 | Serial.print(SERVER[i+1]);
143 | #endif
144 | }
145 | Serial1.println(F("]"));
146 | Serial1.println();
147 | #if debugServer
148 | Serial.println(F("]"));
149 | #endif
150 | }
151 |
152 | void SCKServer::addFIFO(long *value, char *time)
153 | {
154 | uint16_t updates = (base__.readData(EE_ADDR_NUMBER_WRITE_MEASURE, INTERNAL)-base__.readData(EE_ADDR_NUMBER_READ_MEASURE, INTERNAL))/((SENSORS)*4 + TIME_BUFFER_SIZE);
155 | if (updates < MAX_MEMORY)
156 | {
157 | int eeaddress = base__.readData(EE_ADDR_NUMBER_WRITE_MEASURE, INTERNAL);
158 | int i = 0;
159 | for (i = 0; i<9; i++)
160 | {
161 | base__.writeData(eeaddress + i*4, value[i], EXTERNAL);
162 | }
163 | base__.writeData(eeaddress + i*4, 0, time, EXTERNAL);
164 | eeaddress = eeaddress + (SENSORS)*4 + TIME_BUFFER_SIZE;
165 | base__.writeData(EE_ADDR_NUMBER_WRITE_MEASURE, eeaddress, INTERNAL);
166 | }
167 | else
168 | {
169 | #if debugEnabled
170 | if (!ambient__.debug_state()) Serial.println(F("Memory limit exceeded!!"));
171 | #endif
172 | }
173 | }
174 |
175 | void SCKServer::readFIFO()
176 | {
177 | int i = 0;
178 | int eeaddress = base__.readData(EE_ADDR_NUMBER_READ_MEASURE, INTERNAL);
179 | for (i = 0; i<9; i++)
180 | {
181 | Serial1.print(SERVER[i]);
182 | Serial1.print(base__.readData(eeaddress + i*4, EXTERNAL)); //SENSORS
183 | }
184 | Serial1.print(SERVER[i]);
185 | Serial1.print(base__.readData(eeaddress + i*4, 0, EXTERNAL)); //TIME
186 | Serial1.print(SERVER[i+1]);
187 |
188 | #if debugServer
189 | for (i = 0; i<9; i++)
190 | {
191 | Serial.print(SERVER[i]);
192 | Serial.print(base__.readData(eeaddress + i*4, EXTERNAL)); //SENSORS
193 | }
194 | Serial.print(SERVER[i]);
195 | Serial.print(base__.readData(eeaddress + i*4, 0, EXTERNAL)); //TIME
196 | Serial.print(SERVER[i+1]);
197 | #endif
198 |
199 | eeaddress = eeaddress + (SENSORS)*4 + TIME_BUFFER_SIZE;
200 | if (eeaddress == base__.readData(EE_ADDR_NUMBER_WRITE_MEASURE, INTERNAL))
201 | {
202 | base__.writeData(EE_ADDR_NUMBER_WRITE_MEASURE, 0, INTERNAL);
203 | base__.writeData(EE_ADDR_NUMBER_READ_MEASURE, 0, INTERNAL);
204 | }
205 | else base__.writeData(EE_ADDR_NUMBER_READ_MEASURE, eeaddress, INTERNAL);
206 | }
207 |
208 | #define numbers_retry 5
209 |
210 | boolean SCKServer::update(long *value, char *time_)
211 | {
212 | value[8] = base__.scan(); //Wifi Nets
213 | byte retry = 0;
214 | if (time(time_)) //Update server time
215 | {
216 | if (base__.checkRTC())
217 | {
218 | while (!base__.RTCadjust(time_)&&(retry= numbers_retry) return false;
245 | }
246 | }
247 | for (byte i = 1; i<5; i++) Serial1.print(WEB[i]);
248 | Serial1.println(base__.readData(EE_ADDR_MAC, 0, INTERNAL)); //MAC ADDRESS
249 | Serial1.print(WEB[5]);
250 | Serial1.println(base__.readData(EE_ADDR_APIKEY, 0, INTERNAL)); //Apikey
251 | Serial1.print(WEB[6]);
252 | Serial1.println(FirmWare); //Firmware version
253 | Serial1.print(WEB[7]);
254 | return true;
255 | }
256 |
257 |
258 | void SCKServer::send(boolean sleep, boolean *wait_moment, long *value, char *time, boolean instant) {
259 | *wait_moment = true;
260 | if (base__.checkRTC()) base__.RTCtime(time);
261 | char tmpTime[19];
262 | strncpy(tmpTime, time, 20);
263 | uint16_t updates = (base__.readData(EE_ADDR_NUMBER_WRITE_MEASURE, INTERNAL)-base__.readData(EE_ADDR_NUMBER_READ_MEASURE, INTERNAL))/((SENSORS)*4 + TIME_BUFFER_SIZE);
264 | uint16_t NumUpdates = base__.readData(EE_ADDR_NUMBER_UPDATES, INTERNAL); // Number of readings before batch update
265 | if (updates>=(NumUpdates - 1) || instant)
266 | {
267 | if (sleep)
268 | {
269 | #if debugEnabled
270 | if (!ambient__.debug_state()) Serial.println(F("SCK Waking up..."));
271 | #endif
272 | digitalWrite(AWAKE, HIGH);
273 | }
274 | if (base__.connect()) //Wifi connect
275 | {
276 | #if debugEnabled
277 | if (!ambient__.debug_state()) Serial.println(F("SCK Connected to Wi-Fi!!"));
278 | #endif
279 | if (update(value, time)) //Update time and nets
280 | {
281 | #if debugEnabled
282 | if (!ambient__.debug_state())
283 | {
284 | Serial.print(F("updates = "));
285 | Serial.println(updates + 1);
286 | }
287 | #endif
288 | int num_post = updates;
289 | int cycles = cycles = updates/POST_MAX;;
290 | if (updates > POST_MAX)
291 | {
292 | for (int i=0; i
12 |
13 | class SCKServer {
14 | public:
15 | boolean time(char *time);
16 | void json_update(uint16_t updates, long *value, char *time, boolean isMultipart);
17 | void send(boolean sleep, boolean *wait_moment, long *value, char *time, boolean instant);
18 | boolean update(long *value, char *time_);
19 | boolean connect();
20 | void addFIFO(long *value, char *time);
21 | void readFIFO();
22 | boolean RTCupdate(char *time);
23 | private:
24 |
25 | };
26 | #endif
27 |
--------------------------------------------------------------------------------
/sck_beta_v0_9/TemperatureDecoupler.h:
--------------------------------------------------------------------------------
1 | /*
2 | TemperatureDecoupler.h
3 | SmartCitizen
4 |
5 | Created by Oriol Ferrer Mesià on 03/06/13.
6 | */
7 |
8 | #ifndef SmartCitizen_TemperatureDecoupler_h
9 | #define SmartCitizen_TemperatureDecoupler_h
10 |
11 | #define BATTERY_HEATUP_MAX 11
12 | #define BATTERY_CHARGE_THRESHOLD 980
13 | #include
14 | #include "AccumulatorFilter.h"
15 |
16 |
17 | class TemperatureDecoupler{
18 |
19 | public:
20 |
21 | void setup(){
22 | _prevBattery = 0;
23 | filter.setup(0.3);
24 | }
25 |
26 | void update( uint16_t battery ){
27 |
28 | //Serial.println( "# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #" );
29 |
30 | bool charging = false;
31 | bool doNothing = false;
32 | if (battery == _prevBattery){
33 | //doNothing;
34 | if ( battery > BATTERY_CHARGE_THRESHOLD ){
35 | charging = true;
36 | //Serial.println( "Battery same val > 980! charging!");
37 | }else{
38 | charging = false;
39 | //Serial.println( "Battery same val < 980! NOT charging!");
40 | }
41 | }else{
42 | if ( battery > _prevBattery || battery > BATTERY_CHARGE_THRESHOLD ){ //battery is charging!
43 | //Serial.println( "Battery charging!");
44 | charging = true;
45 | }else{ //battery is being drained
46 | //Serial.println( "Battery dis-charging!");
47 | charging = false;
48 | }
49 | }
50 |
51 | if (!doNothing){
52 | if(charging)
53 | filter.goUp();
54 | else
55 | filter.goDown();
56 | }
57 |
58 | //Serial.print(F("battery: ")); Serial.println( battery );
59 | //Serial.print(F("_prevBattery: ")); Serial.println( _prevBattery );
60 | //Serial.print(F("filter: ")); Serial.println( filter.getVal() );
61 |
62 | //Serial.println( "# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #" );
63 | //store last bat reading for future comparing
64 | _prevBattery = battery;
65 | lastChargingState = charging;
66 | }
67 |
68 | short int getCompensation(){
69 | return (short int) (filter.getVal() * BATTERY_HEATUP_MAX);
70 | }
71 |
72 | short int _prevBattery;
73 | AccumulatorFilter filter;
74 | bool lastChargingState; //true == up, false == down
75 |
76 | };
77 |
78 |
79 | #endif
80 |
--------------------------------------------------------------------------------
/sck_beta_v0_9/sck_beta_v0_9.ino:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | Smart Citizen Kit
4 | Ambient Board Beta Firmware v. 0.9.4
5 |
6 | http://smartcitizen.me/
7 |
8 |
9 | Compatible:
10 |
11 | Smart Citizen Kit v.1.0 (Goteo) (ATMEGA32U4 @ 16Mhz - Arduino Leonardo profile)
12 | Smart Citizen Kit v.1.1 (Kickstarter) (ATMEGA32U4 @ 8Mhz - Lylipad Arduino USB)
13 |
14 | Structure:
15 |
16 | sck_beta_v0_9.ino - Core Runtime.
17 |
18 | SCKAmbient.h - Supports the sensor reading and calibration functions.
19 | SCKBase.h - Supports the data management functions (WiFi, RTClock and EEPROM storage)
20 | SCKServer.h - Supports data publishing to the SmartCitizen Platform over WiFi.
21 |
22 | Constants.h - Defines pins configuration and other static parameters.
23 | AccumulatorFilter.h - Used for battery temperature decoupling in Smart Citizen Kit v.1.0
24 | TemperatureDecoupler.h - Used for battery temperature decoupling in Smart Citizen Kit v.1.0
25 |
26 | Check REAMDE.md for more information.
27 |
28 | */
29 |
30 | #include
31 | #include
32 | #include "SCKAmbient.h"
33 |
34 | SCKAmbient ambient;
35 |
36 | void setup() {
37 | ambient.begin();
38 | ambient.ini();
39 | ambient.execute(true);
40 | }
41 |
42 | void loop() {
43 | ambient.execute(false);
44 | }
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/utilities/README.md:
--------------------------------------------------------------------------------
1 | Utilities
2 | =================
3 |
4 | #### This are firmwares to perform repair and update tasks on the Smart Citizen Kit WiFi Module.
5 |
6 | ##### WiFly - Microchip RN131 Wi-Fi Module
7 |
8 | * Most of this functionailities are included directly on the core firmware.
9 | * The aim of the utilities is to perform advanced tasks for repairing damaged WiFly modules.
10 |
11 | Documentation in process. Visit the [forum](http://forum.smartcitizen.me) for more information.
12 |
--------------------------------------------------------------------------------
/utilities/SCK_check/SCK_check.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "SCKlibs.h"
4 |
5 | sck sck;
6 | void setup() {
7 | sck.begin();
8 | delay(5000);
9 | Serial.println("Trying to connect.");
10 | if (!sck.repair()) sck.recovery();
11 | else Serial.println("Device detected.");
12 | Serial.print("Firmware version: ");
13 | char *Version = sck.getWiFlyVersion(1000);
14 | Serial.println(Version);
15 | int state = sck.checkWiFlyVersion(Version);
16 | if (state==1) Serial.println("Wifi device is ok :)");
17 | else if (state==-1) Serial.println("Wifi device is corrupted :(");
18 | else if ((state)==0) if (!sck.webAppRepair())Serial.println("Wifi device is corrupted :(");
19 | Serial.println(F("Want to test the EEPROM? (y/n)"));
20 | while (!Serial.available());
21 | byte inByte = Serial.read();
22 | if (inByte =='y')
23 | {
24 | if (sck.checkEEPROM()) Serial.println("EEPROM is OK");
25 | else Serial.println("EEPROM fail :(");
26 | }
27 | else if (inByte !='n') Serial.println("Request invalid.");
28 | if (sck.checkRTC()) Serial.println("RTC is OK");
29 | else Serial.println("RTC fail, RTC battery check");
30 | Serial.print("Panel: "); Serial.print(sck.getPanel()); Serial.println("mV");
31 | Serial.print("Battery: "); Serial.print(sck.getBattery()); Serial.println("%");
32 | Serial.print("Speed charge: "); Serial.print(sck.readCharge()); Serial.println("mA");
33 | }
34 |
35 | void loop() {
36 | if (Serial.available())
37 | {
38 | int inByte = Serial.read();
39 | Serial1.write(inByte);
40 | }
41 | if (Serial1.available()) {
42 | int inByte = Serial1.read();
43 | Serial.write(inByte);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/utilities/SCK_check/SCKlibs.cpp:
--------------------------------------------------------------------------------
1 | #include "SCKlibs.h"
2 | #include
3 | #include
4 |
5 |
6 | #define WIFLY_LATEST_VERSION 441
7 | #define DEFAULT_WIFLY_FIRMWARE "ftp update wifly3-441.img"
8 | #define DEFAULT_WIFLY_FTP_UPDATE "set ftp address 198.175.253.161"
9 |
10 | #define AWAKE 4 //Despertar WIFI
11 | #define PANEL A8 //Entrada panel
12 | #define BAT A7 //Entrada bateria
13 |
14 | #define IO0 5 //MICS5525_HEATHER
15 | #define IO1 13 //MICS2710_HEATHER
16 | #define IO2 9 //MICS2710_ALTAIMPEDANCIA
17 | #define IO3 10 //MICS2710_ALTAIMPEDANCIA
18 | #define FACTORY 7 //factory RESET/AP RN131
19 | #define CONTROL 12 //Control Mode
20 |
21 | #define S0 A4 //MICS_5525
22 | #define S1 A5 //MICS_2710
23 | #define S2 A2 //SENS_5525
24 | #define S3 A3 //SENS_2710
25 | #define S4 A0 //MICRO
26 | #define S5 A1 //LDR
27 |
28 | #define OPEN "0"
29 | #define WEP "1"
30 | #define WPA1 "2"
31 | #define WPA2 "4"
32 | #define WEP64 "8"
33 |
34 | #define INT_ANT "0" //EXT_ANT
35 | #define EXT_ANT "1" //EXT_ANT
36 |
37 | char* mySSID = "Red";
38 | char* myPassword = "Pass";
39 | char* wifiEncript = WPA2;
40 | char* antenna = INT_ANT; //EXT_ANT
41 |
42 | #define buffer_length 32
43 | static char buffer[buffer_length];
44 |
45 | boolean sck::checkEEPROM() {
46 | boolean ok = true;
47 | for (int i=0; i<32000; i++)
48 | {
49 | writeEEPROM(i, 'x');
50 | Serial.print(".");
51 | if ((i%100) == 0)
52 | {
53 | Serial.println();
54 | Serial.print(i/100);
55 | }
56 | if (readEEPROM(i)!= 'x')
57 | {
58 | ok = false;
59 | break;
60 | }
61 | }
62 | Serial.println();
63 | return ok;
64 | }
65 | #define TWI_FREQ 400000L //Frecuencia bus I2C
66 |
67 | void sck::begin() {
68 | Serial.begin(9600);
69 | Serial1.begin(9600);
70 | Wire.begin();
71 | TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
72 | if (EEPROM.read(0)>=2) EEPROM.write(0, 0);
73 | pinMode(IO0, OUTPUT); //VH_MICS5525
74 | pinMode(IO1, OUTPUT); //VH_MICS2710
75 | pinMode(IO2, OUTPUT); //MICS2710_ALTAIMPEDANCIA
76 | pinMode(AWAKE, OUTPUT);
77 | pinMode(MOSI, OUTPUT);
78 | pinMode(SCK, OUTPUT);
79 | pinMode(FACTORY, OUTPUT);
80 | pinMode(CONTROL, INPUT);
81 | digitalWrite(AWAKE, HIGH);
82 | // digitalWrite(FACTORY, LOW);
83 | digitalWrite(FACTORY, HIGH);
84 | }
85 |
86 | boolean sck::findInResponse(const char *toMatch,
87 | unsigned int timeOut = 1000) {
88 | int byteRead;
89 |
90 | unsigned long timeOutTarget; // in milliseconds
91 |
92 | for (unsigned int offset = 0; offset < strlen(toMatch); offset++) {
93 | timeOutTarget = millis() + timeOut; // Doesn't handle timer wrapping
94 | while (!Serial1.available()) {
95 | // Wait, with optional time out.
96 | if (timeOut > 0) {
97 | if (millis() > timeOutTarget) {
98 | return false;
99 | }
100 | }
101 | delay(1); // This seems to improve reliability slightly
102 | }
103 | byteRead = Serial1.read();
104 | //Serial.print((char)byteRead);
105 | delay(1); // Removing logging may affect timing slightly
106 |
107 | if (byteRead != toMatch[offset]) {
108 | offset = 0;
109 | // Ignore character read if it's not a match for the start of the string
110 | if (byteRead != toMatch[offset]) {
111 | offset = -1;
112 | }
113 | continue;
114 | }
115 | }
116 |
117 | return true;
118 | }
119 |
120 | void sck::recovery()
121 | {
122 | if (EEPROM.read(0) == 0)
123 | {
124 | Serial.println(F("Reseting..."));
125 | digitalWrite(FACTORY, HIGH);
126 | delay(1000);
127 | digitalWrite(FACTORY, LOW);
128 | delay(1000);
129 | digitalWrite(FACTORY, HIGH);
130 | delay(1000);
131 | digitalWrite(FACTORY, LOW);
132 | delay(1000);
133 | digitalWrite(FACTORY, HIGH);
134 | delay(1000);
135 | digitalWrite(FACTORY, LOW);
136 | delay(1000);
137 | digitalWrite(FACTORY, HIGH);
138 | delay(1000);
139 | digitalWrite(FACTORY, LOW);
140 | delay(1000);
141 | digitalWrite(FACTORY, HIGH);
142 | delay(1000);
143 | digitalWrite(FACTORY, LOW);
144 | delay(1000);
145 | Serial.println("Please, turn off the board.");
146 | EEPROM.write(0,1);
147 | while(true);
148 | }
149 | else EEPROM.write(0,2);
150 | }
151 |
152 | void sck::skipRemainderOfResponse(unsigned int timeOut) {
153 | unsigned long time = millis();
154 | while (((millis()-time)=0)&&(!repair)); i--)
280 | {
281 | // Serial1.begin(baud[i]);
282 | // Serial.println(baud[i]);
283 | if(enterCommandMode())
284 | {
285 | reset();
286 | repair = true;
287 | }
288 | Serial1.begin(9600);
289 | }
290 | }
291 | else repair = true;
292 | return repair;
293 | }
294 |
295 | boolean sck::ready()
296 | {
297 | if(!enterCommandMode())
298 | {
299 | repair();
300 | }
301 | if (enterCommandMode())
302 | {
303 | Serial1.println(F("join"));
304 | if (findInResponse("Associated!", 8000))
305 | {
306 | skipRemainderOfResponse(3000);
307 | exitCommandMode();
308 | return(true);
309 | }
310 | }
311 | else return(false);
312 | }
313 |
314 | char* itoa(int32_t number)
315 | {
316 | byte count = 0;
317 | uint32_t temp;
318 | if (number < 0) {temp = number*(-1); count++;}
319 | while ((temp/10)!=0)
320 | {
321 | temp = temp/10;
322 | count++;
323 | }
324 | int i;
325 | if (number < 0) {temp = number*(-1);}
326 | else temp = number;
327 | for (i = count; i>=0; i--)
328 | {
329 | buffer[i] = temp%10 + '0';
330 | temp = temp/10;
331 | }
332 | if (number < 0) {buffer[0] = '-';}
333 | buffer[count + 1] = 0x00;
334 | return buffer;
335 | }
336 |
337 |
338 | char* sck::getWiFlyVersion(unsigned long timeOut) {
339 | Serial1.println();
340 | Serial1.println();
341 | char newChar = '<';
342 | byte offset = 0;
343 | unsigned long time = millis();
344 | while (((millis()-time)'))
351 | {
352 | buffer[offset] = newChar;
353 | offset++;
354 | }
355 | else if (newChar=='>') break;
356 | }
357 | }
358 | skipRemainderOfResponse(1000);
359 |
360 | if (newChar=='>')
361 | {
362 | buffer[offset] = 0x00;
363 | return buffer;
364 | }
365 | else return "0";
366 | }
367 |
368 | int sck::checkWiFlyVersion(char *text) {
369 | if (text[0]=='0')
370 | {
371 | Serial.println(F("Error reading version."));
372 | return -1;
373 | }
374 | else if (text[0]<'4') Serial.println(F("Old version, please update."));
375 | else if ((text[0]=='4')&&(text[2]=='0')) Serial.println(F("Warning version, please update."));
376 | else if ((text[0]=='4')&&(text[2]=='4')) Serial.println(F("WiFly up to date."));
377 | else if (text[0]=='W')
378 | {
379 | Serial.println(F("Started as web_app"));
380 | return 0;
381 | }
382 | return 1;
383 | }
384 |
385 | boolean sck::webAppRepair() {
386 | if (enterCommandMode())
387 | {
388 | Serial1.println(F("boot image 2"));
389 | if (findInResponse("= OK", 8000))
390 | {
391 | skipRemainderOfResponse(3000);
392 | Serial1.println(F("save"));
393 | skipRemainderOfResponse(3000);
394 | Serial1.println(F("reboot"));
395 | skipRemainderOfResponse(3000);
396 | enterCommandMode();
397 | Serial.print("Firmware version: ");
398 | char *Version = getWiFlyVersion(1000);
399 | Serial.println(Version);
400 | int state = checkWiFlyVersion(Version);
401 | if (state==1) Serial.print("Wifi device is ok :)");
402 | return(true);
403 | }
404 | }
405 | else return(false);
406 | }
407 |
408 | #define E2PROM 0x50 // Direcion de la EEPROM
409 |
410 | void sck::writeEEPROM(uint16_t eeaddress, uint8_t data) {
411 | uint8_t retry = 0;
412 | while ((readEEPROM(eeaddress)!=data)&&(retry<10))
413 | {
414 | Wire.beginTransmission(E2PROM);
415 | Wire.write((byte)(eeaddress >> 8)); // MSB
416 | Wire.write((byte)(eeaddress & 0xFF)); // LSB
417 | Wire.write(data);
418 | Wire.endTransmission();
419 | delay(6);
420 | retry++;
421 | }
422 | }
423 |
424 | byte sck::readEEPROM(uint16_t eeaddress) {
425 | byte rdata = 0xFF;
426 | Wire.beginTransmission(E2PROM);
427 | Wire.write((byte)(eeaddress >> 8)); // MSB
428 | Wire.write((byte)(eeaddress & 0xFF)); // LSB
429 | Wire.endTransmission();
430 | Wire.requestFrom(E2PROM,1);
431 | while (!Wire.available());
432 | rdata = Wire.read();
433 | return rdata;
434 | }
435 |
436 | #define RTC_ADDRESS 0x68 // Direcion de la RTC
437 |
438 | boolean sck::checkRTC() {
439 | Wire.beginTransmission(RTC_ADDRESS);
440 | Wire.write(0x00); //Address
441 | Wire.endTransmission();
442 | delay(4);
443 | Wire.requestFrom(RTC_ADDRESS,1);
444 | unsigned long time = millis();
445 | while (!Wire.available()) if ((millis() - time)>500) return false;
446 | Wire.read();
447 | return true;
448 | }
449 |
450 | float average(int anaPin) {
451 | int lecturas = 100;
452 | long total = 0;
453 | float average = 0;
454 | for(int i=0; i 500) value = value + 120; //Tension del diodo de proteccion
478 | else value = 0;
479 | #else
480 | uint16_t value = 3*average(PANEL)*Vref/1023.;
481 | if (value > 500) value = value + 750; //Tension del diodo de proteccion
482 | else value = 0;
483 | #endif
484 | return value;
485 | }
486 |
487 | float sck::getBattery() {
488 | uint16_t temp = average(BAT);
489 | #if F_CPU == 8000000
490 | float voltage = Vref*temp/1023.;
491 | voltage = voltage + (voltage/180)*100;
492 | #else
493 | float voltage = Vref*temp/1023.;
494 | #endif
495 | temp = map(voltage, VAL_MIN_BATTERY, VAL_MAX_BATTERY, 0, 1000);
496 | if (temp>1000) temp=1000;
497 | if (temp<0) temp=0;
498 | return temp/10.;
499 | }
500 |
501 | #define RES 256 //Resolucion de los potenciometros digitales
502 |
503 | #if F_CPU == 8000000
504 | #define R1 12 //Kohm
505 | #else
506 | #define R1 82 //Kohm
507 | #endif
508 |
509 | #define P1 100 //Kohm
510 |
511 | float kr= ((float)P1*1000)/RES; //Constante de conversion a resistencia de potenciometrosen ohmios
512 |
513 | void writeMCP(byte deviceaddress, byte address, int data ) {
514 | if (data>RES) data=RES;
515 | Wire.beginTransmission(deviceaddress);
516 | address=(address<<4)|bitRead(data, 8) ;
517 | Wire.write(address);
518 | Wire.write(lowByte(data));
519 | Wire.endTransmission();
520 | delay(4);
521 | }
522 |
523 | int readMCP(int deviceaddress, uint16_t address ) {
524 | byte rdata = 0xFF;
525 | int data = 0x0000;
526 | Wire.beginTransmission(deviceaddress);
527 | address=(address<<4)|B00001100;
528 | Wire.write(address);
529 | Wire.endTransmission();
530 | Wire.requestFrom(deviceaddress,2);
531 | unsigned long time = millis();
532 | while (!Wire.available()) if ((millis() - time)>500) return 0x00;
533 | rdata = Wire.read();
534 | data=rdata<<8;
535 | while (!Wire.available());
536 | rdata = Wire.read();
537 | data=data|rdata;
538 | return data;
539 | }
540 |
541 | #if F_CPU == 8000000
542 | #define MCP3 0x2D // Direcion del mcp3 Ajuste carga bateria
543 | float sck::readCharge() {
544 | float resistor = kr*readMCP(MCP3, 0x00)/1000;
545 | float current = 1000./(2+((resistor * 10)/(resistor + 10)));
546 | return(current);
547 | }
548 | #else
549 | float SCKBase::readCharge() {
550 | return(500);
551 | }
552 | #endif
553 |
554 |
--------------------------------------------------------------------------------
/utilities/SCK_check/SCKlibs.h:
--------------------------------------------------------------------------------
1 | #ifndef __SCKLIBS_H__
2 | #define __SCKLIBS_H__
3 |
4 | #include
5 |
6 | #define TIME_BUFFER_SIZE 20
7 |
8 | class sck {
9 | public:
10 | boolean checkEEPROM();
11 | void begin();
12 | boolean findInResponse(const char *toMatch,
13 | unsigned int timeOut);
14 | void recovery();
15 | void skipRemainderOfResponse(unsigned int timeOut);
16 | boolean sendCommand(const __FlashStringHelper *command,
17 | boolean isMultipartCommand,
18 | const char *expectedResponse);
19 | boolean sendCommand(const char *command,
20 | boolean isMultipartCommand,
21 | const char *expectedResponse);
22 | boolean enterCommandMode();
23 | boolean reset();
24 | boolean exitCommandMode();
25 | boolean connect();
26 | boolean repair();
27 | boolean ready();
28 | char* getWiFlyVersion(unsigned long timeOut);
29 | int checkWiFlyVersion(char *text);
30 | boolean webAppRepair();
31 | void writeEEPROM(uint16_t eeaddress, uint8_t data);
32 | byte readEEPROM(uint16_t eeaddress);
33 | boolean checkRTC();
34 | uint16_t getPanel();
35 | float getBattery();
36 | float readCharge();
37 | private:
38 |
39 | };
40 | #endif
41 |
--------------------------------------------------------------------------------
/utilities/SCK_testing/SCKtester:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | """
3 | Script for testing new SCK kits.
4 | """
5 | version = 0.2
6 |
7 | import serial, sys, glob, shutil, tempfile, urllib, urllib2, json, zipfile, os, time, subprocess
8 |
9 | SSID = "mySSID"
10 | PHRASE = "myPASSWORD"
11 |
12 |
13 | class SCK:
14 | def __init__(self):
15 | # self.baud = 115200
16 | self.baud = 9600
17 | self.timeout = 20
18 | self.port = False
19 | self.mac = False
20 | self.talkWiflyFirmware = "wifly/wifly.ino"
21 | self.maxRetries = 5
22 | self.connected = False
23 | self.wiflyVersion = 0
24 | self.ssid = SSID
25 | self.phrase = PHRASE
26 | self.associated = False
27 | self.ip = False
28 | self.inoFile = False
29 | self.firmwareDir = "firmware"
30 | self.tmpZip = os.path.join(self.firmwareDir, "tmp.zip")
31 | self.logFileName = "testingLog.csv"
32 | self.usePort = False
33 | def _retry(self, command):
34 | retry = 0
35 | while retry < myKit.maxRetries:
36 | myPrint(".")
37 | retry = retry + 1
38 | if command: return True
39 | return False
40 | def _uploadWifliConsole(self):
41 | out = subprocess.Popen(['arduino', '--upload', self.talkWiflyFirmware, '--board', 'arduino:avr:LilyPadUSB', '--port', self.port, '--preserve-temp-files'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
42 | status = out.wait()
43 | if status == 0: return True
44 | else:return False
45 | def _W_getWiflyVersion(self):
46 | self._W_sendWiflyCommand("$$$")
47 | self._W_sendWiflyCommand("\r\n")
48 | self._W_sendWiflyCommand("exit\r\n", "EXIT", 2)
49 | self._W_sendWiflyCommand("$$$")
50 | response = self._W_sendWiflyCommand("\r\n", "> ", 2)
51 | if "<4.41>" in response[1]:
52 | self.wiflyVersion = 4.41
53 | return True
54 | elif "<4.75>" in response[1]:
55 | self.wiflyVersion = 4.75
56 | return True
57 | else:
58 | return False
59 | def _W_wiflyJoin(self):
60 | self._W_sendWiflyCommand("$$$")
61 | self._W_sendWiflyCommand("\r\n")
62 | self._W_sendWiflyCommand("set wlan join 1\r\n", "AOK", 1)
63 | self._W_sendWiflyCommand("set ip dhcp 1\r\n", "AOK", 1)
64 | self._W_sendWiflyCommand("set ip proto 10\r\n", "AOK", 1)
65 | self._W_sendWiflyCommand("set wlan auth 4\r\n", "AOK", 1)
66 | self._W_sendWiflyCommand("set wlan ssid ")
67 | self._W_sendWiflyCommand(self.ssid)
68 | self._W_sendWiflyCommand("\r\n", "AOK", 3)
69 | self._W_sendWiflyCommand("set wlan phrase ")
70 | self._W_sendWiflyCommand(self.phrase)
71 | self._W_sendWiflyCommand("\r\n", "AOK", 3)
72 | self._W_sendWiflyCommand("set wlan ext_antenna 0\r\n", "AOK", 1)
73 | self._W_sendWiflyCommand("save\r\n", "Storing in config", 5)
74 | response = self._W_sendWiflyCommand("reboot\r\n", "Listen on", 15)
75 | if response[0]:
76 | self.associated = True
77 | self.ip = response[1].split("IP=")[1].split(":")[0]
78 | return True
79 | else:
80 | return False
81 | def _W_updateWifly(self):
82 | self._W_sendWiflyCommand("$$$")
83 | self._W_sendWiflyCommand("\r\n")
84 | updateResponse = self._W_sendWiflyCommand("ftp update wifly3-475.img\r\n", "FTP OK", 60)
85 | self._W_sendWiflyCommand("reboot\r\n", "READY", 10)
86 | return updateResponse[0]
87 | def _W_sendWiflyCommand(self, command, expectedResponse=False, timeout=0.3):
88 | self.serial.write(command)
89 | response = ""
90 | startTime = time.time()
91 | while time.time() - startTime < timeout:
92 | response = response + self.serial.read_all()
93 | if isinstance(expectedResponse, basestring) and expectedResponse in response:
94 | return [True, response]
95 | return [False, response]
96 | def _connectSerial(self):
97 | portList = serialPorts()
98 | if self.port not in portList:
99 | if len(portList) == 1:
100 | print "Changing serial port to: " + bcolors.OKBLUE + portList[0] + bcolors.ENDC
101 | self.port = portList[0]
102 | else:
103 | self.port = False
104 | while not self.port:
105 | self.port = serialPorts()[0]
106 | try:
107 | self.serial = serial.Serial(self.port, self.baud)
108 | self.connected = True
109 | return True
110 | except serial.SerialException:
111 | print bcolors.FAIL + "Can't open Serial Port!!" + bcolors.ENDC
112 | self.connected = False
113 | sys.exit()
114 | def _downloadFirmware(self):
115 | if os.path.exists(myKit.firmwareDir) and len(os.listdir(myKit.firmwareDir)) > 0:
116 | self.inoFile = os.path.join(os.path.join(os.path.join(myKit.firmwareDir, os.listdir(myKit.firmwareDir)[0]), 'sck_beta_v0_9'), 'sck_beta_v0_9.ino')
117 | if os.path.exists(self.inoFile):
118 | return True
119 | else:
120 | if not os.path.exists(myKit.firmwareDir): os.makedirs(myKit.firmwareDir)
121 | myPrint(" downloading...")
122 | zipUrl = "https://github.com/fablabbcn/Smart-Citizen-Kit/archive/master.zip"
123 | downloadedZip = urllib.urlretrieve(zipUrl, myKit.tmpZip)[0]
124 | zipfile.ZipFile(downloadedZip).extractall(myKit.firmwareDir)
125 | os.remove(myKit.tmpZip)
126 | self.inoFile = os.path.join(os.path.join(os.path.join(myKit.firmwareDir, os.listdir(myKit.firmwareDir)[0]), 'sck_beta_v0_9'), 'sck_beta_v0_9.ino')
127 | if os.path.exists(self.inoFile):
128 | return True
129 | else:
130 | return False
131 | def _uploadFirmware(self):
132 | out = subprocess.Popen(['arduino', '--upload', self.inoFile, '--board', 'arduino:avr:LilyPadUSB', '--port', self.port, '--preserve-temp-files'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
133 | status = out.wait()
134 | if status == 0: return True
135 | else: return False
136 | def _sendCommand(self, command, expectedResponse=False, timeout=0.3):
137 | self.serial.write(command)
138 | response = ""
139 | startTime = time.time()
140 | while time.time() - startTime < timeout:
141 | response = response + self.serial.read_all()
142 | #exception for post data
143 | if "post data" in command:
144 | time.sleep(0.05)
145 | if isinstance(expectedResponse, basestring) and expectedResponse in response:
146 | return [True, response]
147 | else:
148 | if isinstance(expectedResponse, basestring) and expectedResponse in response:
149 | return [True, response]
150 | return [False, response]
151 | def _update(self):
152 | response = self._sendCommand("get all\r\n", "|60|1|", 2)
153 | if response[0]:
154 | r = response[1].split("|")
155 | self.version = r[1]
156 | self.mac = r[2]
157 | self.nets = r[3]
158 | self.hardcodedNets = r[4]
159 | self.timeUpdate = r[5]
160 | self.posts = r[6]
161 | else:
162 | return False
163 | response = self._sendCommand("post data\r\n", "UTC:", 45)
164 | if response[0]:
165 | self.temperature = int(response[1].split("Temperature: ")[1].split(" ")[0])
166 | self.humidity = int(response[1].split("Humidity: ")[1].split(" ")[0])
167 | self.light = float(response[1].split("Light: ")[1].split(" ")[0])
168 | self.battery = float(response[1].split("Battery: ")[1].split(" ")[0])
169 | self.solarPanel = float(response[1].split("Panel: ")[1].split(" ")[0])
170 | self.co = float(response[1].split("Monxide: ")[1].split(" ")[0])
171 | self.no2 = float(response[1].split("Dioxide: ")[1].split(" ")[0])
172 | self.noise = float(response[1].split("Noise: ")[1].split(" ")[0])
173 | self.wifiSpots = int(response[1].split("Spots: ")[1].split("\r\n")[0])
174 | self.utc = response[1].split("UTC: ")[1].split("\r\n")[0]
175 | return True
176 | else:
177 | return False
178 | def _evaluate(self):
179 | if self.wiflyVersion < 4.75: return "ERROR: wifly ver"
180 | if not self.ip or self.ip == "0.0.0.0": return "ERROR: no ip"
181 | if self.temperature > 40000 or self.temperature < 0: return "ERROR: temp sensor"
182 | if self.humidity > 100000 or self.humidity < 0: return "ERROR: humidity sensor"
183 | if self.light > 1000 or self.light < 0: return "ERROR: light sensor"
184 | if self.co > 10000 or self.co < 0: return "ERROR: CO sensor"
185 | if self.no2 > 10000 or self.no2 < 0: return "ERROR: NO2 sensor"
186 | if self.noise > 10000 or self.noise < 0: return "ERROR: noise sensor"
187 | return "PASSED"
188 | def _log(self):
189 | headers = "mac_address,firmware_version,wifly_version,temperature,humidity,light,battery,solar_panel,CO,NO2,noise,passed,comment\n"
190 | toLog = [self.mac, self.version, self.wiflyVersion, self.temperature, self.humidity, self.light, self.battery, self.solarPanel, self.co, self.no2, self.noise]
191 | result = self._evaluate()
192 |
193 |
194 | if not os.path.exists(myKit.logFileName):
195 | try:
196 | myFile = open(myKit.logFileName, 'w')
197 | except:
198 | print bcolors.FAIL + "can't create log file!!!, bye!" + bcolors.ENDC
199 | sys.exit()
200 | myFile.write(headers)
201 | else:
202 | try:
203 | myFile = open(myKit.logFileName, 'a')
204 | except:
205 | print bcolors.FAIL + "can't create log file!!!, bye!" + bcolors.ENDC
206 | sys.exit()
207 | for d in toLog:
208 | myFile.write(str(d) + ",")
209 | print headers.split(",")[toLog.index(d)] + ": " + bcolors.OKBLUE + str(d) + bcolors.ENDC
210 | if result == "PASSED":
211 | myFile.write("1")
212 | else:
213 | myFile.write("0")
214 | myFile.write("," + result)
215 | myFile.write("\n")
216 | myFile.close()
217 | return result
218 |
219 | def myPrint(text):
220 | sys.stdout.write(str(text))
221 | sys.stdout.flush()
222 | def serialPorts():
223 | """Lists serial ports
224 |
225 | :raises EnvironmentError:
226 | On unsupported or unknown platforms
227 | :returns:
228 | A list of available serial ports
229 | """
230 | if sys.platform.startswith('win'):
231 | ports = ['COM' + str(i + 1) for i in range(256)]
232 |
233 | elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
234 | # this is to exclude your current terminal "/dev/tty"
235 | ports = glob.glob('/dev/tty[A-Za-z]*')
236 |
237 | elif sys.platform.startswith('darwin'):
238 | ports = glob.glob('/dev/tty.*')
239 |
240 | else:
241 | raise EnvironmentError('Unsupported platform')
242 |
243 | result = []
244 |
245 | #TODO validar que quien responde es un SCK
246 | for port in ports:
247 | try:
248 | s = serial.Serial(port)
249 | s.close()
250 | result.append(port)
251 | except (OSError, serial.SerialException):
252 | pass
253 | return result
254 | def selectPort(ports):
255 | if len(ports) == 1:
256 | print "\nOnly one serial port found, using it! (" + bcolors.OKBLUE + ports[0] + bcolors.ENDC + ")"
257 | return ports[0]
258 | if len(ports) > 0:
259 | print "\nSelect a serial port from the list:\n"
260 | for p in ports:
261 | print "\t" + str(ports.index(p) + 1) + ". " + p
262 |
263 | i = raw_input("\n[" + ports[0] + "]: ")
264 |
265 | try:
266 | val = int(i)
267 | except:
268 | if i == "": val = 1
269 | else: val = -1
270 |
271 | if val-1 >= len(ports) or val-1 < 0:
272 | print "\n*** please input the port number! ***"
273 | return False
274 | else:
275 | return ports[val -1]
276 | else:
277 | print bcolors.FAIL + "No serial port available, bye!" + bcolors.ENDC
278 | sys.exit()
279 | def wiflySetup():
280 | myPrint("Uploading firmware for wifly setup...")
281 | if myKit._retry(myKit._uploadWifliConsole()):
282 | print bcolors.OKGREEN + " OK" + bcolors.ENDC
283 | else:
284 | print bcolors.FAIL + " can't upload firmware, bye!" + bcolors.ENDC
285 | sys.exit()
286 |
287 | time.sleep(1)
288 | myKit._connectSerial()
289 |
290 | myPrint("Checking Wifly version...")
291 | if myKit._retry(myKit._W_getWiflyVersion()):
292 | if myKit.wiflyVersion < 4.75:
293 | myPrint(" " + bcolors.FAIL + str(myKit.wiflyVersion) + bcolors.ENDC)
294 | print " upgrade needed!!!"
295 | else:
296 | print " " + bcolors.OKGREEN + str(myKit.wiflyVersion) + bcolors.ENDC
297 | else:
298 | print bcolors.FAIL + " can't talk with wifly module (try resetting your SCK), bye!" + bcolors.ENDC
299 | sys.exit()
300 |
301 | myPrint("Conecting to network " + bcolors.OKBLUE + myKit.ssid + bcolors.ENDC + "...")
302 | if myKit._retry(myKit._W_wiflyJoin()):
303 | print bcolors.OKGREEN + " OK" + bcolors.ENDC + " (" + bcolors.OKBLUE + myKit.ip + bcolors.ENDC + ")"
304 | else:
305 | print bcolors.FAIL + " cant'connect to network, bye!" + bcolors.ENDC
306 | sys.exit()
307 |
308 | if myKit.wiflyVersion < 4.75:
309 | myPrint("Upgrading wifly version...")
310 | if myKit._retry(myKit._W_updateWifly()) and myKit._W_getWiflyVersion() and myKit.wiflyVersion == 4.75:
311 | print bcolors.OKGREEN + " OK" + bcolors.ENDC
312 | else:
313 | print bcolors.FAIL + " Upgrade failed, please try again, bye!" + bcolors.ENDC
314 | sys.exit()
315 |
316 | #return to factory settings
317 | myPrint("Reseting wifly module...")
318 | myKit._W_sendWiflyCommand("$$$")
319 | myKit._W_sendWiflyCommand("\r\n")
320 | myKit._W_sendWiflyCommand("factory RESET\r\n", "Set Factory Defaults", 1)
321 | myKit._W_sendWiflyCommand("save\r\n", "Storing in config", 1)
322 | response = myKit._W_sendWiflyCommand("reboot\r\n", "*READY*", 15)
323 | if response[0]:
324 | print bcolors.OKGREEN + " OK" + bcolors.ENDC
325 | return True
326 | def installFirmware():
327 | if not myKit.inoFile:
328 | myPrint("Looking for latest SCK firmware...")
329 | if myKit._downloadFirmware():
330 | print bcolors.OKGREEN + " OK" + bcolors.ENDC
331 | else:
332 | print bcolors.FAIL + " download failed, bye!" + bcolors.ENDC
333 | sys.exit()
334 | myPrint("Uploading latest firmware...")
335 | if myKit._uploadFirmware():
336 | print bcolors.OKGREEN + " OK" + bcolors.ENDC
337 | else:
338 | print bcolors.FAIL + " ERROR, reset your kit and try again, bye!" + bcolors.ENDC
339 | sys.exit()
340 | return True
341 |
342 | class bcolors:
343 | OKBLUE = '\033[36m'
344 | OKGREEN = '\033[92m'
345 | WARNING = '\033[93m'
346 | FAIL = '\033[91m'
347 | ENDC = '\033[0m'
348 | BOLD = '\033[1m'
349 | UNDERLINE = '\033[4m'
350 |
351 | if __name__ == '__main__':
352 |
353 | myKit = SCK()
354 |
355 | benchStart = time.time()
356 |
357 | if len(sys.argv) > 1:
358 | if sys.argv[1] == "-p":
359 | myKit.usePort = True
360 | else:
361 | print
362 | print "Usage: SCKtester.py [OPTION]"
363 | print
364 | print " -p If there is only one serial port, don't ask, use it"
365 | print
366 | sys.exit()
367 |
368 | print "\n------------------------------------------"
369 | print "| " + bcolors.BOLD + "Smartcitizen Kit tester Script ver " + str(version) + bcolors.ENDC + " |"
370 | print "------------------------------------------"
371 |
372 | #seleccion de puerto
373 | while not myKit.port:
374 | myKit.port = selectPort(serialPorts())
375 |
376 |
377 | if wiflySetup():
378 | if installFirmware():
379 | time.sleep(5)
380 | if myKit._connectSerial():
381 | time.sleep(0.5)
382 | myPrint("Reading sensors...")
383 | if myKit._retry(myKit._update()):
384 | print bcolors.OKGREEN + " OK\n" + bcolors.ENDC
385 | result = myKit._log()
386 | if result == "PASSED":
387 | print "\nTesting " + bcolors.OKGREEN + result + bcolors.ENDC + "\n"
388 | else:
389 | print bcolors.FAIL + "\n" + result + bcolors.ENDC + "\n"
390 | else:
391 | print bcolors.FAIL + "can't read sensors! bye!" + bcolors.ENDC
392 | sys.exit()
393 | myPrint("Last task: clearing nets and eeprom memory...")
394 | myKit._sendCommand("clear nets\r\n")
395 | myKit._sendCommand("clear memory\r\n")
396 | myKit._sendCommand("get all\r\n", "|60|1|", 25)
397 | print bcolors.OKGREEN + " OK" + bcolors.ENDC
398 | print "Testing has took " + bcolors.OKBLUE + str(int(time.time()-benchStart)) + bcolors.ENDC + " seconds."
399 | print "Bye!\n"
400 |
--------------------------------------------------------------------------------
/utilities/SCK_testing/readme.md:
--------------------------------------------------------------------------------
1 | Smartcitizen Kit testing script
2 | =================
3 |
4 |
5 | #### A python script to test and update Smartcitizen kits
6 |
7 | ##### It's a command line utility aimed to check the different parts of a kit and apply available updates in the most possible automated way.
8 |
9 | * Checks wifly firmware version and installs available updates.
10 | * Installs the latest available firmware from github (after first installation if you want to refresh the firmware, delete the folder named *"firmware"* before running the script again)
11 | * Takes readings from sensors and checks if values are inside an acceptable range (*work in progress*).
12 | * Creates a csv file with the results of the tests with one entry per tested kit.
13 |
14 | ------
15 | ##### Using the script
16 |
17 | * This script requires a working installation of [python](https://www.python.org/) and [Arduino IDE](https://www.arduino.cc/en/Main/Software) and a working Internet connection with wi-fi access.
18 | * Download this folder to your computer, edit your network settings on line 9-10, connect your kit to the USB port and run the script with `python SCKtester`.
19 | * If you only have the kit connected to your computer and only one serial port is available, you can skip port selection with the *-p* option: `python SCKtester -p`
20 |
21 | ------
22 | ##### Screenshot
23 | 
--------------------------------------------------------------------------------
/utilities/SCK_testing/shot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fablabbcn/smartcitizen-kit-10/5d343f7c37d714c69dcb57fa3f7c47099750bee6/utilities/SCK_testing/shot.png
--------------------------------------------------------------------------------
/utilities/SCK_testing/wifly/wifly.ino:
--------------------------------------------------------------------------------
1 |
2 |
3 | void setup() {
4 | Serial.begin(9600);
5 | Serial1.begin(9600);
6 |
7 | pinMode(4, OUTPUT); //despierta al wifly
8 | digitalWrite(4, LOW);
9 |
10 | pinMode(7, OUTPUT); //factory RESET/AP RN131
11 | digitalWrite(7, LOW);
12 |
13 | pinMode(MOSI, OUTPUT);
14 | pinMode(SCK, OUTPUT);
15 | }
16 |
17 | void loop() {
18 | if (Serial.available())
19 | {
20 | int inByte = Serial.read();
21 | Serial1.write(inByte);
22 | }
23 | if (Serial1.available()) {
24 | int inByte = Serial1.read();
25 | Serial.write(inByte);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/utilities/Wifly_Rescue/SCKBase.ino:
--------------------------------------------------------------------------------
1 |
2 | #define AWAKE 4 //Despertar WIFI
3 | #define PANEL A8 //Entrada panel
4 | #define BAT A7 //Entrada bateria
5 |
6 | #define IO0 5 //MICS5525_HEATHER
7 | #define IO1 13 //MICS2710_HEATHER
8 | #define IO2 9 //MICS2710_ALTAIMPEDANCIA
9 | #define IO3 10 //MICS2710_ALTAIMPEDANCIA
10 | #define FACTORY 7 //factory RESET/AP RN131
11 | #define CONTROL 12 //Control Mode
12 |
13 | #define S0 A4 //MICS_5525
14 | #define S1 A5 //MICS_2710
15 | #define S2 A2 //SENS_5525
16 | #define S3 A3 //SENS_2710
17 | #define S4 A0 //MICRO
18 | #define S5 A1 //LDR
19 |
20 | #define OPEN "0"
21 | #define WEP "1"
22 | #define WPA1 "2"
23 | #define WPA2 "4"
24 | #define WEP64 "8"
25 |
26 | #define INT_ANT "0" //EXT_ANT
27 | #define EXT_ANT "1" //EXT_ANT
28 |
29 | char* mySSID = "Red";
30 | char* myPassword = "Pass";
31 | char* wifiEncript = WPA2;
32 | char* antenna = INT_ANT; //EXT_ANT
33 |
34 |
35 | boolean connected;
36 |
37 | #define buffer_length 32
38 | static char buffer[buffer_length];
39 |
40 | void sckBegin() {
41 | Serial.begin(115200);
42 | Serial1.begin(9600);
43 | pinMode(IO0, OUTPUT); //VH_MICS5525
44 | pinMode(IO1, OUTPUT); //VH_MICS2710
45 | pinMode(IO2, OUTPUT); //MICS2710_ALTAIMPEDANCIA
46 | pinMode(AWAKE, OUTPUT);
47 | pinMode(MOSI, OUTPUT);
48 | pinMode(SCK, OUTPUT);
49 | pinMode(FACTORY, OUTPUT);
50 | pinMode(CONTROL, INPUT);
51 | digitalWrite(AWAKE, LOW);
52 | digitalWrite(FACTORY, HIGH);
53 | // digitalWrite(FACTORY, LOW);
54 | }
55 |
56 | boolean sckFindInResponse(const char *toMatch,
57 | unsigned int timeOut = 1000) {
58 | int byteRead;
59 |
60 | unsigned long timeOutTarget; // in milliseconds
61 |
62 | for (unsigned int offset = 0; offset < strlen(toMatch); offset++) {
63 | timeOutTarget = millis() + timeOut; // Doesn't handle timer wrapping
64 | while (!Serial1.available()) {
65 | // Wait, with optional time out.
66 | if (timeOut > 0) {
67 | if (millis() > timeOutTarget) {
68 | return false;
69 | }
70 | }
71 | delay(1); // This seems to improve reliability slightly
72 | }
73 | byteRead = Serial1.read();
74 | //Serial.print((char)byteRead);
75 | delay(1); // Removing logging may affect timing slightly
76 |
77 | if (byteRead != toMatch[offset]) {
78 | offset = 0;
79 | // Ignore character read if it's not a match for the start of the string
80 | if (byteRead != toMatch[offset]) {
81 | offset = -1;
82 | }
83 | continue;
84 | }
85 | }
86 |
87 | return true;
88 | }
89 |
90 | void sckRecovery()
91 | {
92 | Serial.println(F("Reseting..."));
93 | digitalWrite(FACTORY, HIGH);
94 | delay(1000);
95 | digitalWrite(FACTORY, LOW);
96 | delay(1000);
97 | digitalWrite(FACTORY, HIGH);
98 | delay(1000);
99 | digitalWrite(FACTORY, LOW);
100 | delay(1000);
101 | digitalWrite(FACTORY, HIGH);
102 | delay(1000);
103 | digitalWrite(FACTORY, LOW);
104 | delay(1000);
105 | digitalWrite(FACTORY, HIGH);
106 | delay(1000);
107 | digitalWrite(FACTORY, LOW);
108 | delay(1000);
109 | digitalWrite(FACTORY, HIGH);
110 | delay(1000);
111 | digitalWrite(FACTORY, LOW);
112 | delay(1000);
113 | Serial1.println();
114 | sckFindInResponse("=0)&&repair); i--)
256 | {
257 | Serial1.begin(baud[i]);
258 | Serial.println(baud[i]);
259 | if(sckEnterCommandMode())
260 | {
261 | sckReset();
262 | repair = false;
263 | }
264 | Serial1.begin(9600);
265 | }
266 | }
267 | }
268 |
269 | boolean sckReady()
270 | {
271 | if(!sckEnterCommandMode())
272 | {
273 | sckRepair();
274 | }
275 | if (sckEnterCommandMode())
276 | {
277 | Serial1.println(F("join"));
278 | if (sckFindInResponse("Associated!", 8000))
279 | {
280 | sckSkipRemainderOfResponse(3000);
281 | sckExitCommandMode();
282 | return(true);
283 | }
284 | }
285 | else return(false);
286 | }
287 |
288 | char* itoa(int32_t number)
289 | {
290 | byte count = 0;
291 | uint32_t temp;
292 | if (number < 0) {temp = number*(-1); count++;}
293 | while ((temp/10)!=0)
294 | {
295 | temp = temp/10;
296 | count++;
297 | }
298 | int i;
299 | if (number < 0) {temp = number*(-1);}
300 | else temp = number;
301 | for (i = count; i>=0; i--)
302 | {
303 | buffer[i] = temp%10 + '0';
304 | temp = temp/10;
305 | }
306 | if (number < 0) {buffer[0] = '-';}
307 | buffer[count + 1] = 0x00;
308 | return buffer;
309 | }
310 |
311 |
312 |
313 |
--------------------------------------------------------------------------------
/utilities/Wifly_Rescue/Wifly_Rescue.ino:
--------------------------------------------------------------------------------
1 | void setup() {
2 | sckBegin();
3 | delay(5000);
4 | sckRecovery();
5 | }
6 |
7 | void loop() {
8 | if (Serial.available())
9 | {
10 | int inByte = Serial.read();
11 | Serial1.write(inByte);
12 | }
13 | if (Serial1.available()) {
14 | int inByte = Serial1.read();
15 | Serial.write(inByte);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/utilities/Wifly_Update/SCKBase.ino:
--------------------------------------------------------------------------------
1 |
2 | #define AWAKE 4 //Despertar WIFI
3 | #define PANEL A8 //Entrada panel
4 | #define BAT A7 //Entrada bateria
5 |
6 | #define IO0 5 //MICS5525_HEATHER
7 | #define IO1 13 //MICS2710_HEATHER
8 | #define IO2 9 //MICS2710_ALTAIMPEDANCIA
9 | #define IO3 10 //MICS2710_ALTAIMPEDANCIA
10 | #define FACTORY 7 //factory RESET/AP RN131
11 | #define CONTROL 12 //Control Mode
12 |
13 | #define S0 A4 //MICS_5525
14 | #define S1 A5 //MICS_2710
15 | #define S2 A2 //SENS_5525
16 | #define S3 A3 //SENS_2710
17 | #define S4 A0 //MICRO
18 | #define S5 A1 //LDR
19 |
20 | #define OPEN "0"
21 | #define WEP "1"
22 | #define WPA1 "2"
23 | #define WPA2 "4"
24 | #define WEP64 "8"
25 |
26 | #define INT_ANT "0" //EXT_ANT
27 | #define EXT_ANT "1" //EXT_ANT
28 |
29 | //char* mySSID = "Red";
30 | //char* myPassword = "Pass";
31 | char* mySSID = "Mi$Red";
32 | char* myPassword = "FINALFANTASY";
33 | char* wifiEncript = WPA2;
34 | char* antenna = INT_ANT; //EXT_ANT
35 |
36 |
37 | boolean connected;
38 |
39 | #define buffer_length 32
40 | static char buffer[buffer_length];
41 |
42 | void sckBegin() {
43 | Serial.begin(115200);
44 | Serial1.begin(9600);
45 | pinMode(IO0, OUTPUT); //VH_MICS5525
46 | pinMode(IO1, OUTPUT); //VH_MICS2710
47 | pinMode(IO2, OUTPUT); //MICS2710_ALTAIMPEDANCIA
48 | pinMode(AWAKE, OUTPUT);
49 | pinMode(MOSI, OUTPUT);
50 | pinMode(SCK, OUTPUT);
51 | pinMode(FACTORY, OUTPUT);
52 | pinMode(CONTROL, INPUT);
53 | digitalWrite(AWAKE, LOW);
54 | digitalWrite(FACTORY, LOW);
55 | sckExitCommandMode();
56 | }
57 |
58 | boolean sckFindInResponse(const char *toMatch,
59 | unsigned int timeOut = 1000) {
60 | int byteRead;
61 |
62 | unsigned long timeOutTarget; // in milliseconds
63 |
64 | for (unsigned int offset = 0; offset < strlen(toMatch); offset++) {
65 | timeOutTarget = millis() + timeOut; // Doesn't handle timer wrapping
66 | while (!Serial1.available()) {
67 | // Wait, with optional time out.
68 | if (timeOut > 0) {
69 | if (millis() > timeOutTarget) {
70 | return false;
71 | }
72 | }
73 | delay(1); // This seems to improve reliability slightly
74 | }
75 | byteRead = Serial1.read();
76 | //Serial.print((char)byteRead);
77 | delay(1); // Removing logging may affect timing slightly
78 |
79 | if (byteRead != toMatch[offset]) {
80 | offset = 0;
81 | // Ignore character read if it's not a match for the start of the string
82 | if (byteRead != toMatch[offset]) {
83 | offset = -1;
84 | }
85 | continue;
86 | }
87 | }
88 |
89 | return true;
90 | }
91 |
92 | void sckRecovery()
93 | {
94 | Serial.println("Reseting...");
95 | digitalWrite(FACTORY, HIGH);
96 | delay(1000);
97 | digitalWrite(FACTORY, LOW);
98 | delay(1000);
99 | digitalWrite(FACTORY, HIGH);
100 | delay(1000);
101 | digitalWrite(FACTORY, LOW);
102 | delay(1000);
103 | digitalWrite(FACTORY, HIGH);
104 | delay(1000);
105 | digitalWrite(FACTORY, LOW);
106 | delay(1000);
107 | digitalWrite(FACTORY, HIGH);
108 | delay(1000);
109 | digitalWrite(FACTORY, LOW);
110 | delay(1000);
111 | digitalWrite(FACTORY, HIGH);
112 | delay(1000);
113 | digitalWrite(FACTORY, LOW);
114 | delay(1000);
115 | Serial1.println();
116 | sckFindInResponse("=0)&&repair); i--)
271 | {
272 | Serial1.begin(baud[i]);
273 | Serial.println(baud[i]);
274 | if(sckEnterCommandMode())
275 | {
276 | sckReset();
277 | repair = false;
278 | }
279 | Serial1.begin(9600);
280 | }
281 | }
282 | }
283 |
284 | boolean sckReady()
285 | {
286 | if(!sckEnterCommandMode())
287 | {
288 | sckRepair();
289 | }
290 | if (sckEnterCommandMode())
291 | {
292 | Serial1.println(F("join"));
293 | if (sckFindInResponse("Associated!", 8000))
294 | {
295 | sckSkipRemainderOfResponse(3000);
296 | sckExitCommandMode();
297 | return(true);
298 | }
299 | }
300 | else return(false);
301 | }
302 |
303 | char* itoa(int32_t number)
304 | {
305 | byte count = 0;
306 | uint32_t temp;
307 | if (number < 0) {temp = number*(-1); count++;}
308 | while ((temp/10)!=0)
309 | {
310 | temp = temp/10;
311 | count++;
312 | }
313 | int i;
314 | if (number < 0) {temp = number*(-1);}
315 | else temp = number;
316 | for (i = count; i>=0; i--)
317 | {
318 | buffer[i] = temp%10 + '0';
319 | temp = temp/10;
320 | }
321 | if (number < 0) {buffer[0] = '-';}
322 | buffer[count + 1] = 0x00;
323 | return buffer;
324 | }
325 |
326 |
327 |
328 |
--------------------------------------------------------------------------------
/utilities/Wifly_Update/Wifly_Update.ino:
--------------------------------------------------------------------------------
1 | void setup() {
2 | sckBegin();
3 | delay(5000);
4 | sckConnect();
5 | sckExitCommandMode();
6 | sckEnterCommandMode();
7 | }
8 |
9 | void loop() {
10 | if (!digitalRead(12))
11 | {
12 | if (sckConnect())
13 | {
14 | Serial.println("connected!!");
15 | sckExitCommandMode();
16 | sckEnterCommandMode();
17 | Serial.println("Updating...");
18 | if (sckUpdate()) Serial.println("Update OK");
19 | else Serial.println("Update FAIL");
20 | sckReset();
21 | }
22 | else Serial.println("Connection Fail :(");
23 | }
24 |
25 | if (Serial.available())
26 | {
27 | int inByte = Serial.read();
28 | Serial1.write(inByte);
29 | }
30 | if (Serial1.available()) {
31 | int inByte = Serial1.read();
32 | Serial.write(inByte);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/utilities/wifly_terminal/SCKBase.ino:
--------------------------------------------------------------------------------
1 |
2 | #define AWAKE 4 //Despertar WIFI
3 | #define PANEL A8 //Entrada panel
4 | #define BAT A7 //Entrada bateria
5 |
6 | #define IO0 5 //MICS5525_HEATHER
7 | #define IO1 13 //MICS2710_HEATHER
8 | #define IO2 9 //MICS2710_ALTAIMPEDANCIA
9 | #define IO3 10 //MICS2710_ALTAIMPEDANCIA
10 | #define FACTORY 7 //factory RESET/AP RN131
11 | #define CONTROL 12 //Control Mode
12 |
13 | #define S0 A4 //MICS_5525
14 | #define S1 A5 //MICS_2710
15 | #define S2 A2 //SENS_5525
16 | #define S3 A3 //SENS_2710
17 | #define S4 A0 //MICRO
18 | #define S5 A1 //LDR
19 |
20 | #define OPEN "0"
21 | #define WEP "1"
22 | #define WPA1 "2"
23 | #define WPA2 "4"
24 | #define WEP64 "8"
25 |
26 | #define INT_ANT "0" //EXT_ANT
27 | #define EXT_ANT "1" //EXT_ANT
28 |
29 | char* mySSID = "Red";
30 | char* myPassword = "Pass";
31 | char* wifiEncript = WPA2;
32 | char* antenna = INT_ANT; //EXT_ANT
33 |
34 |
35 | boolean connected;
36 |
37 | #define buffer_length 32
38 | static char buffer[buffer_length];
39 |
40 | void sckBegin() {
41 | Serial.begin(115200);
42 | Serial1.begin(9600);
43 | pinMode(IO0, OUTPUT); //VH_MICS5525
44 | pinMode(IO1, OUTPUT); //VH_MICS2710
45 | pinMode(IO2, OUTPUT); //MICS2710_ALTAIMPEDANCIA
46 | pinMode(AWAKE, OUTPUT);
47 | pinMode(MOSI, OUTPUT);
48 | pinMode(SCK, OUTPUT);
49 | pinMode(FACTORY, OUTPUT);
50 | pinMode(CONTROL, INPUT);
51 | digitalWrite(AWAKE, LOW);
52 | digitalWrite(FACTORY, LOW);
53 | }
54 |
55 | boolean sckFindInResponse(const char *toMatch,
56 | unsigned int timeOut = 1000) {
57 | int byteRead;
58 |
59 | unsigned long timeOutTarget; // in milliseconds
60 |
61 | for (unsigned int offset = 0; offset < strlen(toMatch); offset++) {
62 | timeOutTarget = millis() + timeOut; // Doesn't handle timer wrapping
63 | while (!Serial1.available()) {
64 | // Wait, with optional time out.
65 | if (timeOut > 0) {
66 | if (millis() > timeOutTarget) {
67 | return false;
68 | }
69 | }
70 | delay(1); // This seems to improve reliability slightly
71 | }
72 | byteRead = Serial1.read();
73 | //Serial.print((char)byteRead);
74 | delay(1); // Removing logging may affect timing slightly
75 |
76 | if (byteRead != toMatch[offset]) {
77 | offset = 0;
78 | // Ignore character read if it's not a match for the start of the string
79 | if (byteRead != toMatch[offset]) {
80 | offset = -1;
81 | }
82 | continue;
83 | }
84 | }
85 |
86 | return true;
87 | }
88 |
89 | void sckRecovery()
90 | {
91 | Serial.println("Reseting...");
92 | digitalWrite(FACTORY, HIGH);
93 | delay(1000);
94 | digitalWrite(FACTORY, LOW);
95 | delay(1000);
96 | digitalWrite(FACTORY, HIGH);
97 | delay(1000);
98 | digitalWrite(FACTORY, LOW);
99 | delay(1000);
100 | digitalWrite(FACTORY, HIGH);
101 | delay(1000);
102 | digitalWrite(FACTORY, LOW);
103 | delay(1000);
104 | digitalWrite(FACTORY, HIGH);
105 | delay(1000);
106 | digitalWrite(FACTORY, LOW);
107 | delay(1000);
108 | digitalWrite(FACTORY, HIGH);
109 | delay(1000);
110 | digitalWrite(FACTORY, LOW);
111 | delay(1000);
112 | Serial1.println();
113 | sckFindInResponse("=0)&&repair); i--)
268 | {
269 | Serial1.begin(baud[i]);
270 | Serial.println(baud[i]);
271 | if(sckEnterCommandMode())
272 | {
273 | sckReset();
274 | repair = false;
275 | }
276 | Serial1.begin(9600);
277 | }
278 | }
279 | }
280 |
281 | boolean sckReady()
282 | {
283 | if(!sckEnterCommandMode())
284 | {
285 | sckRepair();
286 | }
287 | if (sckEnterCommandMode())
288 | {
289 | Serial1.println(F("join"));
290 | if (sckFindInResponse("Associated!", 8000))
291 | {
292 | sckSkipRemainderOfResponse(3000);
293 | sckExitCommandMode();
294 | return(true);
295 | }
296 | }
297 | else return(false);
298 | }
299 |
300 | char* itoa(int32_t number)
301 | {
302 | byte count = 0;
303 | uint32_t temp;
304 | if (number < 0) {temp = number*(-1); count++;}
305 | while ((temp/10)!=0)
306 | {
307 | temp = temp/10;
308 | count++;
309 | }
310 | int i;
311 | if (number < 0) {temp = number*(-1);}
312 | else temp = number;
313 | for (i = count; i>=0; i--)
314 | {
315 | buffer[i] = temp%10 + '0';
316 | temp = temp/10;
317 | }
318 | if (number < 0) {buffer[0] = '-';}
319 | buffer[count + 1] = 0x00;
320 | return buffer;
321 | }
322 |
323 |
324 |
325 |
--------------------------------------------------------------------------------
/utilities/wifly_terminal/wifly_terminal.ino:
--------------------------------------------------------------------------------
1 | void setup() {
2 | sckBegin();
3 | sckRepair();
4 | //sckConnect();
5 | sckEnterCommandMode();
6 | }
7 |
8 | void loop() {
9 | if (Serial.available())
10 | {
11 | int inByte = Serial.read();
12 | Serial1.write(inByte);
13 | }
14 | if (Serial1.available()) {
15 | int inByte = Serial1.read();
16 | Serial.write(inByte);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------