View difference between Paste ID: Q7rG05Xj and yGUSeRzG
SHOW: | | - or go back to the newest paste.
1
/***********************************************************************************************************
2
Variables used for turning a pin high/low, depending on temperature
3
***********************************************************************************************************/
4
#define relayPin                7       // Set what pin the relay is connected to
5
#define relayInvert             0       // Set to 1 to invert the function of the relay
6
7
float targetTemp =              23.0;   // Target temperature
8
float targetHyst =              0.1;    // Hysteresis determinig how much over and under target temp it should trigger
9
10
11
/***********************************************************************************************************
12
Variables used for reading the TMP36 temperature sensor
13
***********************************************************************************************************/
14
#define TMP36pin                A0
15
#define readTMP36trot 500               // Time in milliseconds between temperature readings
16
char tempStr[16];                       // Holding the result in the json api reply
17
18
/***********************************************************************************************************
19
Variables used for averaging temperature readings
20
The temperature can be accessed by opening https://api.spark.io/v1/devices/{device id}/temperature?access_token={access token}
21
***********************************************************************************************************/
22
#define tempArraySize           20      // Size of the arry holding values for averaging
23
double temps[tempArraySize];            // Arry holding temperature readings
24
double temperature =            0;      // Current average temperature
25
int idx =                       0;      // Index of where we are in the array
26
27
28
/***********************************************************************************************************
29
Only used temporarily until Spark.publish(); can run from inside a function called by Spark.function();
30
***********************************************************************************************************/
31
char sendPublishMessage[128];
32
bool sendPublishActive = false;
33
void sendPublish()
34
{
35
    if (sendPublishActive)
36
    {
37
        sendPublishActive = false;
38
        Spark.publish("debug", sendPublishMessage);
39
    }
40
}
41
42
43
void setup()
44
{
45
    pinMode(relayPin, OUTPUT);  // Set pin for the relay to output
46
    Spark.variable("temperature", &tempStr, STRING);    // Register variable so it can be accessed with the api later
47
    
48
    Spark.function("SETPINS", handlePinCommand);
49
}
50
51
52
void loop()
53
{
54
    nodeSync(); // When last sync was and sync if needed
55
    
56
    cyclePins(); // Run through the tables and check if we got any pulses remaining on any pin
57
    
58
    readTMP36();    // Read from the temperature sensor and set the temperature variable
59
    sprintf(tempStr, "%4.3f", temperature); // Set the result we are going to reply with when asked by the api (returning temperature with two decimals)
60
    
61
    handleRelay(); // Check temperature and determine if relay should be pulled or released
62
    
63
    sendPublish(); // Check if we got any messages pending to be published
64
}
65
66
/***********************************************************************************************************
67
Determine if the pin should be HIGH or LOW depending on temperature and hysteresis
68
***********************************************************************************************************/
69
bool relayState = false;
70
void handleRelay()
71
{
72
    char sendPublishMessage[128];
73
    if (temperature < (targetTemp-targetHyst)) // If the temperature is below our target temperature-hysteresis then...
74
    {
75
        digitalWrite(relayPin, relayInvert?LOW:HIGH); // Set pin high, or low if function is inverted
76
        
77
        if (!relayState)
78
        {
79
            relayState = true;
80
            Spark.publish("relay", "1");
81
        }
82
    }
83
    else if (temperature > targetTemp+targetHyst) // If the temperature is ablove target temperature+hysteresis then..
84
    {
85
        digitalWrite(relayPin, relayInvert?HIGH:LOW); // Set pin to low, or high if function is inverted
86
        
87
        if (relayState)
88
        {
89
            relayState = false;
90
            Spark.publish("relay", "0");
91
        }
92
    }
93
}
94
95
96
/***********************************************************************************************************
97
Read from the TMP36 sensor, calculate themperature and average tmperature
98
***********************************************************************************************************/
99
unsigned long readTMP36last =   0;      // Holding time of when temperature was last checked
100
void readTMP36() // Function for reading from the sensor
101
{
102
    unsigned int now = millis(); // Set the current time (from when the controller was powered on)
103
    
104
    if (now - readTMP36last < readTMP36trot) return; // If less than 500ms (default) has passed, just stop here and return to loop()
105
106
    readTMP36last = now; // More than 500ms (default) has passed, store the time we are reading at so we know when to do it again
107
   
108
    temps[idx] = ((((analogRead(TMP36pin)*3.3)/4095.0)-0.5)*100.0); // Check analog input and calculate the temperature
109
    
110
    if (++idx >= tempArraySize) idx = 0; // Add one to the array index, and check that we dont go above its size, if we do, set index to 0
111
    
112
    double total = 0; // Used to hold total value of the array
113
    for(int i=0; i < tempArraySize; i++) // Run through the array holding the temperatures
114
    {
115
        total += temps[i]; // Add each temperature in the array to the total
116
    }
117
    temperature = total / tempArraySize; // Set temperature variable to total temperature, divided by the array size, so we get an average temperature
118
}
119
120
121
/***********************************************************************************************************
122
Hold info about how many pulses/steps each pin should do, the delay between them,
123
when it last pulsed, and how long a pulse should be
124
***********************************************************************************************************/
125
int stepsLeft[8];                                       // Array to store how many times it should flash the pin
126
int stepDelay[8];                                       // Array to store how long a delay there should be between the pin state changing
127
unsigned long lastStep[8];                              // Array to store when the pin was changed last
128
int pulseLength[8] = {50, 50, 50, 50, 50, 50, 50, 200}; // Array holding pulse length for each pin, so each pin can have a different pulse length
129
130
void cyclePins()
131
{
132
    for (int i = 0; i <= 8; i++) // Run through the arrays to see if any pin should be changed
133
    {
134
        unsigned long now = millis();
135
        
136
        if (stepsLeft[i] > 0) // Do we have to do any steps on this pin?
137
        {
138
            if (now - lastStep[i] >= stepDelay[i]) // Calculate if we are at, or passed the set delay time between pulses
139
            {
140
                lastStep[i] = now; // Set when we set the pin HIGH, so we can calculate when to set it LOW again
141
                digitalWrite(i, HIGH); // Set pin to HIGH
142
                stepsLeft[i]--; // Remove one step
143
            }
144
        }
145
        
146
        if (now - lastStep[i] >= pulseLength[i] && stepsLeft[i] >= 0) // Check if pin has been HIGH long enough and if we are above -1 steps left
147
        {
148
            if (stepsLeft[i] == 0) stepsLeft[i] = -1; // Set steps left to -1 so we don't get in here again
149
            
150
            digitalWrite(i, LOW); // Set pin to LOW
151
        }
152
    }
153
}
154
155
/***********************************************************************************************************
156
Receiving the command for the pins and filling the arrays in the above section accordingly
157
***********************************************************************************************************/
158
int handlePinCommand(String command)
159
{
160
    int pinNum = 0, pinState = 0, pinDelay = 0;
161
    
162
    char * params = new char[command.length() + 1];
163
    strcpy(params, command.c_str());
164
    
165
    char * p = strtok(params, "-");
166
    
167
    int commandStep = 0;
168
    while (p != NULL)
169
    {
170
        //get the values for 
171
        if (commandStep == 0)
172
        {
173
            pinNum = atoi(p);
174
        }
175
        else if (commandStep == 1)
176
        {
177
            pinState = atoi(p);
178
        }
179
        else if (commandStep == 2)
180
        {
181
            pinDelay = atoi(p);
182
            if (pinDelay < pulseLength[pinNum]) pinDelay = pulseLength[pinNum] + 5; // Delay between each pulse can't be less than the pulse length
183
        }
184
        
185
        commandStep++;
186
        p = strtok(NULL, "-");
187
    }
188
189
    pinMode(pinNum, OUTPUT); //Set pin to OUTPUT
190
    
191
    if (stepsLeft[pinNum]) // We gott a new command while doing a number of pulses
192
    {
193
        stepsLeft[pinNum] = 0;
194
        stepDelay[pinNum] = 0;
195
        lastStep[pinNum] = 0;
196
        digitalWrite(pinNum, LOW);
197
    }
198
199
    if (pinDelay > 0)
200
    {
201
        stepsLeft[pinNum] = pinState; //Store how many times the pin should flash, it is changing state for each pass, so it should be done twice for 1 on/off cycle
202
        stepDelay[pinNum] = pinDelay; //Store the delay between pin changes
203
        lastStep[pinNum] = 0; //Set the last time it changed to 0 so it will happen on next loop
204
        
205
        sprintf(sendPublishMessage,"Pin: %d - Flashes: %d - Delay: %d",pinNum,pinState,pinDelay);
206
    }
207
    else
208
    {
209
        stepsLeft[pinNum] = -1; // Set steps left to -1 so cyclePins() will leave it alone
210
        digitalWrite(pinNum, pinState?HIGH:LOW); // Set the pin defined earlier
211
        sprintf(sendPublishMessage,"Pin: %d - State: %d", pinNum, pinState);
212
    }
213
    
214
    sendPublishActive = true;
215
    
216
    return 1;
217
}
218
219
/***********************************************************************************************************
220
Doing synchronization with the database to make sure controller and database is set the same
221
***********************************************************************************************************/
222
TCPClient client;
223
224
unsigned long syncStart = 0;
225
unsigned long lastSync = 0;
226
unsigned long nextSyncIn = 3600000; // Store how many milliseconds until we sync again
227
228
int syncState = 1; // 1 = Need to sync now / 2 = Connected to server / 3 = Client is available / 4 = Reading from web server
229-
    if ((millis() - lastSync < nextSyncIn  && lastSync != 0) && millis() >= lastSync) return; //Only check once every hour, unless we havent checked yet, or if time since overflow of millis is less than last time we checked
229+
230
const char server[] = "www.server.com";
231-
    syncStart = millis();
231+
232
bool webRead = false;
233-
    unsigned long tic = millis();
233+
bool isTime = true;
234-
    char send2PublishMessage[128];
234+
String webString = String(15);
235
236-
    RGB.control(true);
236+
237
{
238-
    const char server[] = "www.server.com";
238+
    if (syncState == 0) // Check if it is time to sync
239
    {
240-
    if (sendGetRequest (server))
240+
        if (millis() - lastSync >= nextSyncIn) syncState = 1; //Only check once every hour, unless we havent checked yet, or if time since overflow of millis is less than last time we checked
241-
    {  
241+
242-
        while (!client.available())
242+
    else if (syncState == 1) // Need to sync now
243
    {
244
        lastSync = millis(); // We read all to the end of the command line, forget the time we reached that point
245
        
246
        webString = "";
247
        
248
        char buf[256];
249-
        bool webRead = false;
249+
250-
        bool isTime = true;
250+
        if (client.connect (server, 80))
251-
        String webString = String(15);
251+
252
            RGB.color(255, 0, 0);
253
            sprintf (buf, "GET /sync.php?spark=%s HTTP/1.1\r\n", Spark.deviceID().c_str());
254-
        while (client.available())
254+
            client.print (buf);
255
            sprintf (buf, "Connection: close\r\nHost: %s\r\n\r\n", server);
256
            client.print (buf);
257
            client.flush();
258
            syncState = 2;
259
        }
260
    }
261
    else if (syncState == 2) // Connected to the web server, waiting for it to reply
262
    {
263
        syncStart = millis();
264
265
        RGB.control(true);
266
        
267
        if (client.available())
268
        {
269-
                    sprintf(send2PublishMessage,"Next synchronization in: %i seconds", (nextSyncIn/1000));
269+
            syncState = 3;
270-
                    Spark.publish("debug", send2PublishMessage);
270+
271
        }
272
    }
273
    else if (syncState == 3) // Web server replied, read what was replied
274
    {
275
        RGB.color(255, 165, 0);
276
            
277
        if(client.available())
278
        {
279
            char c = client.read();
280
            
281
            if (webRead && (c == ',' || c == '>')) // , = command seperator > = no more commands
282-
                   webString.concat(c);
282+
283
                if (isTime)
284
                {
285
                    isTime = false;
286
                    
287
                    char * inString = new char[webString.length() + 1];
288-
                lastSync = millis(); // We read all to the end of the command line, forget the time we reached that point
288+
289
                    nextSyncIn = atoi(inString);
290-
                break;
290+
291
                }
292
                else
293
                {
294
                    handlePinCommand(webString); //Send the string with commands to the function to execute it
295
                }
296
                webString = ""; //Empty string so it is ready for a new command
297
            }
298
            else
299
            {
300
                if (webRead) // webRead is set to true when we encounter the start of commands character
301
                {
302
                webString.concat(c);
303
                }
304-
                break;
304+
305
                
306
            if (c == '>') // > = end of commands
307
            {
308
                webString = "";
309
                syncState = 4;
310
            }
311-
    sendPublish();
311+
                
312
            if (c == '<') // < = start of commands
313-
    unsigned long toc = millis();
313+
314-
    sprintf(send2PublishMessage,"Synchronization took : %ims", (toc-tic));
314+
315-
    Spark.publish("debug", send2PublishMessage);
315+
316
        
317-
    RGB.control(false);
317+
318
            if (millis() - syncStart > 5000) // If synchronization takes more than 5 seconds, abort and try again in 60 seconds
319
            {
320-
char buf[256];
320+
321-
int sendGetRequest (const char *server)
321+
322
                syncState = 4;
323-
    if (client.connect (server, 80))
323+
324
        }
325-
        RGB.color(255, 0, 0);
325+
        else
326-
        sprintf (buf, "GET /sync.php?spark=%s HTTP/1.1\r\n", Spark.deviceID().c_str());
326+
327-
        client.print (buf);
327+
            syncState = 4;
328-
        sprintf (buf, "Connection: close\r\nHost: %s\r\n\r\n", server);
328+
329-
        client.print (buf);
329+
330-
        client.flush();
330+
    else if (syncState == 4) // Done with the web server, stop client and set state to check the time again
331-
        return 1;
331+
332
        client.stop();
333-
    return 0;
333+
334
        sendPublish();
335
336
        RGB.control(false);
337
        syncState = 0;
338
    }
339
}