Ss Brewing Technologies Giveaway!

Home Brew Forums > Home Brewing Beer > DIY Projects > TeensyPi Networked Temperature Controller
Reply
 
LinkBack Thread Tools
Old 02-08-2013, 06:43 PM   #131
redbenn
Feedback Score: 0 reviews
Recipes 
 
Join Date: Dec 2009
Location: Chicago
Posts: 133
Liked 3 Times on 3 Posts

Default

In the Action Array, what is the difference between:

Code:
uint32_t  tcDelay;
 uint32_t tcMillis;
Are they both storing the delay time, tcDelay in seconds, and tcMillis the millisecond value of tcDelay?
__________________
redbenn is offline
 
Reply With Quote Quick reply to this message
Old 02-08-2013, 07:09 PM   #132
jimmayhugh
Turgid Member
HBT_LIFETIMESUPPORTER.png
Feedback Score: 0 reviews
 
jimmayhugh's Avatar
Recipes 
 
Join Date: Feb 2011
Location: Las Vegas, NV
Posts: 581
Liked 46 Times on 41 Posts
Likes Given: 2

Default

Quote:
Originally Posted by redbenn View Post
In the Action Array, what is the difference between:
Code:
uint32_t  tcDelay;
 uint32_t tcMillis;
Are they both storing the delay time, tcDelay in seconds, and tcMillis the millisecond value of tcDelay?
The Delay value is the number of miiliseconds of delay that can be set by the user in order to delay the turn on of the associated switch. This would be used in cases where you don't want the device to be constantly turning on and off, such as a refrigerator compressor. The Millis is set with the current time the first time the trigger is reached, and reset when the trigger value is no longer correct.
jimmayhugh is offline
 
Reply With Quote Quick reply to this message
Old 02-08-2013, 11:00 PM   #133
jimmayhugh
Turgid Member
HBT_LIFETIMESUPPORTER.png
Feedback Score: 0 reviews
 
jimmayhugh's Avatar
Recipes 
 
Join Date: Feb 2011
Location: Las Vegas, NV
Posts: 581
Liked 46 Times on 41 Posts
Likes Given: 2

Default

Got my TeensyPi board and RGB LCD boards back from the fabricators, both work as planned.

Also got the switch boards back, and they also are working.

After I've wrung them out for a couple of weeks, I'll offer then to interested parties.

jimmayhugh is offline
 
Reply With Quote Quick reply to this message
Old 02-09-2013, 03:08 PM   #134
redbenn
Feedback Score: 0 reviews
Recipes 
 
Join Date: Dec 2009
Location: Chicago
Posts: 133
Liked 3 Times on 3 Posts

Default

OK, I am looking to setup the array to setup multiple PIDs

I think I understand the values of the array:

Code:
typedef struct
{
  bool     pidEnabled;
  chipStruct *tempPtr;
  int16_t  pidSetPoint;
  chipStruct *tcPtr;
  uint8_t  tcSwitchLastState;
  chipStruct *thPtr;
  uint8_t  thSwitchLastState;
  uint32_t  pidKp;
  uint32_t  pidKi;
  uint32_t  pidKd;
  uint32_t  pidDirection;
  uint32_t  pidMode;
  uint32_t  pidWindowSize;
  uint32_t  windowStartTime;
}chipPIDStruct;

chipPIDStruct ePID[maxPIDs] =
{
  { FALSE, NULL, 70, NULL, 'F', NULL, 'F', 0, 0, 0, 1, 5000, 0 },
  { FALSE, NULL, 70, NULL, 'F', NULL, 'F', 0, 0, 0, 1, 5000, 0 },
  { FALSE, NULL, 70, NULL, 'F', NULL, 'F', 0, 0, 0, 1, 5000, 0 },
  { FALSE, NULL, 70, NULL, 'F', NULL, 'F', 0, 0, 0, 1, 5000, 0 },
  { FALSE, NULL, 70, NULL, 'F', NULL, 'F', 0, 0, 0, 1, 5000, 0 },
  { FALSE, NULL, 70, NULL, 'F', NULL, 'F', 0, 0, 0, 1, 5000, 0 },
  { FALSE, NULL, 70, NULL, 'F', NULL, 'F', 0, 0, 0, 1, 5000, 0 },
  { FALSE, NULL, 70, NULL, 'F', NULL, 'F', 0, 0, 0, 1, 5000, 0 },
  { FALSE, NULL, 70, NULL, 'F', NULL, 'F', 0, 0, 0, 1, 5000, 0 },
  { FALSE, NULL, 70, NULL, 'F', NULL, 'F', 0, 0, 0, 1, 5000, 0 },
  { FALSE, NULL, 70, NULL, 'F', NULL, 'F', 0, 0, 0, 1, 5000, 0 },
  { FALSE, NULL, 70, NULL, 'F', NULL, 'F', 0, 0, 0, 1, 5000, 0 }
};
Would I then call 12 individual PIDs? Or is there a way to construct via the array, to replace this code
Code:
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);

