How to add Hand gestures to your Arduino projects using PAJ7620
Hello and welcome, this tutorial is about the PAJ7620 Hand gestures sensor, it permits your hand gestures to be detected by the Arduino board, and then you can use it to control lights, robots (cool stuff), HMI, games… using IR LED and optical CMOS array, it can detect up to 15 gestures.
This one costs around 2-3$ only but it is not very precise (as you can see in the video) as the Thermal Imaging Arrays who can detect precisely complex gestures cost around 30-40$.
The gestures that can be detected are:
- Right, Left, Up, Down, Forward, Backward,
- Clockwise, Anti clockwise,
- and waving.
Those are the basic 9 then you can add:
- Right-Left, Left-Right,
- Up-Down, Down-up,
- Forward-Backward, Backward-Forward (Check the video to know the differences).
There are two ways of detecting:
-  Near, which is on 5-15 cm distance with 60° angle
-  Far, on 15-30 cm distance with 30° angle
For this project I’m gonna interface it with Arduino Uno board, and I’ll use a LCD i²c screen to show the gesture detected, using this method you can adapt it to whatever project you’re working on.
Hardware and parts
Wirings
Wiring 1: Basic wiring of the module
Wiring 2: Adding LCD i2c
Libraries
- PAJ7620 Library: Download here from Github or Download Here.
- LCD i²c New Liquid Library: Download it here, This library I’ve been using for years, maybe you can find an alternative or new one.
Please pay attention, the libraries in Github get constantly modified and may not work with old versions of Arduino IDE, chose to either keep up or use the library I provided. I may do a review for these codes in the future.
Codes
Code 1: Library example – paj7620_9gestures
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
/*  * Copyright (c) 2015 seeed technology inc.  * Website  : http://www.seeed.cc  * Author   : Wuruibin  * Modified Time: June 2015  * Description: This demo can recognize 9 gestures and output the result, including move up, move down, move left, move right,  * move forward, move backward, circle-clockwise, circle-counter clockwise, and wave.  *  * The MIT License (MIT)  *  * Permission is hereby granted, free of charge, to any person obtaining a copy  * of this software and associated documentation files (the "Software"), to deal  * in the Software without restriction, including without limitation the rights  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  * copies of the Software, and to permit persons to whom the Software is  * furnished to do so, subject to the following conditions:  *  * The above copyright notice and this permission notice shall be included in  * all copies or substantial portions of the Software.  *  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN  * THE SOFTWARE.  */ #include <Wire.h> #include "paj7620.h" /* Notice: When you want to recognize the Forward/Backward gestures, your gestures' reaction time must less than GES_ENTRY_TIME(0.8s).     You also can adjust the reaction time according to the actual circumstance. */ #define GES_REACTION_TIME 500 // You can adjust the reaction time according to the actual circumstance. #define GES_ENTRY_TIME 800 // When you want to recognize the Forward/Backward gestures, your gestures' reaction time must less than GES_ENTRY_TIME(0.8s). #define GES_QUIT_TIME 1000 void setup() { uint8_t error = 0; Serial.begin(9600); Serial.println("\nPAJ7620U2 TEST DEMO: Recognize 9 gestures."); error = paj7620Init();// initialize Paj7620 registers if (error) { Serial.print("INIT ERROR,CODE:"); Serial.println(error); } else { Serial.println("INIT OK"); } Serial.println("Please input your gestures:\n"); } void loop() { uint8_t data = 0, data1 = 0, error; error = paj7620ReadReg(0x43, 1, &data);// Read Bank_0_Reg_0x43/0x44 for gesture result. if (!error) { switch (data) // When different gestures be detected, the variable 'data' will be set to different values by paj7620ReadReg(0x43, 1, &data). { case GES_RIGHT_FLAG: delay(GES_ENTRY_TIME); paj7620ReadReg(0x43, 1, &data); if(data == GES_FORWARD_FLAG) { Serial.println("Forward"); delay(GES_QUIT_TIME); } else if(data == GES_BACKWARD_FLAG) { Serial.println("Backward"); delay(GES_QUIT_TIME); } else { Serial.println("Right"); }      break; case GES_LEFT_FLAG: delay(GES_ENTRY_TIME); paj7620ReadReg(0x43, 1, &data); if(data == GES_FORWARD_FLAG) { Serial.println("Forward"); delay(GES_QUIT_TIME); } else if(data == GES_BACKWARD_FLAG) { Serial.println("Backward"); delay(GES_QUIT_TIME); } else { Serial.println("Left"); }      break; case GES_UP_FLAG: delay(GES_ENTRY_TIME); paj7620ReadReg(0x43, 1, &data); if(data == GES_FORWARD_FLAG) { Serial.println("Forward"); delay(GES_QUIT_TIME); } else if(data == GES_BACKWARD_FLAG) { Serial.println("Backward"); delay(GES_QUIT_TIME); } else { Serial.println("Up"); }      break; case GES_DOWN_FLAG: delay(GES_ENTRY_TIME); paj7620ReadReg(0x43, 1, &data); if(data == GES_FORWARD_FLAG) { Serial.println("Forward"); delay(GES_QUIT_TIME); } else if(data == GES_BACKWARD_FLAG) { Serial.println("Backward"); delay(GES_QUIT_TIME); } else { Serial.println("Down"); }      break; case GES_FORWARD_FLAG: Serial.println("Forward"); delay(GES_QUIT_TIME); break; case GES_BACKWARD_FLAG:  Serial.println("Backward"); delay(GES_QUIT_TIME); break; case GES_CLOCKWISE_FLAG: Serial.println("Clockwise"); break; case GES_COUNT_CLOCKWISE_FLAG: Serial.println("anti-clockwise"); break;  default: paj7620ReadReg(0x44, 1, &data1); if (data1 == GES_WAVE_FLAG) { Serial.println("wave"); } break; } } delay(100); } |
Code 2: Library example – paj7620_15gestures
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
/*  * Copyright (c) 2015 seeed technology inc.  * Website  : http://www.seeed.cc  * Author   : Wuruibin  * Modified Time: June 2015  * Description: This demo can recognize 15 gestures and output the result.  * You can adjust the reaction time according to the actual circumstance  * by modifying "#define GES_REACTION_TIME 500".  *  * The MIT License (MIT)  *  * Permission is hereby granted, free of charge, to any person obtaining a copy  * of this software and associated documentation files (the "Software"), to deal  * in the Software without restriction, including without limitation the rights  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  * copies of the Software, and to permit persons to whom the Software is  * furnished to do so, subject to the following conditions:  *  * The above copyright notice and this permission notice shall be included in  * all copies or substantial portions of the Software.  *  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN  * THE SOFTWARE.  */ #include <Wire.h> #include "paj7620.h" /* Notice: When you want to recognize the Forward/Backward gesture or other continuous gestures, your gestures' reaction time must less than GES_REACTION_TIME(0.8s).     You also can adjust the reaction time according to the actual circumstance. */ #define GES_REACTION_TIME 800 #define GES_QUIT_TIME 1000 void setup() { uint8_t error = 0; Serial.begin(9600); Serial.println("\nPAJ7620U2 TEST DEMO: Recognize 15 gestures."); error = paj7620Init();// initialize Paj7620 registers if (error) { Serial.print("INIT ERROR,CODE:"); Serial.println(error); } else { Serial.println("INIT OK"); } Serial.println("Please input your gestures:"); } void loop() { uint8_t data = 0, data1 = 0, error; error = paj7620ReadReg(0x43, 1, &data);// Read Bank_0_Reg_0x43/0x44 for gesture result. if (!error) { switch (data) // When different gestures be detected, the variable 'data' will be set to different values by paj7620ReadReg(0x43, 1, &data). { case GES_RIGHT_FLAG: delay(GES_REACTION_TIME); paj7620ReadReg(0x43, 1, &data); if(data == GES_LEFT_FLAG) { Serial.println("Right-Left"); } else if(data == GES_FORWARD_FLAG) { Serial.println("Forward"); delay(GES_QUIT_TIME); } else if(data == GES_BACKWARD_FLAG) { Serial.println("Backward"); delay(GES_QUIT_TIME); } else { Serial.println("Right"); }      break; case GES_LEFT_FLAG: delay(GES_REACTION_TIME); paj7620ReadReg(0x43, 1, &data); if(data == GES_RIGHT_FLAG) { Serial.println("Left-Right"); } else if(data == GES_FORWARD_FLAG) { Serial.println("Forward"); delay(GES_QUIT_TIME); } else if(data == GES_BACKWARD_FLAG) { Serial.println("Backward"); delay(GES_QUIT_TIME); } else { Serial.println("Left"); }      break; break; case GES_UP_FLAG: delay(GES_REACTION_TIME); paj7620ReadReg(0x43, 1, &data); if(data == GES_DOWN_FLAG) { Serial.println("Up-Down"); } else if(data == GES_FORWARD_FLAG) { Serial.println("Forward"); delay(GES_QUIT_TIME); } else if(data == GES_BACKWARD_FLAG) { Serial.println("Backward"); delay(GES_QUIT_TIME); } else { Serial.println("Up"); } break; case GES_DOWN_FLAG: delay(GES_REACTION_TIME); paj7620ReadReg(0x43, 1, &data); if(data == GES_UP_FLAG) { Serial.println("Down-Up"); } else if(data == GES_FORWARD_FLAG) { Serial.println("Forward"); delay(GES_QUIT_TIME); } else if(data == GES_BACKWARD_FLAG) { Serial.println("Backward"); delay(GES_QUIT_TIME); } else { Serial.println("Down"); } break; case GES_FORWARD_FLAG: delay(GES_REACTION_TIME); paj7620ReadReg(0x43, 1, &data); if(data == GES_BACKWARD_FLAG) { Serial.println("Forward-Backward"); delay(GES_QUIT_TIME); } else { Serial.println("Forward"); delay(GES_QUIT_TIME); } break; case GES_BACKWARD_FLAG:  delay(GES_REACTION_TIME); paj7620ReadReg(0x43, 1, &data); if(data == GES_FORWARD_FLAG) { Serial.println("Backward-Forward"); delay(GES_QUIT_TIME); } else { Serial.println("Backward"); delay(GES_QUIT_TIME); } break; case GES_CLOCKWISE_FLAG: Serial.println("Clockwise"); break; case GES_COUNT_CLOCKWISE_FLAG: Serial.println("anti-clockwise"); break;  default: paj7620ReadReg(0x44, 1, &data1); if (data1 == GES_WAVE_FLAG) { Serial.println("wave"); } break; } } delay(100); } |
Code 3: Using LCD i2c
You can Download it here.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
/* This code works with PAJ7620 Hand gestures sensor and LCD i²c screen * It shows the gestures detected on the LCD screen * Adapted from the Seeed PAJ7620 library examples * For more details check http://www.surtrtech.com */ #include <LiquidCrystal_I2C.h> #include <Wire.h> #include "paj7620.h" #define I2C_ADDR 0x27 //I2C adress, you should use the code to scan the adress first (0x27) here #define BACKLIGHT_PIN 3 // Declaring LCD Pins #define En_pin 2 #define Rw_pin 1 #define Rs_pin 0 #define D4_pin 4 #define D5_pin 5 #define D6_pin 6 #define D7_pin 7 #define GES_REACTION_TIME 500 #define GES_ENTRY_TIME 800 #define GES_QUIT_TIME 1000 LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin); void setup() { paj7620Init(); lcd.begin (16,2); lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE); lcd.setBacklight(HIGH); //Lighting backlight } void printing(){ lcd.clear(); lcd.setCursor(0,0); lcd.print("Gesture Sensor"); lcd.setCursor(0,1); } void loop() { uint8_t data = 0, data1 = 0, error; error = paj7620ReadReg(0x43, 1, &data); // Read Bank_0_Reg_0x43/0x44 for gesture result. if (!error) { switch (data) // When different gestures be detected, the variable 'data' will be set to different values by paj7620ReadReg(0x43, 1, &data). { case GES_RIGHT_FLAG: delay(GES_ENTRY_TIME); paj7620ReadReg(0x43, 1, &data); if(data == GES_FORWARD_FLAG) { printing(); lcd.print("Forward"); delay(GES_QUIT_TIME); } else if(data == GES_BACKWARD_FLAG) { printing(); lcd.print("Backward"); delay(GES_QUIT_TIME); } else { printing(); lcd.print("Right"); } break; case GES_LEFT_FLAG: delay(GES_ENTRY_TIME); paj7620ReadReg(0x43, 1, &data); if(data == GES_FORWARD_FLAG) { printing(); lcd.print("Forward"); delay(GES_QUIT_TIME); } else if(data == GES_BACKWARD_FLAG) { printing(); lcd.print("Backward"); delay(GES_QUIT_TIME); } else { printing(); lcd.print("Left"); } break; case GES_UP_FLAG: delay(GES_ENTRY_TIME); paj7620ReadReg(0x43, 1, &data); if(data == GES_FORWARD_FLAG) { printing(); lcd.print("Forward"); delay(GES_QUIT_TIME); } else if(data == GES_BACKWARD_FLAG) { printing(); lcd.print("Backward"); delay(GES_QUIT_TIME); } else { printing(); lcd.print("Up"); } break; case GES_DOWN_FLAG: delay(GES_ENTRY_TIME); paj7620ReadReg(0x43, 1, &data); if(data == GES_FORWARD_FLAG) { printing(); lcd.print("Forward"); delay(GES_QUIT_TIME); } else if(data == GES_BACKWARD_FLAG) { printing(); lcd.print("Backward"); delay(GES_QUIT_TIME); } else { printing(); lcd.print("Down"); } break; case GES_FORWARD_FLAG: printing(); lcd.print("Forward"); delay(GES_QUIT_TIME); break; case GES_BACKWARD_FLAG: printing(); lcd.print("Backward"); delay(GES_QUIT_TIME); break; case GES_CLOCKWISE_FLAG: printing(); lcd.print("Clockwise"); break; case GES_COUNT_CLOCKWISE_FLAG: printing(); lcd.print("anti-clockwise"); break; default: paj7620ReadReg(0x44, 1, &data1); if (data1 == GES_WAVE_FLAG) { printing(); lcd.print("wave"); } break; } } delay(100); } |
Test
The tests are straight forward, just wire the module, plug the Arduino, upload the code, open the serial monitor and start moving your hands.
Overall the module performances are not bad for 2$, sometimes it can be tricky when detecting the Forward gesture, you can check the code to actually find that it can be confused with other gestures, you can always modify the detection speed for all and for the forward&backward alone:
Also make sure the module is on a flat surface, otherwise the clockwise anti-clockwise gestures won’t be detected, and make sure you have enough space for you hand to move.
Categories
Yassine View All
Automation and Electrical Engineer, Electronics amateur trying to share my little projects.
great…..please tell me the water proof ultra sound sensor interfced with arduino