element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Design For A Cause 2021
  • Challenges & Projects
  • Design Challenges
  • Design For A Cause 2021
  • More
  • Cancel
Design For A Cause 2021
Blog VenTTracker #03 -  Analyzing window types II
  • Blog
  • Forum
  • Documents
  • Polls
  • Files
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: javagoza
  • Date Created: 21 Mar 2021 8:10 PM Date Created
  • Views 1217 views
  • Likes 8 likes
  • Comments 2 comments
  • venttracker
  • home automatisation
  • covid-19
  • school
  • design for a cause
  • arduino nano 33 iot
Related
Recommended

VenTTracker #03 -  Analyzing window types II

javagoza
javagoza
21 Mar 2021

This is the continuation of last week's blog where I began to analyze strategies to be able to monitor the status of windows, doors, blinds and shutters.

During this week I do some tests on last week's ideas on sliding elements and I analyze strategies for pivoting elements.

 

image

  Design for A Cause 2021 the VenTTracker project

  01 - Intro and motivation. | 02 - Analyzing Window Types (I) | 03 - Analyzing Window Types (II) | 04 - Playing with the IMU | 05-Sliding Window Mock-up | 06 -  Window Sensor Prototype | 07 - Adjusting the window sensor | 08 - Trying to make a measuring device with the accelerometer | 09 - Checking and updating WiFiNINA Firmware | 10 - Ventilation Monitor on Arduino IoT Cloud | 11 - Wireless Environmental Monitor on Arduino Nano 33 IoT | 12 - Window Anomaly Detection. Edge Impulse & Arduino Nano 33 IoT | 14 - Environmental Monitor Revisited - Version 2 | 13 - Project wrap-up and Lessons learned

 

Tracking System for Classroom Ventilation Routines

A STEM project for classrooms

 

the VenTTracker project - Blog #03 - Analyzing Window Types II

imageimageimage

Testing ideas for monitoring sliding elements

 

The first tests with the design developed last week have not been entirely satisfactory. Initially, it was intended to be able to use only two reed switch sensors, but it complicates the software design quite a bit if we want to use multithreading with interruptions. So we go back to the original idea of a sensor for closing and opening detection and we made it independent from detecting the relative position of the element.

 

This was the previous version:

  • Two Reed Switch Sensors Aligned with pull down resistors and positive logic.

 

image

 

And this is the new version:

image

image

In the new version:

  • We can no longer detect the closing position. Although the encoder could try to detect the closed position through the relative position, since there is no absolute reference we cannot know if it is closed or not. We have to delegate the problem of detecting the closed position to a new sensor.
  • The sensors are no longer aligned. Being aligned, and not being exactly the same, caused them not to switch at the right time.
  • We change the ports that the sensors connect to. Now there are two ports that support interruptions to allow us to work with multithreading.
  • We add two LEDs for debugging.
  • We removed the pull down resistors from the old version switches and replaced them with two internal 20K pull up resistors from the microcontroller.
  • This makes the logic of the switches in our design now negative. Low when the switch is closed and High when the switch is open.

 

Building an encoder model for testing

 

Let's build a real model for testing and see if our design works.

 

Parts

#Part
1Arduino Nano 33 IOT
2100Ω Resistor
2TILT-SWITCH-SW-200D
4MAGNET
2Red LED

 

Connections:

Arduino Nano 33 IoTComponent
10Left Reed Switch. Other end to ground.
9Right Reed Switch. Other end to ground.
8Left Red LED. With a 100Ω Resistor to ground.
7Right Red LED. With a 100Ω Resistor to ground.

 

The pins below can be used with attachInterrupt() on Nano 33 IoT.

We are going to use pins 9 and 10:

 

BOARDDIGITAL PINS USABLE FOR INTERRUPTS
Nano 33 IoT2, 3, 9, 10, 11, 13, 15, A5, A7

Arduino Nano 33 IoT Pinout:

image

 

Checking encoder signals.

image

 

The video shows the signals at the two switch sensors

 

image

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

 

As seen in the video we will need a low pass filter to avoid bouncing on the switches.

image

 

Zooming:

 

image

 

Coding a busy simple encoder.

 

Let's code a simple encoder without interrupts.

 

/*
  Test Reed Switch Quadrature Encoder
  @author Enrique Albertos
  @link https://www.element14.com/community/community/design-challenges/design-for-a-cause-2021/

*/

// Port connections
int leftSwitchPort = 10; // switch to ground + internal pull-up resistor. Negative logic LOW when switch is closed  
int rightSwitchPort = 9;  // switch to ground + internal pull-up resistor. Negative logic LOW when switch is closed  
int leftLedPort = 8; // positive logic. HIGH turn on the LED  
int rightLedPort = 7; // positive logic. HIGH turn on the LED  

void setup() {
  // set port switches with internal 20K pull up resistors
  pinMode (leftSwitchPort, INPUT_PULLUP);
  pinMode (rightSwitchPort, INPUT_PULLUP);

  // set debugging LEDs ports
  pinMode (leftLedPort, OUTPUT);
  pinMode (rightLedPort, OUTPUT);
  
  Serial.begin (9600);
  delay(1000); // wait for serial port
}

void loop() {
  static int encoderPosition = 0;
  static int leftSwitchPortLast = LOW;
  // switches are in negative logic. Negate
  int leftSwitchState = !digitalRead(leftSwitchPort);
  int rightSwitchState = !digitalRead(rightSwitchPort);
  
  // Light leds for debugging
  digitalWrite(leftLedPort, leftSwitchState);
  digitalWrite(rightLedPort, rightSwitchState);
  if ((leftSwitchPortLast == LOW) && (leftSwitchState == HIGH)) {
    if (rightSwitchState == LOW) {
      encoderPosition++;
    } else {
      encoderPosition--;
    }
     Serial.println(encoderPosition);
  }
  leftSwitchPortLast = leftSwitchState;
  // debouncing switches
  delay(20);
}

 

When the code finds a low-to-high transition on the leftSwitchState , it checks to see if the rightSwitchState  channel is high or low and then increments/decrements the counter with the encoderPosition. By now the encoder position is a relative position. We will need to add an absolute reference position to calibrate our encoder.

 

This is the serial output going right to left and left to right with the magnet.

 

image

 

Going multithreading

 

Let's try now with interrupts

 

Interrupts and ISR

We want to ensure that our program always caught the pulses from our encoder, so that it never misses a pulse. With the above code it would make very tricky to do anything else, because the program would need to constantly poll the sensor lines for the encoder, in order to catch pulses when they occurred.

Using an interrupt can free the microcontroller to get some other work done while not missing the input.

To make sure variables shared between the Interrupt Service Routine (ISR) and the main program are updated correctly, we declare them as volatile.

Declaring a variable volatile is a directive to the compiler. It directs the compiler to load the variable from RAM and not from a storage register, which is a temporary memory location where program variables are stored and manipulated. Under certain conditions, the value for a variable stored in registers can be inaccurate.

 

Some notes about the code

In this revision of our code we will use the LEDS for monitoring the detected direction. Left LED will turn on when last direction detected is to the left and the Right LED will turn on when the last direction detected is to the right.

ISR should be as short and fast as possible so we will use events to notify changes.

We are interested in only one of the four possible transitions. We will detect only falling edges in left switch. We'll detect falling edges as the switch logic is negative. When falling edge the switch transitions from open to closed.

 

/*
  Test Reed Switch Quadrature Encoder 02 With interrupts
  @author Enrique Albertos
  @link
  https://www.element14.com/community/community/design-challenges/design-for-a-cause-2021/

*/

// Port connections
int leftSwitchPort = 10; // switch to ground + internal pull-up resistor. Negative logic LOW when switch is closed  
int rightSwitchPort = 9;  // switch to ground + internal pull-up resistor. Negative logic LOW when switch is closed  
int leftLedPort = 8; // positive logic. HIGH turn on the LED  
int rightLedPort = 7; // positive logic. HIGH turn on the LED  


typedef enum direction_t  {RIGHT = 0x00, LEFT = 0xFF};
volatile direction_t lastWindowDirection = LEFT;

volatile int8_t encoderPosition = 0; // don't know where is our encoder, we'll need an absolute reference
                                     // let's assume we are in closed position and window opens from left to right
volatile bool encoderChangePending = false;
unsigned long lastLeftSwitchDebounceTime = 0;  // the last time the input left encoder pin was toggled
unsigned long debounceDelay = 50;    // the debounce time


void isrFallingLeftSwitchPort(); // ISR for leftSwitchPort

