Fan speed control using motion sensor

Hello everybody,

I am a newbie, I'm a student, and l like doing DIY projects.

Currently i'm working on a interactive project, the idea is to create a tornado machine that can be controlled by users. I am sorry is this is a very long post, but I figured it's better to put all three part together instead of three different posts.

The first part:
I am using 3 motion sensors in form of a line with some distance between them. That would detect the presence of a hand that move side to side and each time each sensor detects a presence it would add some percentage to the speed of a fan that is installed on top until fan reaches 80% total capacity. I have the code with all three sensors working fine, now i don't know how to count the detection and use it as an input to control then fan.

The second part:
With every 10 detection, 3 led would light up on LED strip until you reach to the last 3 LEDs. The strip has 30 LED's. I have the same issue here, how illuminate every 3 LEDs with 10 detection.

The third part:

Using two ultra sound sensors on the sides of the object, when we try join our hands together the speed of the fan rises to maximum speed (100%) thus creating a thin tornado. In my code I am measuring the distance between the sensor and the objects to increase or reduce the speed of fan.

I would appreciate any help / suggestions. I have attached the codes that I have made and a picture of my fan a little video if the prototype.

Thank you

Fan_speed_motion_controlled.ino (2.67 KB)

Ultrasound.ino (1003 Bytes)

now i don't know how to count the detection

I'll give you a pencil and some paper (the Arduino has variables and an assignment operator that serve the same purpose). I want you to count every time I whack you. Can you manage that?

how illuminate every 3 LEDs with 10 detection.

if(detectionCount == 10)
{
   litUpLEDCount += 3;
   detectionCount = 0;
}

Then, light up however many LEDs you need to.

In my code I am measuring the distance between the sensor and the objects to increase or reduce the speed of fan.

And the problem is?

I'm sorry, you want me to count every time you whack me?! What is that suppose to mean?

It means he gives you a form of input :wink:

Yes, you shouldn't defend him. I don't need sarcastic forms of inputs, I came here because I didn't know any better. This is not how you should reply to a question, however it seems obvious to you.

Tnx.

Hi,
Welcome to the forum.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html then look down to item #7 about how to post your code.

Please post your code in the post.
It will be formatted in a scrolling window that makes it easier to read.

Thanks.. Tom... :slight_smile:

Sarcasm is what makes life fun :wink:

Now a whack isn't a nice form of input so "count every time I give you candy" would have been nicer but the idea how to handle it is the same :slight_smile:

Some more general tips to create a program:

int PWM = 3;                    // Fan

Call things what they are in the project, not what the hardware is etc. Aka, FanPin.

Extra tip, pick a variable that's large enough to hold what you want (a pin number) but no larger. And if it doesn't change on runtime, make it const.

const byte FanPin = 3; //convention to start a const with a capital, non-const start with a small letter
bool pirState = LOW;             // you only need HIGH/LOW / TRUE/FALSE so a bool will do
int PRI_Right_Pin  = 9;               // PRI input pin

PIR?

int val = 0;                    // variable to read the pin status

It's not mandatory to make every variable a global. In contrary, if you make all variables global you end up with a long list which takes a lot of memory. And for what? You only use val in loop() so define it there. And again, as a bool.

PWMVal = map(val, LOW, HIGH, 26, 255);
analogWrite(PWM, val);

Translation, all you did with PIR lleft and PIR right is ignored and the fan is set to 26 is PRI_Center_Pin is LOW and 255 if it's HIGH.

Making code easier:

 //Print it
  Serial.print(F("Motion "));
  if(val){
    Serial.print(F("detected"));
  }
  else{
    Serial.print(F("ended"));
  }
  Serial.println(F(": Right PRI!"));

And if you have multiple things that are kind of the same an array makes it easier :slight_smile: Because now you do almost the same thing for 3 PIR's. If you put the PIR pins and the led pins in an array you can replace almost everything in the loop with

 for(byte i = 0; i < sizeof(PirPins); i++){
    bool val = digitalRead(PirPins[i]);
    digitalWrite(LedPins[i], val);
    
    //Print it
    Serial.print(F("Pir #"));
    Serial.print(i);
    Serial.print(F(": "));
    if(val){
      Serial.print(F("detected"));
    }
    else{
      Serial.print(F("ended"));
    }
  }

And the most important part when writing code, try to chop it up! What do you want to do and make functions of those steps. For example, all you want to do is

void loop() {
  readPirs();
  updateLeds();
  updateFanSpeed();
}

Next, fill in those functions :slight_smile: And maybe in those functions you have a new step

void readPirs(){
  for(byte i = 0; i < sizeof(PirPins); i++){
    pirStates[i] = digitalRead(PirPins[i]);
    
    debugPrintPirState(i,  pirStates[i]);
  }
}

Which you fill in

void debugPrintPirState(const byte Number, const bool State){
  Serial.print(F("Pir #"));
  Serial.print(Number);
  Serial.print(F(": "));
  if(State){
    Serial.print(F("detected"));
  }
  else{
    Serial.print(F("ended"));
  }
}

Etc until the program is complete :slight_smile:

TomGeorge:
Hi,
Welcome to the forum.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html then look down to item #7 about how to post your code.

Please post your code in the post.
It will be formatted in a scrolling window that makes it easier to read.

Thanks.. Tom... :slight_smile:

Hi,

Thank you for your reply, sure I understand. Perhaps others could read item #13 more carefully as well.

Thank you

septillion:
Sarcasm is what makes life fun :wink:

Now a whack isn't a nice form of input so "count every time I give you candy" would have been nicer but the idea how to handle it is the same :slight_smile:

Some more general tips to create a program:

int PWM = 3;                    // Fan

Call things what they are in the project, not what the hardware is etc. Aka, FanPin.

Extra tip, pick a variable that's large enough to hold what you want (a pin number) but no larger. And if it doesn't change on runtime, make it const.

const byte FanPin = 3; //convention to start a const with a capital, non-const start with a small letter

bool pirState = LOW;            // you only need HIGH/LOW / TRUE/FALSE so a bool will do






int PRI_Right_Pin  = 9;              // PRI input pin



PIR?



int val = 0;                    // variable to read the pin status



It's not mandatory to make every variable a global. In contrary, if you make all variables global you end up with a long list which takes a lot of memory. And for what? You only use val in loop() so define it there. And again, as a bool.



PWMVal = map(val, LOW, HIGH, 26, 255);
analogWrite(PWM, val);



Translation, all you did with PIR lleft and PIR right is ignored and the fan is set to 26 is PRI_Center_Pin is LOW and 255 if it's HIGH.

Making code easier:


//Print it
  Serial.print(F("Motion "));
  if(val){
    Serial.print(F("detected"));
  }
  else{
    Serial.print(F("ended"));
  }
  Serial.println(F(": Right PRI!"));




And if you have multiple things that are kind of the same an array makes it easier :) Because now you do almost the same thing for 3 PIR's. If you put the PIR pins and the led pins in an array you can replace almost everything in the loop with



for(byte i = 0; i < sizeof(PirPins); i++){
    bool val = digitalRead(PirPins[i]);
    digitalWrite(LedPins[i], val);
   
    //Print it
    Serial.print(F("Pir #"));
    Serial.print(i);
    Serial.print(F(": "));
    if(val){
      Serial.print(F("detected"));
    }
    else{
      Serial.print(F("ended"));
    }
  }




And the most important part when writing code, try to chop it up! What do you want to do and make functions of those steps. For example, all you want to do is



void loop() {
  readPirs();
  updateLeds();
  updateFanSpeed();
}



Next, fill in those functions :) And maybe in those functions you have a new step



void readPirs(){
  for(byte i = 0; i < sizeof(PirPins); i++){
    pirStates[i] = digitalRead(PirPins[i]);
   
    debugPrintPirState(i,  pirStates[i]);
  }
}




Which you fill in


void debugPrintPirState(const byte Number, const bool State){
  Serial.print(F("Pir #"));
  Serial.print(Number);
  Serial.print(F(": "));
  if(State){
    Serial.print(F("detected"));
  }
  else{
    Serial.print(F("ended"));
  }
}





Etc until the program is complete :)

Thank you, that's very helpful. I will try to improve.

Hi,

So I have worked on my code for a while and I know it is not efficient this way, but before I jump into arrays I want to make sure the LEDs and fan work fine. I'm not sure about the last part of the code that counts the motions to turn on the LEDs and fan. I have the code only for one sensor for now, then I add the other two.

const int FanPin         = 3;    // Fan negative pin

// PIR input pins
const int PIR_Front_Pin  = 8;
const int PIR_Right_Pin  = 9;               
const int PIR_Center_Pin = 10;
const int PIR_Left_Pin   = 11;


int pirState     = LOW;          // To start with no motion detected, can be 0?
int MotionState  = 0;            // variable to read the pin status
int FanSpeed     = 0;            // Variable to store the the fan RPM coming from fan speed wire
int LastFanSpeed = 0;            // Previous fan RPM

// LED pins
const int Front_ledPin   = 4;
const int Right_ledPin   = 5;         
const int Left_ledPin    = 6;
const int Center_ledPin  = 7;
const int LED_Strip      = 3;

// Variables will change:
int MotionCounter   = 0;       // counter for the number of motions detected
int LastMotionState = 0;       // previous state of the motion

void setup() {
  // PIR sensors
  pinMode(FanPin,         OUTPUT);
  pinMode(PIR_Right_Pin,  INPUT);
  pinMode(PIR_Left_Pin,   INPUT);
  pinMode(PIR_Center_Pin, INPUT);
  // LEDs
  pinMode(Right_ledPin,  OUTPUT);
  pinMode(Left_ledPin,   OUTPUT);
  pinMode(Center_ledPin, OUTPUT);
  pinMode(Front_ledPin,  OUTPUT);
  Serial.begin(9600);

}


void loop() {
 
 // Front sensor
  MotionState = digitalRead(PIR_Front_Pin);  // read input value
  if (MotionState == HIGH) {            // If there is motion
    digitalWrite(Front_ledPin, HIGH);  // turn the front LED ON
    if (pirState == LOW) {
      // That has been switched on
      Serial.println("Motion detected:Front PIR");
      // print the output change, not state
      pirState = HIGH;
    }
  } else {
    digitalWrite(Front_ledPin, LOW); // turn the front LED OFF
    if (pirState == HIGH){
      // That has been switched off
      Serial.println("Motion ended : Front PIR!");
      // print the output change, not state
      pirState = LOW;
    }
  }


 // Right sensor
  MotionState = digitalRead(PIR_Right_Pin);  // read input value
  if (MotionState == HIGH) {                 // If there is motion
    digitalWrite(Right_ledPin, HIGH);        // turn the right LED ON
    if (pirState == LOW) {
      // That has been switched on
      Serial.println("Motion detected:Right PIR");
      // print the output change, not state
      pirState = HIGH;
    }
  } else {
    digitalWrite(Right_ledPin, LOW);        // turn the right LED OFF
    if (pirState == HIGH){
      // That has been switched off
      Serial.println("Motion ended : Right PIR!");
      // print the output change, not state
      pirState = LOW;
    }
  }


// Left sensor
  MotionState = digitalRead(PIR_Left_Pin);  // read input value
  if (MotionState == HIGH) {                // If there is motion
    digitalWrite(Left_ledPin, HIGH);        // turn the left LED ON
    if (pirState == LOW) {
      // That has been switched on
      Serial.println("Motion detected:Left PIR");
      // print the output change, not state
      pirState = HIGH;
    }
  } else {
    digitalWrite(Left_ledPin, LOW);         // turn the left LED OFF
    if (pirState == HIGH){
      // That has been switched off
      Serial.println("Motion ended : Left PIR!");
      // print the output change, not state
      pirState = LOW;
    }
  }


// Center PRI
  MotionState = digitalRead(PIR_Center_Pin);  // read input value
  if (MotionState == HIGH) {                  // If there is motion
    digitalWrite(Center_ledPin, HIGH);        // turn the center LED ON
    if (pirState == LOW) {
      // That has been switched on
      Serial.println("Motion detected:Center PIR");
      // print the output change, not state
      pirState = HIGH;
    }
  } else {
    digitalWrite(Center_ledPin, LOW);         // turn the center LED OFF
    if (pirState == HIGH){
      // That has been switched off
      Serial.println("Motion ended : Center PIR!");
      // print the output change, not state
      pirState = LOW;
    }
  }

 
// read the right PIR pin input pin:
  MotionState = digitalRead(PIR_Right_Pin);

  // compare the motionstate to its previous state
  if (pirState != MotionState) {
    // if the state has changed, increment the counter
    if (pirState == HIGH) {
      // if the current state is HIGH then a motion has been detected
      MotionCounter++;
      Serial.println("Right PIR");
      Serial.print("number of motions detected: ");
      Serial.println(MotionCounter);
    } else {
      // if the current state is LOW then there is no motion
      Serial.println("No Motion detected");
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
  MotionState = pirState;


  // turns on the LED strip with every 10 motions detected by checking the modulo of the
  // motion counter.
  if (MotionCounter % 10 == 0) {
    digitalWrite(LED_Strip, HIGH);    //Do I need a separate pin and variable for each 3 LEDs?
  } else {
    digitalWrite(LED_Strip, LOW);
  }
 
  // To incease the speed of fan by 2.66 % with every detection (Left-right-center)
  if (MotionCounter % 1 == 0) {
     if (FanSpeed < LastFanSpeed)
    digitalWrite(FanPin, HIGH);
  } else {
   
  }
  
}

Maverick_exists_already:
but before I jump into arrays

I would say that's not the best way around. Getting started with arrays takes you 5 minutes and the time saved by it for this project is already more then that :wink:

septillion:
Extra tip, pick a variable that's large enough to hold what you want (a pin number) but no larger.

Try to get into that. Aka

// PIR input pins
const byte PirFrontPin  = 8;
//and
bool pirState     = LOW;          // To start with no motion detected, can be 0?
// PS.LOW and 0 are the same thing :)

Also try to stick with a single naming convention. "Arduino" convention is toUseThisForVariables AndThisForConst.

And a problem in your code, you have to save the previous state PER PIR. Now you compare the current state with the state that was written to pirState by one of the PIRs but you don't know which.

Hi,

So I have made a new sketch with arrays, I'm not good with arrays so please bear with me.

  1. I cannot put the new functions inside void loop:
exit status 1
a function-definition is not allowed here before '{' token
  1. Are my if statements in new functions are correct?
// To illuminate the LEDs
  void updateLeds(){
   if (motionCounter == 10) {
    LedStrip = HIGH;
   }
   else {
    LedStrip = LOW;
   }
   motionCounter = 0;
  }

  // To change fan speed
  void updateFanSpeed(){
     if (motionCounter == 30) {
    FanPin = HIGH;
   }
   else {
    FanPin = LOW;
    
   }
   motionCounter = 0;
  }
  1. I don't understand this function very well, what is F?
void debugPrintPirState(const byte Number, const bool State){
  Serial.print(F("Pir #"));
  Serial.print(Number);
  Serial.print(F(": "));
  if(State){
    Serial.print(F("detected"));
  }
  else{
    Serial.print(F("ended"));
  }
}

And here is the code:

int FanPin       = 2;                // Fan negative pin

// PIR input pins
const int FrontPirPin  = 8;     // Front sensor is only there to initialize the machine. 
const int RightPirPin  = 9;               
const int CenterPirPin = 10;
const int LeftPirPin   = 11;
int PirPins[]= {8,9,10,11};          // The array to hold the PIR pins
int PirPinCount = 4;                 //The number of PIR pins

int pirState     = LOW;              // To start with no motion detected
int motionState  = 0;                // variable to read the pin status
int motionCounter   = 0;             // counter for the number of motions detected
int lastMotionState = 0;             // previous state of the motion
int fanSpeed     = 0;                // Variable to store the the fan RPM coming from fan speed wire
int lastFanSpeed = 0;                // Previous fan RPM

// LED pins
int FrontLedPin   = 4;
int RightLedPin   = 5;         
int LeftLedPin    = 6;
int CenterLedPin  = 7;
int LedStrip      = 3;
int LedPins[]={4,5,6,7};        //The array to hold the LED pins 
int ledPinCount = 5;            // The number of LED pins


void setup() {
  pinMode(LedStrip, OUTPUT);
  pinMode(FanPin, OUTPUT);
  // To initialize each LED pin as output
  int i;
for (int i = 0; i < ledPinCount; i++) {
    pinMode(LedPins[i], OUTPUT);
  }
 // To initialize each PIR pin as output
 int j;
for (int j = 0; j < PirPinCount; j++) {
    pinMode(PirPins[j], OUTPUT);
  }  
}

 // To read the PIRs
  void readPirs() {
  
for(byte i = 0; i < sizeof(PirPins); i++){
    bool motionState = digitalRead(PirPins[i]);
    digitalWrite(LedPins[i], motionState);
  }
 }

  // To debug the PIR pins
  void debugPrintPirState(const byte Number, const bool State){
  Serial.print(F("Pir #"));
  Serial.print(Number);
  Serial.print(F(": "));
  if(State){
    Serial.print(F("detected"));
  }
  else{
    Serial.print(F("ended"));
  }
}

// To illuminate the LEDs
  void updateLeds(){
   if (motionCounter == 10) {
    LedStrip = HIGH;
   }
   else {
    LedStrip = LOW;
   }
   motionCounter = 0;
  }

  // To change fan speed
  void updateFanSpeed(){
     if (motionCounter == 30) {
    FanPin = HIGH;
   }
   else {
    FanPin = LOW;
    
   }
   motionCounter = 0;
  }

  
void loop() {  
   
  }

Please let me know.

Cheers.

Hi,

 // To initialize each PIR pin as output
 int j;
for (int j = 0; j < PirPinCount; j++) {
    pinMode(PirPins[j], OUTPUT);
  }

Shouldn't they be inputs?
Tom... :slight_smile:

tnx, yes I've fixed that already.

  1. Of course not, you declare the function outside and function (including loop()) but you simply call it in loop(). Like digitalRead() is not declared in loop() but you just call it.

  2. Don't know what the LedStrip variable is. If you just want it to be true is motionCounter is 10 then yes. But that's just long for

void updateLeds() {
  LedStrip = motionCounter == 10;
  motionCounter = 0;
}

But I don't think you really want that. At least, that's not what the function name tells. That would suggest writing to the outputs to set/clear the leds you want.

  1. Did you Google it? Otherwise: Arduino Playground - Memory
    Long story short, it saves memory when working with strings.

And for the code, just fill in the names with what it tells. Aka, you first translate your program in human readable statements and jsut add code to that. Aka, you don't expect readPirs() to do digitalWrite() to leds pins. I would assume it reads the current state of the pir and saves it somewhere.

Like I siand in the earlier reply (and extended a bit), what you want to do is:

void loop() {
  //First read the inputs
  readPirs();
  
  //Now we know that, we can check for motion and count it
  checkMotion();

  //Now we know if there is motion and how many, we might want the leds to reflect that
  updateLeds();

  //And the fan speed as well
  updateFanSpeed();
}

Hi,

Thank you for your reply;

  1. Don't know what the LedStrip variable is. If you just want it to be true is motionCounter is 10 then yes. But that's just long for

There is one strip of LEDs in front of the machine that light up like a spectrum analyzer.

There is an open box in front of the machine with the sensors inside, you can make the tornado rise by swinging you hand left to right or inverse. By every x detection we would have more LEDs in front so we know how much we have progressed.

Other issues:

When I print using my code, it prints rapidly because it's inside void loop() and couldn't find a good solution online, and I couldn't make your debug code work.

void debugPrintPirState() {
  int motionState = digitalRead(PirPins[i]);
  if (motionState != lastMotionState);
  Serial.print(F(" Pir "));
  Serial.print(PirPins[i]);
  Serial.print(F(" : "));
  if (motionState = HIGH) {
    Serial.print(F("Detected"));
  }
  else {
    Serial.print(F("Ended"));
  }
  lastMotionState = motionState;
 }

And my void motioncounter() doesnt work, this function merge update LEDs and fan together.

// To illuminate the LEDs and increase the fan speed
void motioncounter() {
// read the PIR array:
  motionState = digitalRead(PirPins[i]);
  // compare the motionstate to its previous state
  if (motionState != lastMotionState) {
    // if the state has changed, increment the counter
    if (motionState == HIGH) {
    // if the current state is HIGH then a motion has been detected
      motionCounter++;
     Serial.print("number of motions detected through : ");
     Serial.print(PirPins[i]);
     Serial.println(motionCounter);
    } else {
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
 
  motionState = lastMotionState;
  

  // turns on the LED strip with every 10 motions detected by checking the modulo of the
  // motion counter.
  if (motionCounter % 50 == 0) {
    digitalWrite(LedStripPin, HIGH);    //Do I need a separate pin and variable for each 3 LEDs?
  } else {
    digitalWrite(LedStripPin, LOW);
  }
 
  // To incease the speed of fan by 2.66 % with every detection (Left-center-Right)
  if (motionCounter % 150 == 0) {
    digitalWrite(FanPin, HIGH);
  } else {
    digitalWrite(FanPin, LOW);
   
  }
}
  if (motionState != lastMotionState);

Can you fine ONE example of properly functioning code that has a ; at the end of an if statement?

How many of the statements that follow this will be executed if the statement (without the ; ) evaluates to true?

  if (motionState = HIGH) {

RTFM. = is NOT the same as ==.

Uhm, snippets are just not working to get to an answer. If you changed code, post it all again.

And yes, you want to check the inputs often in loop() so if you print it every time you check it you get a lot of prints. If you don't want to do that you have to think of when you do want to print it. For example only if the input changed.

And I don't really get what the VU meter needs to display.

But I think it's best to kind of start over. So, first explain what you all want to do. I get you want to drive a fan at different speeds. And you want to increase it every time a hand is waved from left to right or from right to left in front of some PIR sensors. What else?

Also, keep in mind a PIR output stays high some time after motion. You can set this time but it's not precise. Which means not all PIR's will go low after the same amount of time which can upset the detection.

And you somehow shielded the PIR's from other motion? A PIR might not be the easiest sensor to use here.

Hi,

If you don't want to do that you have to think of when you do want to print it. For example only if the input changed

I want to print only when the status of the motion sensor has changed.

And I don't really get what the VU meter needs to display.

It only demonstrate your progress, from 0-100% of fan speed. Moving the hand side to side will create the tornado so to inform the users how far are they from creating the tornado using the fan speed.

But I think it's best to kind of start over. So, first explain what you all want to do. I get you want to drive a fan at different speeds. And you want to increase it every time a hand is waved from left to right or from right to left in front of some PIR sensors. What else?

This should be an interactive object, so the user could make the tornado by moving their hand side to side.

Maybe this video would help: https://youtu.be/2csEvqLb20E

And you somehow shielded the PIR's from other motion?

The PIRs will be lined up inside an open box and they will have a cone shape cover so that they would overlap with each other. I have used ultrasound sensors but that was more difficult to manage.

Here is the schema of the object:

The code:

int FanPin       = 2;                   // Fan negative pin
int i;
int j;

// PIR input pins
const int FrontPirPin  = 8;             // Front sensor is only there to initialize the machine.

//These are only here so that we remember which pin is for which sensor
const int RightPirPin  = 9;
const int CenterPirPin = 10;
const int LeftPirPin   = 11;

int PirPins[] = {9, 10, 11};            // The array to hold the PIR pins
int PirPinCount = 3;                    // The number of PIR pins

int motionState     = 0;                // variable to read the pin status
int motionCounter   = 0;                // counter for the number of motions detected
int lastMotionState = 0;                // previous state of the motion
int fanSpeed        = 0;                // Variable to store the the fan RPM coming from fan speed wire
int lastFanSpeed    = 0;                // Previous fan RPM

// LED pins
int FrontLedPin   = 4;          // Lights up the inside of the machine while there is a user in front

// These LEDs light up inside the gesture box when their correspondent sensor detects movement
int RightLedPin   = 5;
int LeftLedPin    = 6;
int CenterLedPin  = 7;

int LedStripPin      = 3;          // Only lights up with every 10 detections (3 LEDs at a time)
int LedPins[] = {5, 6, 7};      //The array to hold the LED pins
int ledPinCount = 3;            // The number of LED pins


void setup() {
  
  pinMode(LedStripPin, OUTPUT);
  pinMode(FanPin, OUTPUT);
  pinMode(FrontPirPin, INPUT);
  
  // To initialize each LED pin as output
  for (int i = 0; i < ledPinCount; i++) {
    pinMode(LedPins[i], OUTPUT);
  }
  // To initialize each PIR pin as input
  for (int j = 0; j < PirPinCount; j++) {
    pinMode(PirPins[j], INPUT);
  }
  Serial.begin(9600);

}

// To read the PIRs
void readPirs() {

  for (i = 0; i < 3; i++) {int motionState = digitalRead(PirPins[i]);
    
    if (motionState == HIGH) {
      digitalWrite(LedPins[i], HIGH);   // Only the LEDs that are in the gesture box
      lastMotionState = HIGH; 
    }   
    else {
      digitalWrite(LedPins[i], LOW);
      }
      lastMotionState = LOW;
    }
  }


// To debug the PIR pins

void debugPrintPirState() {
  int motionState = digitalRead(PirPins[i]);
  if (motionState != lastMotionState);
  Serial.print(F(" Pir "));
  Serial.print(PirPins[i]);
  Serial.print(F(" : "));
  if (motionState = HIGH) {
    Serial.print(F("Detected"));
  }
  else {
    Serial.print(F("Ended"));
  }
  lastMotionState = motionState;
 }

// To illuminate the LEDs and increase the fan speed
void motioncounter() {
// read the PIR array:
  motionState = digitalRead(PirPins[i]);
  // compare the motionstate to its previous state
  if (motionState != lastMotionState) {
    // if the state has changed, increment the counter
    if (motionState == HIGH) {
    // if the current state is HIGH then a motion has been detected
      motionCounter++;
     Serial.print("number of motions detected through : ");
     Serial.print(PirPins[i]);
     Serial.println(motionCounter);
    } else {
    }
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  // save the current state as the last state, for next time through the loop
 
  motionState = lastMotionState;
  

  // turns on the LED strip with every 10 motions detected by checking the modulo of the
  // motion counter.
  if (motionCounter % 50 == 0) {
    digitalWrite(LedStripPin, HIGH);    //Do I need a separate pin and variable for each 3 LEDs?
  } else {
    digitalWrite(LedStripPin, LOW);
  }
 
  // To incease the speed of fan by 2.66 % with every detection (Left-center-Right)
  if (motionCounter % 150 == 0) {
    digitalWrite(FanPin, HIGH);
  } else {
    digitalWrite(FanPin, LOW);
   
  }
}

void loop() {
  debugPrintPirState();
  readPirs();  
}

Okay, idea is more clear now. Wave your hand, increase speed.

But I do thing ultrasonic sensors would work better. I don't know what the minimum time between retriggering is of those PIR's but most of the time it's more then 5 seconds...

And the VU meter, after each step (12 steps?) it will just adds an extra bar with the relative length of the force? So kind of each bar has a fixed length when on?

First look at the code, variables like i and j NEVER have the right to be global :wink: And delay()'s will just make an less responsive device.

And please start using the smallest possible variable instead of int for everything :wink:

More into detail, you're still not really counting waves. You still try to cram the state of all pirs into the same variable (which will just overwrite it) etc.

First, how to see a wave? That is, the pirs are activated left to right of right to left in order. As a flow diagram:

And I even made some code. It does compile but it's not checked:

const byte FanPin = 2;
const byte PirPins[] = {9, 10, 11}; //left, middle, right
const byte NrPirs = sizeof(PirPins); //number of PIRs

const byte SpeedSteps[] = {0, 50, 100, 150, 200, 250};
const byte NrSpeedSteps = sizeof(SpeedSteps);

const unsigned int TimeoutTime = 2000; //time without motion to reset motion state

//variable to hold the current and last state of the pir
bool pirStates[NrPirs];
bool lastPirStates[NrPirs];

unsigned long lastMotionTime; // last change of the motionState
byte motionState; //current state of the wave

byte waveCount; //number of waves

void setup(){
  for(byte i = 0; i < NrPirs; i++){
    pinMode(PirPins[i], INPUT_PULLUP);
  }
  pinMode(FanPin, OUTPUT);
}

void loop(){
  checkMotion();
  
  updateFanSpeed();
}

bool checkMotion(){
  readPirs();
  
  const bool Dir = motionState & 0x80; //direction is MSB
  const byte LastMotionState = motionState;
  
  //Check to see if we can procede
  switch(motionState & ~0x80){
    //waiting to start
    case 0:
      //did the left or  pir became activated?
      if(pirActivated(0)){
        motionState = 1;
      }
      else if(pirActivated(2)){
        motionState = 1 & 0x80; //MSB indicates  direction aka, we start from the right
      }
    break;
    //waiting for middle
    case 1:
      //if the middle became activated, go to next state
      if(pirActivated(1)){
        motionState++;
      }
    break;
    //waiting for last
    case 2:
      if( (Dir && pirActivated(0)) || (!Dir && pirActivated(2)) ){
        motionState = 0;
        waveCount++;
        
        //reset is max number of waves has passed
        if(waveCount == NrSpeedSteps){
          waveCount = 0;
        }
        
        //debug
        Serial.print(F("WaveCount set to: "));
        Serial.println(waveCount);
      }
    break;
  }
  
  //if state changed, reset the timeout
  if(motionState != LastMotionState){
    lastMotionTime = millis();
    
    //debug
    Serial.print(F("Motion state changed to: "));
    Serial.println(motionState & ~0x80);
    Serial.print(F("Dir: "));
    Serial.println(Dir);
  }
  
  //reset motionState on timeout
  if(millis() - lastMotionTime >= TimeoutTime){
    motionState = 0;
  }
}

void readPirs(){  
  for(byte i = 0; i < NrPirs; i++){
    //save for next time
    lastPirStates[i] = pirStates[i];
    
    //read new value
    pirStates[i] = digitalRead(PirPins[i]);
    
    //if state changed, print it
    if(pirStates[i] != lastPirStates[i]){
      debugPrintPirState(i, pirStates[i]);
    }
  }
}

inline bool pirActivated(byte i){
  return pirStates[i] && (pirStates[i] != lastPirStates[i]);
}

void debugPrintPirState(const byte Number, const bool State){
  Serial.print(F("Pir #"));
  Serial.print(Number);
  Serial.print(F(": "));
  if(State){
    Serial.print(F("detected"));
  }
  else{
    Serial.print(F("ended"));
  }
  Serial.println();
}

void updateFanSpeed(){
  analogWrite(FanPin, SpeedSteps[waveCount]);
}

And I just used some random speed steps etc. But it gives an idea of how to chop up a program into little pieces :slight_smile:

PS The xml is the flow chart to be used with Draw.io

WaveFlow.zip (15.6 KB)