I want to write a program to activate 5 relays connected to 5 solenoid valves based on a particular logic.
These relays are to be turned-on in specific intervals.
I am using Mega 2560. How do i set arduino pins high and low at different timings.
Please.
This can be extremely simple. I suggest you slow your roll a bit and work through the simple basic programs from the examples in the IDE.
Then give it a whirl. You could use LEDs to experiment instead of “real” solenoids.
Show us what you got working, or why you can’t make what you write work.
You can get help walking here, and running, too, but you kinda have to stand up on two feet youself first.
a7
#include "MCUFRIEND_kbv.h"
#include "TouchScreen.h"
#include "Adafruit_GFX.h"
MCUFRIEND_kbv tft;
#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
#define LCD_RESET A4
#define MINPRESSURE 200
#define MAXPRESSURE 1000
const int XP = 6, XM = A2, YP = A1, YM = 7; //240x320 ID=0x3229
const int TS_LEFT = 864, TS_RT = 195, TS_TOP = 76, TS_BOT = 895;
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
TSPoint tp;
Adafruit_GFX_Button sub_btn, add_btn;
int pixel_x, pixel_y;
bool Touch_getXY()
{
TSPoint p = ts.getPoint();
pinMode(YP, OUTPUT);
pinMode(XM, OUTPUT);
digitalWrite(YP, HIGH);
digitalWrite(XM, HIGH);
bool pressed = (p.z > MINPRESSURE && p.z < MAXPRESSURE);
if (pressed) {
pixel_x = map(p.x, TS_LEFT, TS_RT, 0, tft.width());
pixel_y = map(p.y, TS_TOP, TS_BOT, 0, tft.height());
}
return pressed;
}
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
int motor = 45;
int volt = 0;
int diff = 10;
int test = 53;
int V1;
int V2;
int a = 0;
int b = 0;
int c = 0;
long int time1;
long int time2;
long int interval;
void setup()
{
Serial.begin(9600);
uint16_t ID = tft.readID();
tft.reset();
tft.begin(0x3229);
tft.setRotation(0);
tft.setCursor(38, 5);
tft.setTextColor(WHITE);
tft.setTextSize(2);
tft.print("PRECISION");
tft.setCursor(13, 25);
tft.setTextColor(WHITE);
tft.setTextSize(2);
tft.print("PRODUCTS PVT. LTD.");
/*tft.setCursor(80, 35);
tft.setTextColor(WHITE);
tft.setTextSize(2);
tft.print("PVT. LTD.");*/
tft.setCursor(70, 50);
tft.setTextColor(WHITE, RED);
tft.setTextSize(3);
tft.print("Oxygen");
tft.setCursor(12, 80);
tft.setTextColor(WHITE, RED);
tft.setTextSize(3);
tft.print("Concentrator");
sub_btn.initButton(&tft, 37, 150, 70, 40, WHITE, CYAN, BLACK, "-", 3);
add_btn.initButton(&tft, 203, 150, 70, 40, WHITE, CYAN, BLACK, "+", 3);
sub_btn.drawButton(false);
add_btn.drawButton(false);
pinMode(motor, OUTPUT);
pinMode(31, INPUT);
pinMode(33, INPUT);
pinMode(35, OUTPUT);
pinMode(37, OUTPUT);
digitalWrite(35, HIGH);
digitalWrite(37, HIGH);
}
void loop()
{
bool down = Touch_getXY();
sub_btn.press(down && sub_btn.contains(pixel_x, pixel_y));
add_btn.press(down && add_btn.contains(pixel_x, pixel_y));
if (sub_btn.justReleased())
sub_btn.drawButton();
if (add_btn.justReleased())
add_btn.drawButton();
if (sub_btn.justPressed()) {
sub_btn.drawButton(true);
if (volt > 0) volt = volt - diff;
Serial.print("no");
}
if (add_btn.justPressed()) {
add_btn.drawButton(true);
if (volt < 245) volt = volt + diff;
Serial.print("yes");
}
tft.setCursor(72, 135);
tft.setTextColor(TFT_RED, TFT_BLACK);
tft.setTextSize(4);
tft.print(volt);
tft.print(" ");
analogWrite(53, 25);
int pressureValue = analogRead(44);
// Convert the analog reading (which goes from 0 - 1023) to a voltage (0 - 5V):
float pressure = pressureValue * (5.0 / 1023.0);
tft.setCursor(70, 250);
tft.setTextColor(TFT_RED, TFT_BLACK);
tft.setTextSize(4);
tft.print(interval);
analogWrite(motor, volt);
V1 = digitalRead(31);
V2 = digitalRead(33);
if (a < 1 & V1 == HIGH & V2 == LOW) {
Serial.println("Time1");
time1 = millis();
Serial.println(time1);
a++;
}
if (b < 1 & V2 == HIGH & V1 == LOW) {
Serial.println("Time2");
time2 = millis();
Serial.println(time2);
interval = time2 - time1;
Serial.println(interval);
b++;
}
}
This is what I have written till now. The code consists of some text, number value with inc/dec touch buttons, time value between two inputs. But how do I keep turning on and off outputs continuously, following a particular sequence. Should I use millis function?
here is a demo-code that shows the principle of non-blocking timing.
If you find this code difficult to understand please read the tutorials about timing with millis()
These tutorials use more words to explain in detail how it works
unsigned long currentMillis;
unsigned long Period = 1000; // after 1000 milliseconds a "period" has passed by
unsigned long LastTime_Period_Elapsed;
unsigned long SlowDownPeriod = 20; // print a new character every 20 milliseconds so your eyes can follow the serial-output
unsigned long LastTime_SlowDownPeriod_Elapsed;
unsigned long DoubleCrossPeriod = 5 * SlowDownPeriod; // every 5th character shall be a #
unsigned long LastTime_DoubleCrossPeriod_Elapsed;
int NumberOfElapsedPeriods = 0;
const char dot = '.';
const char doubleCross = '#';
char CharToPrint;
void setup() {
Serial.begin(115200);
LastTime_Period_Elapsed = millis();
LastTime_SlowDownPeriod_Elapsed = millis();
LastTime_DoubleCrossPeriod_Elapsed = millis();
}
void loop() { // main-loop is running at high speed
currentMillis = millis(); // update timing-variable each time the main-loop starts again
visualiseLooping(); // this function gets called with every run of the loop
// but contains logic to execute parts of its code
// only if a certain amount of time has passed by
// this part shows the same principle check if a certain amount of time has passed by
// if yes execute commands inside the if-condition
// the variable period contains the number of milliseconds
// if THIS number of milliseconds has passed by the if-condition becomes true
// ==> the code inside the if-condition is executed
if (currentMillis - LastTime_Period_Elapsed >= Period) {
LastTime_Period_Elapsed = currentMillis; // first thing to do is updating this variable
NumberOfElapsedPeriods ++;
Serial.println();
Serial.print(NumberOfElapsedPeriods);
Serial.println(" period is over");
}
}
// every time a certain amount of time has passed by a character is printed to the serial monitor
// for your application you just put your code that shall be executed in such a timing-pattern
// inside the if-condition that checks the time that has passed by
void visualiseLooping() {
if (currentMillis - LastTime_DoubleCrossPeriod_Elapsed >= DoubleCrossPeriod) {
LastTime_DoubleCrossPeriod_Elapsed = currentMillis;
CharToPrint = doubleCross;
}
else {
CharToPrint = dot;
}
if (currentMillis - LastTime_SlowDownPeriod_Elapsed >= SlowDownPeriod) {
LastTime_SlowDownPeriod_Elapsed = currentMillis;
Serial.print(CharToPrint);
}
}
best regards Stefan
But how do I keep turning on and off outputs continuously, following a particular sequence.
is a still more or less unprecise description of what should happen.
Best thing would be to draw a diagram that has a line for each of your 5 channels and the diagram shows an example
how all these five channels shall switch ON/OFF
Add information if all channels should work independent of each other or if you want to have the channels be in some kind of synchronisation like "each time channel 3 switches OFF channel 1 shall switch ON after an additional time of x seconds
best regards Stefan
#include "MCUFRIEND_kbv.h"
MCUFRIEND_kbv tft;
unsigned long Period = 1000;
unsigned long currentMillis;
unsigned long current_RF;
unsigned long lasttime_RF;
unsigned long current_LW;
unsigned long lasttime_LW;
bool RF = 0;
bool LW = 0;
bool LF = 0;
bool RW = 0;
bool EQ = 1;
bool SR1 = 0;
bool SR2 = 0;
void setup() {
tft.begin(0x3229);
tft.setRotation(0);
tft.fillScreen(TFT_BLACK);
Serial.begin(9600);
currentMillis = millis();
tft.fillRect(205, 260, 40, 40, TFT_GREEN);
}
void loop()
{
RFLW ();
}
void RFLW ()
{
current_RF = millis();
if (RF == 0 & LW == 0 & LF == 0 & RW == 0 & EQ == 1 & current_RF - currentMillis >= Period * 2) {
RF = 1;
tft.fillRect(5, 260, 40, 40, TFT_GREEN);
Serial.println("RF=ON");
}
if (RF == 1 & LW == 0 & LF == 0 & RW == 0 & EQ == 1 & SR1 == 0 & current_RF - currentMillis >= Period * 3) {
LW = 1;
tft.fillRect(55, 260, 40, 40, TFT_GREEN);
EQ = 0;
tft.fillRect(205, 260, 40, 40, TFT_RED);
Serial.println("LW=ON");
SR1 = 1;
}
if (RF == 1 & LW == 1 & LF == 0 & RW == 0 & EQ == 0 & current_RF - currentMillis >= Period * 4) {
EQ = 1;
tft.fillRect(205, 260, 40, 40, TFT_GREEN);
Serial.println("EQ=ON");
}
if (LW == 1 & RF == 1 & LF == 0 & RW == 0 & EQ == 1 & SR1 == 1 & current_RF - currentMillis >= Period * 5) {
LW = 0;
tft.fillRect(55, 260, 40, 40, TFT_RED);
Serial.println("LW=OFF");
}
if (LW == 0 & RF == 1 & LF == 0 & RW == 0 & EQ == 1 & current_RF - currentMillis >= Period * 6) {
RF = 0;
tft.fillRect(5, 260, 40, 40, TFT_RED);
LF = 1;
tft.fillRect(105, 260, 40, 40, TFT_GREEN);
Serial.println("RF=OFF");
}
if (LW == 0 & RF == 0 & LF == 1 & RW == 0 & EQ == 1 & SR2 == 0 & current_RF - currentMillis >= Period * 7) {
RW = 1;
tft.fillRect(155, 260, 40, 40, TFT_GREEN);
EQ = 0;
tft.fillRect(205, 260, 40, 40, TFT_RED);
Serial.println("EQ=OFF");
SR2 = 1;
}
if (RF == 0 & LW == 0 & LF == 1 & RW == 1 & EQ == 0 & current_RF - currentMillis >= Period * 8) {
EQ = 1;
tft.fillRect(205, 260, 40, 40, TFT_GREEN);
Serial.println("LW=ON");
}
if (LW == 0 & RF == 0 & LF == 1 & RW == 1 & EQ == 1 & SR2 == 1 & current_RF - currentMillis >= Period * 9) {
RW = 0;
tft.fillRect(155, 260, 40, 40, TFT_RED);
Serial.println("RW=OFF");
}
if (LW == 0 & RF == 0 & LF == 1 & RW == 0 & EQ == 1 & current_RF - currentMillis >= Period * 10) {
LF = 0;
tft.fillRect(105, 260, 40, 40, TFT_RED);
Serial.println("LF=OFF");
current_RF = 0;
currentMillis = millis();
SR1 = 0;
SR2 = 0;
}
}
This is what I've written.
It works but are there better ways to write this code? Easier and efficient.
I'm wondering that your code is working because you use the bitwise AND-operator "&" a single "&"
usially in if-conditions thet check for multiple conditions like
(RF == 0 & LW == 0
the logical AND "&&" a double "&&" is used.
so your if-condition would look like this
if (RF == 0 && LW == 0 && LF == 0 && RW == 0 && EQ == 1 && current_RF - currentMillis >= Period * 2) {
a comparison like "RF == 0" results in true or false. As your variables are of type boolean you can use
the variables itself and in case of 0 with the not-operator
if (!RF && !LW && !LF && !RW && EQ && (current_RF - currentMillis >= Period * 2) ) {
The timing-pattern is mutliples of period. This could be coded with using arrays which would shorten the code
but is harder to read and understand.
More efficient to maintain is using self-explaining names. If you want to modify this code in half a year or later
I estimate you have difficulties to remember what was "RF" for?? what was "EQ" for ??
Your brain has to do a lot of additional translations instead of reading a selfexplaining name
It works to assign boolean variables the integernumbers 0 and 1.
Usually the are assigned true and false which indicates that the variable is of type boolean so you don't have to look up the variable type
best regards Stefan
Thankyou Stefan.
I used single "&" and its working correctly.
I'll modify the code and get back if needed.
Once again thank you.