void setup() {
  // set port switches with internal 20K pull up resistors
  pinMode(leftSwitchPort, INPUT_PULLUP);
  pinMode(rightSwitchPort, INPUT_PULLUP);

  // detect falling edges the switch chages from open to closed. It is negative logic
  attachInterrupt(digitalPinToInterrupt(leftSwitchPort),
                  isrFallingLeftSwitchPort, FALLING);

  // set debugging LEDs ports
  pinMode(leftLedPort, OUTPUT);
  pinMode(rightLedPort, OUTPUT);

  Serial.begin(9600);
  delay(1000); // wait for serial port
}

void loop() {
  if (encoderChangePending) {
    encoderChangePending = false;
    // turn on left led when window direction is LEFT
    digitalWrite(leftLedPort, lastWindowDirection == LEFT );
     // and turn on right led when window direction is RIGHT
    digitalWrite(rightLedPort, lastWindowDirection == RIGHT );
    // log encoder position to serial port
    Serial.println(encoderPosition);
  }
}
/**
* Interrupt Service Routine for Falling Edge in Left Switch Port
*/
void isrFallingLeftSwitchPort() {
  if ((millis() - lastLeftSwitchDebounceTime) > debounceDelay) {
    if (digitalRead(rightSwitchPort) == HIGH) {
      encoderPosition++;
      lastWindowDirection = RIGHT;
    } else {
      encoderPosition--;
      lastWindowDirection = LEFT;
    }
  lastLeftSwitchDebounceTime = millis();
  encoderChangePending = true;
  }
}

 

The new encoder in action.

 

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

Strategies for Casement Windows and Doors

 

For casement windows we are going to start using the accelerometer and the gyroscope. We build a small model to simulate the orientation of the window or door from closed to open.

A priori the results are good but the position obtained oscillates in the stop situation. This is going to require us to filter the data. It will not be a problem since our requirements for the position are not strict at all.

 

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

 

Testing Casement Window and Door Orientation with LSM6DS3 IMU and Madgwick filter

Arduino code

/*
  Testing Casement Window and Door Orientation with Arduino nano 33 IoT LSM6DS3 IMU and Madgwick filter
  @author Enrique Albertos
  @link https://www.element14.com/community/community/design-challenges/design-for-a-cause-2021/

*/

#include <Arduino_LSM6DS3.h>
#include <MadgwickAHRS.h>

Madgwick filter;

void setup() {
  Serial.begin(9600);
  delay(1000);
  // start the IMU and filter
  if (!IMU.begin()) {
    Serial.println("Failed to initialize IMU!");
    while (1);
  }
  filter.begin(IMU.accelerationSampleRate());
}

void loop() {
  float  aix, aiy, aiz;
  float gix, giy, giz;
  float roll, pitch, heading;

  // read raw data from IMU
  if (IMU.accelerationAvailable() && IMU.gyroscopeAvailable()) {
    IMU.readAcceleration(aix, aiy, aiz);
    IMU.readGyroscope(gix, giy, giz);
    filter.updateIMU(0, giy, 0, 0, aiz, 0);
    heading = -filter.getYaw();
    Serial.print("Orientation: ");
    Serial.println(heading);
  }

}

 

For visualization in Windows we are using a java Processing script

 

/**
   Testing Casement Window and Door Orientation with Arduino nano 33 IoT LSM6DS3 IMU and Madgwick filter
  Processing 3D Visualizer
   @author Enrique Albertos
   @link https://www.element14.com/community/community/design-challenges/design-for-a-cause-2021/
*/
import processing.serial.*;
Serial myPort;
 float yaw = 0.0;
 void setup()
{
  size(1200, 1000, P3D);
  myPort = new Serial(this, "COM4", 9600);  
  textSize(16); // set text size
  textMode(SHAPE); // set text mode to shape
}

void draw()
{
  serialEvent();  // read and parse incoming serial message
  background(255); // set background to white
  lights();
   translate(width/2, height/2); // set position to centre
   pushMatrix(); // begin object
   float c1 = cos(radians(0));
  float s1 = sin(radians(0));
  float c2 = cos(radians(0));
  float s2 = sin(radians(0));
  float c3 = cos(radians(yaw));
  float s3 = sin(radians(yaw));
  applyMatrix( c2*c3, s1*s3+c1*c3*s2, c3*s1*s2-c1*s3, 0,
               -s2, c1*c2, c2*s1, 0,
               c2*s3, c1*s2*s3-c3*s1, c1*c3+s1*s2*s3, 0,
               0, 0, 0, 1);

  drawCasementWindow();
   popMatrix(); // end of object
   // Print values to console
  print(yaw);
  println();
}

