0

This code is for automatically opening and closing a window using a motor with senors such as dust, humidity, temperature, and rain sensor with bluetooth module through phone. With this code if I press 1,2 it would close or open the window and 3 would let the window open or close regarding the measures that the sensor reads. Right now pressing 3 would only simulate this once and then turn off untill I press it again So I would want this part else if (cmd == '3') to repeat itself until I press another cmd button so the window keeps opening and closing.

//////////////////////////////////////////////////////////////////////////
#include <SoftwareSerial.h>
#include <Stepper.h>
#include <DHT.h>
#define DHTPIN A1
#define DHTTYPE DHT11
#define D_IN 3
#define A_IN A0

int Txpin = 7;
int Rxpin = 8;
int stepsmotor = 1024;
const int stepsPerRevolution = 64;
SoftwareSerial BTSerial(Txpin, Rxpin);
DHT dht(DHTPIN, DHTTYPE);
int measurePin = 0;          // measurePin을 0으로 설정합니다.
int ledPower = 2; // ledPower를 2로 설정합니다.
int samplingTime = 280;    // samplingTime을 280으로 설정합니다.
int deltaTime = 40;           // deltaTime을 40으로 설정합니다.
int sleepTime = 9680;       // sleepTime을 9690으로 설정합니다.
float voMeasured = 0;      // voMeasured를 0으로 설정합니다.
float calcVoltage = 0;       // calcVoltage를 0으로 설정합니다.
float dustDensity = 0;       // dustDensity를 0으로 설정합니다.

Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);

void setup()
{
  Serial.begin(9600);
  BTSerial.begin(9600);
  myStepper.setSpeed(550);  
  pinMode(ledPower,OUTPUT);
  pinMode(D_IN, INPUT);
}

void loop()
{
 if (BTSerial.available())
  {
    char cmd = (char)BTSerial.read();
    if(cmd == '1'){
      for(int i=0; i<(32*3-6); i++){
    myStepper.step(stepsPerRevolution); 
      }}
    else if (cmd == '2')
      for(int i=0; i<(32*3-6); i++){
    myStepper.step(-stepsPerRevolution);
   }
    else if (cmd == '3'){
     int dIn = digitalRead(D_IN);
  double aIn = analogRead(A_IN);
    int h = dht.readHumidity();
    int t = dht.readTemperature();
digitalWrite(ledPower,LOW);                             
  delayMicroseconds(samplingTime);                    

  voMeasured = analogRead(measurePin);             
  delayMicroseconds(deltaTime);                        
  digitalWrite(ledPower,HIGH);                              
  delayMicroseconds(sleepTime);                        

  calcVoltage = voMeasured * (5.0 / 1024.0);        

  dustDensity = (0.17 * calcVoltage - 0.1) * 1000;   



    Serial.print(dustDensity);                             
    Serial.println(" ug/m3");                             
  Serial.print("Digital Input = "); Serial.println(dIn);
  Serial.print("Analog Input  = "); Serial.println(aIn);
  Serial.println();   
    Serial.print("humidity:");          
    Serial.println(h);                
    Serial.print("temperature:");       
    Serial.println(t);                 
    delay(1000);


    if (t >= 25 or h >= 70 or dustDensity >= 100 or aIn <= 50)
     for(int i=0; i<(32*3-6); i++){
    myStepper.step(stepsPerRevolution); 
    }
    else
     for(int i=0; i<(32*3-6); i++){
    myStepper.step(-stepsPerRevolution); 
    }

  delay(3000);
    }
    else if (cmd == '4'){

    }
      }
    }    
  • 1
    Please no code as image. It is difficult to read and nobody will type the code for testing into their own computer. You already had correctly formatted code. Why did you replace it with an image? – chrisl Nov 28 '19 at 8:24
1

I would suggest to rewrite your program as a Finite State Machine (FSM). It's a simple but powerful concept. You first model your program into multiple states, that are connected through state transitions. It is a good way to first draw this as a graph. You can see one example in my answer to this question.

For your case I would use your "modes" as states for the FSM plus an idle state, where simply nothing happens. You would start in the idle stat and then change to different states depending on the Serial input. In the states/modes 1 and 2, which are only one time actions, you would execute the action in the state and then directly change to the idle state again.

From the programming side a FSM can be implemented in multiple ways. I have seen FSMs using a variable and switch cases, but also FSMs, that use a function pointer. The last is elegant, but not as easy to understand for beginners. So I suggest you use the switch-case variant, as you can see in the answer linked above. Basically you use a variable (something like int or char) to represent the current state. In your loop() function you then build a switch-case statement for different values of your state variable. Often an enum is used as variable type to make the code more readable. In each case statement you write the code for the corresponding state. In your state/mode 3 you would check your sensors and close/open the window as needed, then leaving the case statement. When the next iteration of the loop() function happens, the FSM will still be in this state, checking again the sensors. In your states/modes 1 and 2 you would check, if the window already has the needed state and - if not - drive to motor to close/open the window. Then - still in the case statement - you would set the state variable to the idle state, then leave the case statement. So in the next interation of the loop() function the FSM will be in the idle state, doing nothing, making the states/modes 1 and 2 a one-shot everytime, that you activate them.

In contrast to the code in the linked answer, I would read the Serial data outside of the switch statement, since you will write directly to the state variable in there.

I strongly suggest, that you try to implement this. It is an important principle, that makes your more structural sound and easier to extent. A great learning experience.

  • Thanks a bunch! – Jacob Nov 30 '19 at 4:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.