Hi I have a an arduino which controls a temperature with a Dallas DS18B20 temp sensor and the arduino PID lib I control it. It used to work fine for quite some times except for very rare instances where the temp sensors just gave max or min readings.
but now (I did not change a thing) I get 0 readings from the arduino all the time every 3-5measurement (measurement every second to PC ) when the PID is on. when it is off it behaves normal.
I attached one of my tuning curves so one can see the problem visually.
I tried to condense the code as much as possible the entire programm is quite big (So I might have missed one or two functions).
#include <OneWire.h>
#include <DallasTemperature.h>
#include <PID_v1.h>
#include "helper.c"
int pwmpeltier1 = 3;
int dirpeltier1 = 8;
int power = 0; //Power level fro 0 to 99%
int peltier_level = map(power, 0, 99, 0, 255);
// Setup a oneWire instance to communicate with any OneWire devices
// (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
DeviceAddress tmp_address;
int numberOfDevices;
//---------------------------end One Wire Tempsensors Setup--------------------------------
//------------------------------------- PID Setup------------------------------------------
//Define Variables we'll be connecting to
double Setpoint1, Input1, Output1, Setpoint2, Input2, Output2;
//Define the aggressive and conservative Tuning Parameters
double Kp1=39, Ki1=0.9, Kd1=43;
double Kp2=4, Ki2=0.2, Kd2=1;
byte PIDon=0;
//Specify the links and initial tuning parameters
PID myPIDh(&Input1, &Output1, &Setpoint1, Kp1, Ki1, Kd1, DIRECT);
void setup()
{
// start serial port at 115200 bps:
Serial.begin(115200);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
pinMode(fan, OUTPUT);
digitalWrite(fan, fanstat);
//-------------------????????????????????????____________________________
// pinMode(2, INPUT); // digital sensor is on digital pin 2
//------------------------??????????????????-----\end
establishContact(); // send a byte to establish contact until receiver responds
sensors.begin();
delay(1000);
numberOfDevices = sensors.getDeviceCount();
Serial.print("Found ");
Serial.print(numberOfDevices);
Serial.println(" sensors. Starting now...");
//setup peltier
pinMode(dirpeltier1, OUTPUT);
digitalWrite(dirpeltier1, dirstate);
setPwmFrequency(11, 1024);
//---------setup PID---------
//flush temperature sensor buffer
for(int i=0;i<=3;i++)
{
float t1,t2;
getTemp(t1,t2);
}
//declaring Setpoints to be initial values
float t1,t2;
getTemp(t1,t2);
Input1=t1;
Input2=t2;
Setpoint1=t1;
Setpoint2=t2;
//Initializing values
//PID stays off for now
//--------- end setup PID---------
}
void mainfkt(int mini, int maxi)
{
if (Serial.peek() == 'r')
{
char y = Serial.read();
//Serial.write(y);Serial.println(" Reads data from sensors.");
SendTemperature();
}
else if (Serial.peek() == 'n')
{
char y = Serial.read();
//Serial.print(y);Serial.print(" Number of found sensors: ");
numberOfDevices = sensors.getDeviceCount();
Serial.println(numberOfDevices);
}
else if (Serial.peek() == 'a')
{
char y = Serial.read();
Serial.print(y);Serial.println(" starting PID hot side!");
myPIDh.SetMode(AUTOMATIC);
PIDon=1;
}
else if (Serial.peek() == 'k')
{
char y = Serial.read();
Kp1=readdouble(0.0,500.0);
Ki1=readdouble(0.0,500.0);
Kd1=readdouble(0.0,500.0);
SendHotKs();
}
else if (Serial.peek() == 't')
{
//get Setpoint for hot side
char y = Serial.read();
Setpoint1=readdouble(22,80);
SendHotKs();
}
else if (Serial.peek() == 'g')
{
//get data for hot side
char y = Serial.read();
Serial.print("In.: ");Serial.print(Input1);Serial.print(" SP: ");Serial.print(Setpoint1);Serial.print(" Out: ");Serial.print(Output1);Serial.print(" Kp: ");Serial.print(Kp1);
Serial.print(" Ki: ");Serial.print(Ki1);Serial.print(" Kd: ");Serial.print(Kd1);Serial.print(" PIDon: ");Serial.println(PIDon);
}
void SendHotKs() {
char buffer[25];
String sKp1=ftoa(buffer, Kp1, 2);
String sKi1=ftoa(buffer, Ki1, 2);
String sKd1=ftoa(buffer, Kd1, 2);
Serial.println("Kp1: "+sKp1+" Ki1: "+sKi1+" Kd1: "+sKd1);
}
void loop()
{
// if we get a valid byte, read analog ins:
if (Serial.available() > 0) {
// get incoming byte:
//Serial.println("Serial Available");
mainfkt(0,100);
}
else if (PIDon==1) {
//do PID Stuff
float t1,t2;
getTemp(t1,t2);
if (dirstate==LOW)
{
Input1 = t1;
Input2 = t2;
}
else
{
//changed direction: switch input values
Input1 = t2;
Input2 = t1;
}
myPIDh.SetTunings(Kp1, Ki1, Kd1);
myPIDh.Compute();
if (dirstate==LOW)
{
analogWrite(pwmpeltier1, Output1); // Peltier1 set to PID Output
analogWrite(pwmpeltier2, Output2); // Peltier2 set to PID Output
}
else
{
//changed direction: switch pwmpeltiers to corresponding Outputs
analogWrite(pwmpeltier1, Output2); // Peltier1 set to PID Output
analogWrite(pwmpeltier2, Output1); // Peltier2 set to PID Output
}
}
double readdouble(double mini, double maxi)
{
double x = Serial.parseFloat();
if (x< mini || x>maxi){
//Serial.print("The value needs to be between ");Serial.print(mini);Serial.print(" and ");Serial.print(maxi);Serial.println("!");
if (x< mini){
x=mini;
//Serial.print("Since you entered a value lower than ");Serial.print(mini);Serial.print(", ");Serial.print(mini);Serial.println("was chosen!");
}
else{
x=maxi;
//Serial.print("Since you entered a value higher than ");Serial.print(maxi);Serial.print(", ");Serial.print(maxi);Serial.println("was chosen!");
}
}
return(x);
}
int readint(int mini, int maxi)
{
float in=Serial.parseFloat();
int x =(int)in;
if (x< mini || x>maxi){
//Serial.print("The value needs to be between ");Serial.print(mini);Serial.print(" and ");Serial.print(maxi);Serial.println("!");
if (x< mini){
x=mini;
//Serial.print("Since you entered a value lower than ");Serial.print(mini);Serial.print(", ");Serial.print(mini);Serial.println("was chosen!");
}
else{
x=maxi;
//Serial.print("Since you entered a value higher than ");Serial.print(maxi);Serial.print(", ");Serial.print(maxi);Serial.println("was chosen!");
}
}
return(x);
}
void setpowerlevel()
{
if(power > 100) power = 100;
if(power < 0) power = 0;
peltier_level = map(power, 0, 100, 0, 255);
Serial.print("Power=");
Serial.print(power);
Serial.print(" PLevel=");
Serial.println(peltier_level);
analogWrite(pwmpeltier1, peltier_level); //Write this new value out to the port
analogWrite(pwmpeltier2, peltier_level); //Write this new value out to the port
}
void establishContact() {
while (Serial.available() <= 0) {
Serial.print('A'); // send a capital A
delay(300);
}
}
void setPwmFrequency(int pin, int divisor) {
//change the PWM frequency
byte mode;
if(pin == 5 || pin == 6 || pin == 9 || pin == 10) {
switch(divisor) {
case 1: mode = 0x01; break;
case 8: mode = 0x02; break;
case 64: mode = 0x03; break;
case 256: mode = 0x04; break;
case 1024: mode = 0x05; break;
default: return;
}
if(pin == 5 || pin == 6) {
TCCR0B = TCCR0B & 0b11111000 | mode;
} else {
TCCR1B = TCCR1B & 0b11111000 | mode;
}
} else if(pin == 3 || pin == 11) {
switch(divisor) {
case 1: mode = 0x01; break;
case 8: mode = 0x02; break;
case 32: mode = 0x03; break;
case 64: mode = 0x04; break;
case 128: mode = 0x05; break;
case 256: mode = 0x06; break;
case 1024: mode = 0x7; break;
default: return;
}
TCCR2B = TCCR2B & 0b11111000 | mode;
}
}
I changed the cables, I changed the arduinos, which both had no effect. My only two explanations are the following my serial communication is not robust enough or the PID signal influences the signal quality from the dallas DS 18B20.
Any ideas? I really need a fresh pair of eyes on that.