void serialEvent()
{
  int newLine = 13; // new line character in ASCII
  String message;
  do {
    message = myPort.readStringUntil(newLine); // read from port until new line
    if (message != null) {
      String[] list = split(trim(message), " ");
      if (list.length >= 2 && list[0].equals("Orientation:")) {
        yaw = float(list[1]); // convert to float yaw
      }
    }
  } while (message != null);
}

void drawCasementWindow()
{
  translate(0, 0, 100); 
  stroke(255, 255, 255);
  fill(250, 250, 250); 
  box(10, 300, 200); 
  stroke(90, 90, 0);
  fill(180, 180, 0); 
  translate(0, 0, -100); 
  box(10,300,20);
  stroke(90, 90, 0);
  fill(180, 180, 0);
  translate(0, 0, 200); 
  box(10,300,20); 
  stroke(90, 90, 0);
  fill(180, 180, 0);
  translate(0, 150, -100); 
  box(10,20,200); 
  stroke(90, 90, 0);
  fill(180, 180, 0);
  translate(0, -300, 0); 
  box(10,20,200);  
}

 

Next steps

 

  • Design and build a mockup to simulate the behavior with the sliding parts.
  • Investigate what ML can contribute to our goals.
  • Create a game to get familiar with the accelerometer and have fun along the way.

 

VenTTracker Blogs
VenTTracker #01 - Intro and motivation.
VenTTracker #02 - Analyzing window types.
VenTTracker #03 - Analyzing window types II
VenTTracker #04 - Playing with the IMU
VenTTracker #05 - Sliding Window Mock-up
VenTTracker #06 - Window Sensor Prototype
VenTTracker #07 - Adjusting the window sensor
VenTTracker #08 - Trying to make a measuring device with the accelerometer
VenTTracker #09 - Checking and updating WiFiNINA Firmware
VenTTracker #10 - Ventilation Monitor on Arduino IoT Cloud
VenTTracker #11 - Wireless Environmental Monitor on Arduino Nano 33 IoT
VenTTracker #12 - Window Anomaly Detection. Edge Impulse & Arduino Nano 33 IoT
VenTTracker #14 (aka #11 bis) - Environmental Monitor Revisited - Version 2
VenTTracker #13 - Project wrap-up and Lessons learned

 

<< Previous VenTTracker BlogNext VenTTracker Blog  >>
VenTTracker #02 -  Analyzing window types.VenTTracker #04 -  Playing with the IMU
  • Sign in to reply

Top Comments

  • aspork42
    aspork42 over 4 years ago +3
    Looks like great progress on the sensors. I was wondering how well the casement window sensor would work. It is “almost” there, but I’m sure it will drift over time. You could use a third Reed switch for…
  • javagoza
    javagoza over 4 years ago in reply to aspork42 +2
    aspork42 thank you very much for these suggestions. You're right. As can be seen in the video, without prior filtering of the values, the position estimate deviates over time. In the ideal case for a no…
  • javagoza
    javagoza over 4 years ago in reply to aspork42

    aspork42 thank you very much for these suggestions.

     

    You're right. As can be seen in the video, without prior filtering of the values, the position estimate deviates over time.

    In the ideal case for a no-motion condition all samples should be zero. That constant speed indicates a condition of continuous motion and therefore an unstable position. Due to the fact that samples that are not equal to zero are being added.

    To solve this I intend to apply a mechanical filtering window, so that when we are in a condition of absence of movement, a stopped state, avoid that minor errors in acceleration that can be interpreted as a constant speed. A discrimination window between valid values and invalid values for the no movement condition.

     

    The project requirements do not need precise control of the position of the window or door.

    We are only interested in determining 4 states:

    • Completely closed: open ratio = 0%
    • Almost closed: 0% <open ratio <33%
    • Semi-open 33% <= open ratio <66%
    • Fully open 66% <= open ratio <100%
    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • aspork42
    aspork42 over 4 years ago

    Looks like great progress on the sensors. I was wondering how well the casement window sensor would work. It is “almost” there, but I’m sure it will drift over time. You could use a third Reed switch for the “closed” sensor and minimize components. You’ve really gone to town just doing test setups for these - I love it.

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube