Hello
I installed the pid-relayoutput.ino firmware present
in the pid library, I connected a potentiometer to the input to simulate an analog signal, to pin D0 I have a circuit where an optocoupler combined with a relay is connected. I can’t understand how it works. If I simulate with the Tinker application the relay works and opens and closes the contacts.
Someone can give me more info on this firmware (attached).
Valentino
#include "pid.h"
#define RelayPin 2
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,2,5,1, PID::DIRECT);
int WindowSize = 100;
unsigned long windowStartTime;
void setup()
{
Serial.begin(9600);
windowStartTime = millis();
//initialize the variables we're linked to
Setpoint = 100;
//tell the PID to range between 0 and the full window size
myPID.SetOutputLimits(0, WindowSize);
//turn the PID on
myPID.SetMode(PID::AUTOMATIC);
}
void loop()
{
Input = analogRead(1);
myPID.Compute();
/************************************************
* turn the output pin on/off based on pid output
************************************************/
if(millis() - windowStartTime>WindowSize)
{ //time to shift the Relay Window
windowStartTime += WindowSize;
}
if(Output < millis() - windowStartTime) digitalWrite(RelayPin,HIGH);
else digitalWrite(RelayPin,LOW);
Serial.print("ValInput: ");Serial.println(Input);
delay(1000);
}
Hello @ScruffR first time I use I have do A1 and D0 but the firmware don’t work like regulator - controlling.
You write:Also, even if you had the signal connected to D0 why are you not using D0 in this?
as I know temperature control systems there is an input parameter (temp) the specific SW commands and regulates through the firmware the opening and closing of the relay to increase or decrease the temperature.
Best Valentino
Your code is analogRead() ing pin 1 (aka D1) but controlling RelayPin 2 (aka D2) via digitaWrite().
Since your verbal description of the issue neither mention D1 nor D2 but only D0 - which your code is not using anywhere - it’s rather unclear what and why that code looks as it looks.
I apologize I made a writing mistake in my code
there is (#define RelayPin 2) where a relay is connected and the input is A1
(Input = analogRead (1), I checked with Serial.print and even omitting A in the print I see the values change.
Hello
first of all I apologize, I have great respect for all of you who give valid support to the community.
For this I summarize what has already been written also attaching the firmware again.
So I connected a potentiometer to A1 to simulate an analog input signal to pin D2 a relay is connected via optocoupler.
If the entry signal varies, I suggest that the relay should open and close the contacts. I tested output D2 via Tinker and the relay works. In the skecht I inserted a Serial.print to verify that the input signal varies by acting on the potentiometer, as well as I put the display of the output value of D2.
Best Regards
Valentino
#include "pid.h"
#define RelayPin D2
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,2,5,1, PID::DIRECT);
int WindowSize = 5000;
unsigned long windowStartTime;
void setup()
{
Serial.begin(9600);
windowStartTime = millis();
//initialize the variables we're linked to
Setpoint = 100;
//tell the PID to range between 0 and the full window size
myPID.SetOutputLimits(0, WindowSize);
//turn the PID on
myPID.SetMode(PID::AUTOMATIC);
}
void loop()
{
Input = analogRead(A1);
myPID.Compute();
/************************************************
* turn the output pin on/off based on pid output
************************************************/
if(millis() - windowStartTime>WindowSize)
{ //time to shift the Relay Window
windowStartTime += WindowSize;
}
if(Output < millis() - windowStartTime) digitalWrite(RelayPin,HIGH);
else digitalWrite(RelayPin,LOW);
Serial.print("ValInput: ");Serial.println(Input);
delay(1000);
}
All PID regulator members are time based.
how do you expect that his is gonna work ? when you block entire PID for 1s at every loop ?
also your setpoint is set to 100
and your analogRead() is from 0 to 4095 (from 0 to 3.3V respectively)
so consider to use map() functionality as when you connect just a pot. to A1 and 3.3V
the value of 100 will be reached right after you just touch the pot.
If you are referring to a notification that your post was edited, then this comes from my re-formatting of your posts.
You keep wrapping your verbal part of the post in a pre-formatted text block which isn’t meant for that but for code blocks. Hence I keep moving the verbal part of your posts out of that block.
When having it inside the block your @ pings will not work nor word wrapping work - among other things like “misguided” text formats.
There are two versions of map(): One takes all integers and the other all doubles. Since you are passing in a mix of that the compiler doesn't know which to take.
To solve that issue, you need to clarify either as
Input = map((int)Input, 0, 4095, 0, 100);
or
Input = map(Input, 0.0, 4095.0, 0.0, 100.0);
(adding the .0 makes clear to the compiler that the number literals are to be taken as floating point values)
However, I'd write that part like this anyhow
Input = map(analogRead(A1), 0, 4095, 0, 100);
BTW, can you tell us, how you are testing whether the relay gets controlled correctly or not?
How are you "twiddling" the potentiometer?
With a setpoint of 100 and a max value of 100 you still haven't got a lot of wiggle room.
Without map() you only had very little wiggle room on the low end of the potentiometer and with it but both values at the top end you have no wiggle room at all at the top.
The former version probably had the relay mostly off and the current version mostly/always on I'd suspect.
The extra data in the Serial.print() statement should also provide some more insight into what's going on
You are also missing pinMode(RelayPin, OUTPUT) in setup().
Here is some code to try
#include "pid.h"
const int pinRelay = D7; // use onboard LED as visual feedback for the relay state
const int pinTempSensor = A0; // potentiometer pin
const uint32_t msTimeFrame = 5000;
bool localRead = true; // take reading from potentiometer
uint32_t msStart;
double setPoint;
double input;
double output;
PID myPID(&input, &output, &setPoint, 2, 5, 1, PID::DIRECT);
void setup() {
Particle.function("newSetPoint", newSetPoint);
Particle.function("newTemp", newTemp);
pinMode(pinRelay, OUTPUT);
pinMode(pinTempSensor, INPUT);
setPoint =
input = 100; // start off mid range and on target
msStart = millis();
myPID.SetOutputLimits(0, msTimeFrame);
myPID.SetMode(PID::AUTOMATIC);
}
void loop() {
if (localRead) // when required, read potentiometer
input = map(analogRead(pinTempSensor), 0, 4095, 0, 200);
myPID.Compute();
if(millis() - msStart > msTimeFrame) // reached end of time frame
msStart += msTimeFrame; // shift forward
digitalWrite(pinRelay, (output < (millis() - msStart)));
Serial.printf("In: %6.0f, Out: %6.0f, time: %6d %c \r", input, output, millis() - msStart, digitalRead(pinRelay) ? '+' : '-');
}
int newSetPoint(String arg) {
setPoint = arg.toFloat();
return setPoint;
}
int newTemp(String arg) {
input = arg.toFloat();
localRead = (input <= 0); // values <= 0 replace remote value with local potentiometer reading
return input;
}
Here you can set the setPoint via a Particle.function().
The current state (input) can either be set remotely via another Particle.function() or via the potentiometer on A0 when you set the remote input to anything less or equal to zero (= initial condition).
The relay goes to D7 where the onboard LED also indicates the output state.
To view the serial output I'd recommend particle serial monitor --follow to see a steady line permanently disclosing the internal state of the program.
Hello @ScruffR thanks for the suggestion, soon I’ll try then until tomorrow it will not be possible for me to run tests and leave any feedback in the community.
Good day
Valentino