Advertisement
bld

Untitled

bld
Mar 24th, 2014
161
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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.  
  230. const char server[] = "www.server.com";
  231.  
  232. bool webRead = false;
  233. bool isTime = true;
  234. String webString = String(15);
  235.  
  236. void nodeSync()
  237. {
  238.     if (syncState == 0) // Check if it is time to sync
  239.     {
  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.     }
  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.  
  250.         if (client.connect (server, 80))
  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.             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.             syncState = 3;
  270.             RGB.color(0, 255, 0);
  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.             {
  283.                 if (isTime)
  284.                 {
  285.                     isTime = false;
  286.                    
  287.                     char * inString = new char[webString.length() + 1];
  288.                     strcpy(inString, webString.c_str());
  289.                     nextSyncIn = atoi(inString);
  290.                     nextSyncIn *= 1000;
  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.             }
  305.                
  306.             if (c == '>') // > = end of commands
  307.             {
  308.                 webString = "";
  309.                 syncState = 4;
  310.             }
  311.                
  312.             if (c == '<') // < = start of commands
  313.             {
  314.                 webRead = true;
  315.             }
  316.        
  317.             sendPublish();
  318.             if (millis() - syncStart > 5000) // If synchronization takes more than 5 seconds, abort and try again in 60 seconds
  319.             {
  320.                 nextSyncIn = 60000;
  321.                 RGB.control(false);
  322.                 syncState = 4;
  323.             }
  324.         }
  325.         else
  326.         {
  327.             syncState = 4;
  328.         }
  329.     }
  330.     else if (syncState == 4) // Done with the web server, stop client and set state to check the time again
  331.     {
  332.         client.stop();
  333.    
  334.         sendPublish();
  335.  
  336.         RGB.control(false);
  337.         syncState = 0;
  338.     }
  339. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement