# Pid-relayoutput.ino

**URL:** <https://community.particle.io/t/pid-relayoutput-ino/61600>\
**Category:** Libraries\
**Tags:** argon\
**Created:** [November 30, 2021, 3:26pm UTC](https://community.particle.io/t/pid-relayoutput-ino/61600 "2021-11-30T15:26:37Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tino52](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/tino52/32/16619_2.png) [@Tino52](https://community.particle.io/u/Tino52)\
**Post date:** [November 30, 2021, 3:26pm UTC](https://community.particle.io/t/pid-relayoutput-ino/61600/1 "2021-11-30T15:26:38Z")

</div>

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

```cpp
#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);
}

```

---

<div class="post-metadata">

**Author:** ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)\
**Post date:** [November 30, 2021, 3:37pm UTC](https://community.particle.io/t/pid-relayoutput-ino/61600/2 "2021-11-30T15:37:01Z")

</div>

> [@Tino52](#):
>
> I connected a potentiometer to the input to simulate an analog signal, to pin D0

If you want to read analog signals you should use an A# pin

> [@Tino52](#):
>
> `Input = analogRead(1);`

Also, even if you had the signal connected to D0 why are you not using D0 in this?

---

<div class="post-metadata">

**Author:** ![Tino52](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/tino52/32/16619_2.png) [@Tino52](https://community.particle.io/u/Tino52)\
**Post date:** [November 30, 2021, 3:44pm UTC](https://community.particle.io/t/pid-relayoutput-ino/61600/3 "2021-11-30T15:44:35Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)\
**Post date:** [November 30, 2021, 3:50pm UTC](https://community.particle.io/t/pid-relayoutput-ino/61600/4 "2021-11-30T15:50:14Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![Tino52](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/tino52/32/16619_2.png) [@Tino52](https://community.particle.io/u/Tino52)\
**Post date:** [November 30, 2021, 4:19pm UTC](https://community.particle.io/t/pid-relayoutput-ino/61600/5 "2021-11-30T16:19:00Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)\
**Post date:** [November 30, 2021, 5:21pm UTC](https://community.particle.io/t/pid-relayoutput-ino/61600/6 "2021-11-30T17:21:52Z")

</div>

If you insist

---

<div class="post-metadata">

**Author:** ![Tino52](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/tino52/32/16619_2.png) [@Tino52](https://community.particle.io/u/Tino52)\
**Post date:** [November 30, 2021, 7:09pm UTC](https://community.particle.io/t/pid-relayoutput-ino/61600/7 "2021-11-30T19:09:28Z")

</div>

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

```cpp
#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);
}

```

---

<div class="post-metadata">

**Author:** ![dreamER](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/dreamer/32/26550_2.png) [@dreamER](https://community.particle.io/u/dreamER)\
**Post date:** [November 30, 2021, 8:05pm UTC](https://community.particle.io/t/pid-relayoutput-ino/61600/8 "2021-11-30T20:05:27Z")

</div>

> [@Tino52](#):
>
> `delay(1000);`

Please remove this **`delay()` !**

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.

try something like this:

```auto
Input = analogRead(A1);
Input = map(Input, 0, 4095, 0, 100);
myPID.Compute();

```

Best,

---

<div class="post-metadata">

**Author:** ![Tino52](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/tino52/32/16619_2.png) [@Tino52](https://community.particle.io/u/Tino52)\
**Post date:** [December 1, 2021, 7:56am UTC](https://community.particle.io/t/pid-relayoutput-ino/61600/9 "2021-12-01T07:56:08Z")

</div>

> [@dreamER](#):
>
> ```auto
> Input = analogRead(A1);
> Input = map(Input, 0, 4095, 0, 100);
> myPID.Compute();
> 
> ```

Hello @dreamER  
I made the changes that suggested, due to the variable declarations it throws an error.

```cpp
Input = map (Input, 0, 4095, 0, 100);

```

call of overloaded 'map (double &, int, int, int, int)' is ambiguous

With my limited knowledge I made the following modification as follows:  
On top

```cpp
double val0 = 0;
double val1 = 4095;
double val3 = 100;

```

On `void loop()`

```cpp
Input = analogRead (A1);
Input = map (Input, val0, val1, val0, val3);
myPID.Compute ();

```

but it doesn't work the same, I also removed the delay as indicated, could you tell me which changes to make so that it works?  
Best Valentino

---

<div class="post-metadata">

**Author:** ![Tino52](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/tino52/32/16619_2.png) [@Tino52](https://community.particle.io/u/Tino52)\
**Post date:** [December 1, 2021, 7:58am UTC](https://community.particle.io/t/pid-relayoutput-ino/61600/10 "2021-12-01T07:58:36Z")

</div>

Good morning @ScruffR  
why does your answer remain in edit?  
Thanks Valentino

---

<div class="post-metadata">

**Author:** ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)\
**Post date:** [December 1, 2021, 8:56am UTC](https://community.particle.io/t/pid-relayoutput-ino/61600/11 "2021-12-01T08:56:34Z")

</div>

What do you mean?

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.

---

<div class="post-metadata">

**Author:** ![ScruffR](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/scruffr/32/6952_2.png) [@ScruffR](https://community.particle.io/u/ScruffR)\
**Post date:** [December 1, 2021, 9:07am UTC](https://community.particle.io/t/pid-relayoutput-ino/61600/12 "2021-12-01T09:07:43Z")

</div>

> [@Tino52](#):
>
> call of overloaded ‘map (double &, int, int, int, int)’ is ambiguous

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

```cpp
  Input = map((int)Input, 0, 4095, 0, 100);

```

or

```cpp
  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

```cpp
  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.

Another code streamline would be this  
instead of

```cpp
  if(Output < millis() - windowStartTime) digitalWrite(RelayPin,HIGH);
  else digitalWrite(RelayPin,LOW);
  Serial.print("ValInput: ");Serial.println(Input);

```

I'd write

```cpp
  digitalWrite(RelayPin, millis() - windowStartTime > Output);
  Serial.printf("In: %6.0f, Out: %6.0f, time: %6d \r", Input, Output, millis() - windowStartTime);

```

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

```cpp
#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.

---

<div class="post-metadata">

**Author:** ![Tino52](https://sea2.discourse-cdn.com/flex026/user_avatar/community.particle.io/tino52/32/16619_2.png) [@Tino52](https://community.particle.io/u/Tino52)\
**Post date:** [December 2, 2021, 5:12am UTC](https://community.particle.io/t/pid-relayoutput-ino/61600/13 "2021-12-02T05:12:24Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/particle/original/3X/3/2/3291e3c9351789fe8620ae5bcec8d3fec67ff221.png) [@system](https://community.particle.io/u/system)\
**Post date:** [January 31, 2022, 5:13am UTC](https://community.particle.io/t/pid-relayoutput-ino/61600/14 "2022-01-31T05:13:08Z")

</div>

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.