int WindowSize = 5000;
unsigned long windowStartTime;
Something like:
Code:
PID ePID[x](&Input, &Output, &Setpoint, &kP, &kI, &kD, &Direction);
I could then call the PID like:

Code:
void updatePIDs(uint8_t x)
{

  
  if(epid[x].actionEnabled == TRUE)
  {
    Input = ePID[x].tempPtr->chipStatus;
    ePID[x].Compute();
    
  /************************************************
   * turn the output pin on/off based on pid output
   ************************************************/
  if(millis() - ePID[x].windowStartTime>ePID[x].WindowSize)
  { //time to shift the Relay Window
    ePID[x].windowStartTime += ePID[x].WindowSize;
  }
  
  unsigned long now = millis();

  if(Output > now - windowStartTime) setSwitch(epid[x].tcPtr,ds2406PIOAoff);
    else setSwitch(epid[x].tcPtr,ds2406PIOAon);
// *** End PID Loop ***
    }
__________________
redbenn is offline
 
Reply With Quote Quick reply to this message
Old 02-10-2013, 01:34 AM   #135
jimmayhugh
Turgid Member
HBT_LIFETIMESUPPORTER.png
Feedback Score: 0 reviews
 
jimmayhugh's Avatar
Recipes 
 
Join Date: Feb 2011
Location: Las Vegas, NV
Posts: 581
Liked 46 Times on 41 Posts
Likes Given: 2

Default

OK here's my thoughts on the PID so far:

First, the variables and structures:

Code:
// PID Stuff

double Input, Output;
const uint8_t maxPIDs = 12;
uint8_t pidCnt = 0;

typedef struct
{
  bool       pidEnabled;
  chipStruct *tempPtr;
  double     pidSetPoint;
  chipStruct *switchPtr;
  uint8_t    switchLastState;
  double     pidKp;
  double     pidKi;
  double     pidKd;
  int        pidDirection;
  uint32_t   pidMode;
  uint32_t   pidWindowSize;
  uint32_t   pidwindowStartTime;
  PID       *myPID;
}chipPIDStruct;

chipPIDStruct ePID[maxPIDs] =
{
  { FALSE, NULL, 70, NULL, 'F', 0, 0, 0, 1, 0, 5000, 0, NULL },
  { FALSE, NULL, 70, NULL, 'F', 0, 0, 0, 1, 0, 5000, 0, NULL },
  { FALSE, NULL, 70, NULL, 'F', 0, 0, 0, 1, 0, 5000, 0, NULL },
  { FALSE, NULL, 70, NULL, 'F', 0, 0, 0, 1, 0, 5000, 0, NULL },
  { FALSE, NULL, 70, NULL, 'F', 0, 0, 0, 1, 0, 5000, 0, NULL },
  { FALSE, NULL, 70, NULL, 'F', 0, 0, 0, 1, 0, 5000, 0, NULL },
  { FALSE, NULL, 70, NULL, 'F', 0, 0, 0, 1, 0, 5000, 0, NULL },
  { FALSE, NULL, 70, NULL, 'F', 0, 0, 0, 1, 0, 5000, 0, NULL },
  { FALSE, NULL, 70, NULL, 'F', 0, 0, 0, 1, 0, 5000, 0, NULL },
  { FALSE, NULL, 70, NULL, 'F', 0, 0, 0, 1, 0, 5000, 0, NULL },
  { FALSE, NULL, 70, NULL, 'F', 0, 0, 0, 1, 0, 5000, 0, NULL },
  { FALSE, NULL, 70, NULL, 'F', 0, 0, 0, 1, 0, 5000, 0, NULL }
};

//Specify the links and initial tuning parameters
PID PID0(&Input,  &Output,  &ePID[0].pidSetPoint,  (double) ePID[0].pidKp,  (double) ePID[0].pidKi,  (double) ePID[0].pidKd,  ePID[0].pidDirection);
PID PID1(&Input,  &Output,  &ePID[1].pidSetPoint,  (double) ePID[1].pidKp,  (double) ePID[1].pidKi,  (double) ePID[1].pidKd,  ePID[1].pidDirection);
PID PID2(&Input,  &Output,  &ePID[2].pidSetPoint,  (double) ePID[2].pidKp,  (double) ePID[2].pidKi,  (double) ePID[2].pidKd,  ePID[2].pidDirection);
PID PID3(&Input,  &Output,  &ePID[3].pidSetPoint,  (double) ePID[3].pidKp,  (double) ePID[3].pidKi,  (double) ePID[3].pidKd,  ePID[3].pidDirection);
PID PID4(&Input,  &Output,  &ePID[4].pidSetPoint,  (double) ePID[4].pidKp,  (double) ePID[4].pidKi,  (double) ePID[4].pidKd,  ePID[4].pidDirection);
PID PID5(&Input,  &Output,  &ePID[5].pidSetPoint,  (double) ePID[5].pidKp,  (double) ePID[5].pidKi,  (double) ePID[5].pidKd,  ePID[5].pidDirection);
PID PID6(&Input,  &Output,  &ePID[6].pidSetPoint,  (double) ePID[6].pidKp,  (double) ePID[6].pidKi,  (double) ePID[6].pidKd,  ePID[6].pidDirection);
PID PID7(&Input,  &Output,  &ePID[7].pidSetPoint,  (double) ePID[7].pidKp,  (double) ePID[7].pidKi,  (double) ePID[7].pidKd,  ePID[7].pidDirection);
PID PID8(&Input,  &Output,  &ePID[8].pidSetPoint,  (double) ePID[8].pidKp,  (double) ePID[8].pidKi,  (double) ePID[7].pidKd,  ePID[8].pidDirection);
PID PID9(&Input,  &Output,  &ePID[9].pidSetPoint,  (double) ePID[9].pidKp,  (double) ePID[9].pidKi,  (double) ePID[8].pidKd,  ePID[9].pidDirection);
PID PID10(&Input, &Output, &ePID[10].pidSetPoint, (double) ePID[10].pidKp, (double) ePID[10].pidKi, (double) ePID[10].pidKd, ePID[10].pidDirection);
PID PID11(&Input, &Output, &ePID[11].pidSetPoint, (double) ePID[11].pidKp, (double) ePID[11].pidKi, (double) ePID[11].pidKd, ePID[10].pidDirection);

PID *pidArray[] = {&PID0,&PID1,&PID2,&PID3,&PID4,&PID5,&PID6,&PID7,&PID8,&PID9,&PID10,&PID11};

// End PID Stuff
You're using one temp chip and one switch for each PID.

Next, you need to initialize the PIDs in the setup():
Code:
/// ***** Start PID Setup *****

  for(x =0; x < maxPIDs; x++)
  {
    ePID[x].myPID = pidArray[x];
    ePID[x].pidwindowStartTime = millis();
    ePID[x].pidSetPoint = 70;
  //tell the PID to range between 0 and the full window size
    ePID[x].myPID->SetOutputLimits(0, ePID[x].pidWindowSize);
  //turn the PID on
    ePID[x].myPID->SetMode(AUTOMATIC);
  }


/// ***** End PID Setup *****
Then test the PID's in the loop():
Code:
    updatePIDs(pidCnt);
    pidCnt++;
    if(pidCnt >= maxPIDs){pidCnt = 0;}
And finally the actual PID control function:
Code:
void updatePIDs(uint8_t pidCnt)
{
// *** Start PID Loop ***
  Input = (double) ePID[pidCnt].tempPtr->chipStatus;
  ePID[pidCnt].myPID->Compute();

  /************************************************
   * turn the output pin on/off based on pid output
   ************************************************/
  if(millis() - ePID[pidCnt].pidwindowStartTime > ePID[pidCnt].pidWindowSize)
  { //time to shift the Relay Window
    ePID[pidCnt].pidwindowStartTime += ePID[pidCnt].pidWindowSize;
  }
  
  unsigned long now = millis();

  if(Output > now - ePID[pidCnt].pidwindowStartTime) actionSwitchSet((uint8_t *) &ePID[pidCnt].switchPtr->chipAddr,ds2406PIOAoff);
    else actionSwitchSet((uint8_t *) &ePID[pidCnt].switchPtr->chipAddr,ds2406PIOAon);
// *** End PID Loop ***
}
I've plugged this code into my IDE, and it all compiles, but I haven't actually tested it.

You might want to try a single instance of the code and see if it behaves as you expect.

What remains are the PHP code and functions to set up and enable/disable the PIDs from the Web Interface.

But that's enough for today...
jimmayhugh is offline
 
Reply With Quote Quick reply to this message
Old 02-10-2013, 06:08 PM   #136
redbenn
Feedback Score: 0 reviews
Recipes 
 
Join Date: Dec 2009
Location: Chicago
Posts: 133
Liked 3 Times on 3 Posts

Default

Wow, thanks for the code!

Loaded it up, and the input switch came on, but it never booted the webserver so I couldn't view the temps, it didn't react when I heated and cooled.

Hooked the raspberry pi up to my monitor, and got a lot of unreadable text during boot.

The Teensy LED also stayed solid, so it looks like it wasn't reading the sensors.

Going to keep playing with it.

__________________
redbenn is offline
 
Reply With Quote Quick reply to this message
Old 02-10-2013, 06:34 PM   #137
jimmayhugh
Turgid Member
HBT_LIFETIMESUPPORTER.png
Feedback Score: 0 reviews
 
jimmayhugh's Avatar
Recipes 
 
Join Date: Feb 2011
Location: Las Vegas, NV
Posts: 581
Liked 46 Times on 41 Posts
Likes Given: 2

Default

Quote:
Originally Posted by redbenn View Post
Wow, thanks for the code!

Loaded it up, and the input switch came on, but it never booted the webserver so I couldn't view the temps, it didn't react when I heated and cooled.

Hooked the raspberry pi up to my monitor, and got a lot of unreadable text during boot.

The Teensy LED also stayed solid, so it looks like it wasn't reading the sensors.

Going to keep playing with it.
It's not going to work just "yet"...

The code still needs an initialization routine similar to the "updateActionArray" case in the softSerialProcess() function. You'll also need a php program similar to ActionDataWithMySQL.php to setup and initialize the PID array. Finally you need a php program similar to ActionStatus.php and updateActionStatusWithMySQL.php to display the PID results.

I'm right in the middle of another project right now, but I'll be happy to help when and where I can.
__________________
TeensyNet Networked Controller
ButtCrack Brewery
And This Is Why We Drink...
jimmayhugh is offline
 
Reply With Quote Quick reply to this message
Old 02-12-2013, 06:10 AM   #138
redbenn
Feedback Score: 0 reviews
Recipes 
 
Join Date: Dec 2009
Location: Chicago
Posts: 133
Liked 3 Times on 3 Posts

Default

Working on the UI a bit today.

I have a dark and light version using gauges for the thermometers and switches for the switches.




I will post the code tomorrow.

__________________
redbenn is offline
 
Reply With Quote Quick reply to this message
Old 02-12-2013, 10:49 AM   #139
jimmayhugh
Turgid Member
HBT_LIFETIMESUPPORTER.png
Feedback Score: 0 reviews
 
jimmayhugh's Avatar
Recipes 
 
Join Date: Feb 2011
Location: Las Vegas, NV
Posts: 581
Liked 46 Times on 41 Posts
Likes Given: 2

Default

Looks Good!

__________________
TeensyNet Networked Controller
ButtCrack Brewery
And This Is Why We Drink...
jimmayhugh is offline
 
Reply With Quote Quick reply to this message
Old 02-12-2013, 08:10 PM   #140
helibrewer
HBT_SUPPORTER.png
Feedback Score: 1 reviews
 
helibrewer's Avatar
Recipes 
 
Join Date: Nov 2011
Location: Santa Rosa, CA
Posts: 3,218
Liked 192 Times on 172 Posts
Likes Given: 47

Default

Nice UI redbenn.

__________________
Something is always fermenting....
"It's Bahl Hornin'"

Primary:
Brite Tank/Lagering:
Kegged: Hefeweizen, Chocolate Hazelnut Porter, Kumquat Saison, Tart Cherry Cider, Belgian Tripel, Maibock Bock, Ommegang Abbey Ale Clone, Belgian Golden Strong, German Pils (WLP830)
Bottled: Belgian Quad (Grand Reserve), Derangement (Belgian Dark Strong)
On Deck:
My Site: www.restlesscellars.com
helibrewer is offline
 
Reply With Quote Quick reply to this message
Reply



Quick Reply
Message:
Options
Thread Tools


Similar Threads
Thread Thread Starter Forum Replies Last Post
Arduino - Networked Temperature Monitor jimmayhugh DIY Projects 81 01-27-2013 12:22 AM
Temperature Controller sy2088 Equipment/Sanitation 3 10-25-2012 06:28 PM
Lux Temperature Controller scoots DIY Projects 9 07-06-2012 01:38 PM
temperature controller from deas fridge - use as external controller on live fridge? BrewingChemist DIY Projects 1 05-22-2012 10:21 PM
Johnson Analog Temperature Controller Temperature Profile Coastarine Equipment/Sanitation 4 10-11-2010 03:58 PM