Showing posts with label raspberry pi. Show all posts
Showing posts with label raspberry pi. Show all posts

Thursday, October 8, 2020

Home Automation step1

LAMP1,2,3 are the light going to control. L1 controlled by PIR sensor that attached to ESP32, L2 and L3 can control via MQTT massage which pass by node-red dashboard, Node-red dash board can be access using any portable device such as phone, Tab etc.

 

#include <WiFi.h>
#include <PubSubClient.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// Change the credentials below, so your ESP32 connects to your router
const char* ssid = "Dialog 4G";
const char* password = "YJNHQ102RD8";

// Change the variable to your Raspberry Pi IP address, so it connects to your MQTT broker
const char* mqtt_server = "192.168.0.105";

// Initializes the espClient. You should change the espClient name if you have multiple ESPs running in your home automation system
WiFiClient espClient;
PubSubClient client(espClient);

#define timeSeconds 10 // dealy for PIR motion

const int lamp2 = 17; // lamp2 - LED - GPIO 17 on ESP32 board
const int lamp3 = 5 ; // Lamp3 - LED - GPIO 5 on ESP32 board
const int lamp1 = 14;  // lamp1==PIR out // Set GPIOs for lamp1 and PIR Motion Sensor
const int mqttInterrupt = 12; // Interrupt GPIO for PIR mtion sensor trigger input
const int mqttInterruptL2= 13; // interrrupt GPIO for Lamp2
const int mqttInterruptL3= 27; // interrrupt GPIO for Lamp2
boolean toggle =false;
boolean toggle1=false;


// Timer: Auxiliary variables
unsigned long now_delay = millis();
unsigned long lastTrigger = 0;
boolean startTimer = false;

// Checks if motion was detected, sets LED HIGH and starts a timer
void IRAM_ATTR detectsMovement() {
  Serial.println("MOTION DETECTED!!!");
  digitalWrite(lamp1, HIGH);
  startTimer = true;
  lastTrigger = millis();
}
void IRAM_ATTR lamp2interrupt() {
  toggle=!toggle;
  Serial.println("Lamp2 interrupt");
  digitalWrite(lamp2, toggle );

}
void IRAM_ATTR lamp3interrupt() {
  toggle1=!toggle1;
  Serial.println("Lamp3 interrupt");
  digitalWrite(lamp3, toggle1 );

}

// Don't change the function below. This functions connects your ESP8266 to your router
void setup_wifi() {
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("WiFi connected - ESP IP address: ");
  Serial.println(WiFi.localIP());
}


void callback(String topic, byte* message, unsigned int length) {
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  String messageTemp;
 
  for (int i = 0; i < length; i++) {
    Serial.print((char)message[i]);
    messageTemp += (char)message[i];
  }
  Serial.println();

  // Feel free to add more if statements to control more GPIOs with MQTT
  if(topic=="room/lamp3"){
      Serial.print("Changing Room lamp3 to ");
      if(messageTemp == "on"){
        digitalWrite(lamp3, HIGH);
        Serial.print("On");
      }
      else if(messageTemp == "off"){
        digitalWrite(lamp3, LOW);
        Serial.print("Off");
      }
  }
  Serial.println();
  // If a message is received on the topic room/lamp2, you check if the message is either on or off. Turns the lamp GPIO according to the message
  if(topic=="room/lamp2"){
      Serial.print("Changing Room lamp2 to ");
      if(messageTemp == "on"){
        digitalWrite(lamp2, HIGH);
        Serial.print("On");
      }
      else if(messageTemp == "off"){
        digitalWrite(lamp2, LOW);
        Serial.print("Off");
      }
  }
  Serial.println();

  if(topic=="room/pir"){
      Serial.print("PIR DETECTED ");
      if(messageTemp == "on"){
        digitalWrite(lamp1, HIGH);
        Serial.print("PIR On");
      }
      else if(messageTemp == "off"){
        digitalWrite(lamp1, LOW);
        Serial.print("PIR Off");
      }
  }
  Serial.println();
 
}



void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    /*
     YOU MIGHT NEED TO CHANGE THIS LINE, IF YOU'RE HAVING PROBLEMS WITH MQTT MULTIPLE CONNECTIONS
     To change the ESP device ID, you will have to give a new name to the ESP8266.
     Here's how it looks:
       if (client.connect("ESP8266Client")) {
     You can do it like this:
       if (client.connect("ESP1_Office")) {
     Then, for the other ESP:
       if (client.connect("ESP2_Garage")) {
      That should solve your MQTT multiple connections problem
    */
    if (client.connect("ESP8266Client")) {
      Serial.println("connected");  
      // Subscribe or resubscribe to a topic
      // You can subscribe to more topics (to control more LEDs in this example)
      client.subscribe("room/pir");
      client.subscribe("room/lamp2");
      client.subscribe("room/lamp3");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}




void setup() {

 
 
 
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

 
  // Serial port for debugging purposes
  Serial.begin(115200);
 
  // PIR Motion Sensor mode INPUT_PULLUP
  pinMode(mqttInterrupt, INPUT_PULLUP);
  pinMode(mqttInterruptL2, INPUT_PULLUP);
  pinMode(mqttInterruptL3, INPUT_PULLUP);
  // Set mqttInterrupt pin as interrupt, assign interrupt function and set RISING mode
  attachInterrupt(digitalPinToInterrupt(mqttInterrupt), detectsMovement, RISING);
  attachInterrupt(digitalPinToInterrupt(mqttInterruptL2), lamp2interrupt, RISING);
  attachInterrupt(digitalPinToInterrupt(mqttInterruptL3), lamp3interrupt, RISING);
 
  // Set lamps to LOW
  pinMode(lamp1, OUTPUT);
  digitalWrite(lamp1, LOW);
  pinMode(lamp2, OUTPUT);
  digitalWrite(lamp2, LOW);
  pinMode(lamp3, OUTPUT);
  digitalWrite(lamp3, LOW);
}

void loop() {

 
  if (!client.connected()) {
    reconnect();
  }
  if(!client.loop())
    client.connect("ESP8266Client");

 // now = millis();
  //   return;
 
   Serial.println("im busy .");
   delay(500);
 
  // Current time
  now_delay = millis();
  // Turn off the lamp1 after the number of seconds defined in the timeSeconds variable
  if(startTimer && (now_delay - lastTrigger > (timeSeconds*1000))) {
    Serial.println("Motion stopped...");
    digitalWrite(lamp1, LOW);
    startTimer = false;
  }
}

Wednesday, December 11, 2019

How to use MPU6050 (GY521) with Raspberry PI

 What is MPU 6050 ?

The MPU-6050 is an integrated 6-axis motion tracking device that combines a 3-axis gyroscope and a 3-axis accelerometer on a single microchip. It is commonly referred to as the GY-521 module and is used in a variety of applications, such as drone stabilization systems, wearable devices, and gaming controllers.

The device communicates with microcontrollers and single-board computers, such as the Arduino, via the I2C interface. The MPU-6050 provides raw accelerometer and gyroscope data that can be processed using a Kalman filter or complementary filter to obtain a more accurate estimate of the device's orientation in space.

The MPU-6050 is a low-cost and widely available device that is well-suited for a variety of motion tracking applications.


MPU6050 (GY521)

 


The MPU6050 also categorized as Micro Electro-Mechanical Systems (MEMS) which consists of a 3-axis Accelerometer and 3-axis Gyroscope inside it.
Following information can be read out from the MPU6050.
  • Acceleration along three mutually perpendicular axes with a programmable full scale range of ±2g, ±4g, ±8g and ±16g. This measurement includes the acceleration due to gravity.
  • Angular velocity around three mutually perpendicular axes, with a user-programmable full-
    scale range of ±250, ±500, ±1000, and ±2000°/sec
  • Temperature

To integrate the MPU-6050 with a Raspberry Pi, you will need to follow these steps:

  1. Connect the MPU-6050 to the Raspberry Pi: Connect the VCC pin of the MPU-6050 to the 3.3V pin of the Raspberry Pi, GND to GND, SDA to SDA (GPIO 2), and SCL to SCL (GPIO 3).


     

  2. Enable I2C on the Raspberry Pi: You will need to enable the I2C interface on your Raspberry Pi in order to communicate with the MPU-6050. This can be done through the Raspberry Pi Configuration tool in the Preferences menu, or by adding the following line to the /boot/config.txt file:

dtparam=i2c_arm=on
  1. Install the i2c-tools package: The i2c-tools package provides the necessary tools to communicate with I2C devices on the Raspberry Pi. You can install it by running the following command:
sudo apt-get install i2c-tools
  1. Test the connection: After enabling I2C and installing the i2c-tools package, you can test the connection between the Raspberry Pi and the MPU-6050 by running the following command:
sudo i2cdetect -y 1

If the MPU-6050 is connected correctly, you should see its address (0x68) in the list of I2C devices.

  1. Read data from the MPU-6050: To read data from the MPU-6050, you will need to write code in a programming language such as Python that reads the raw data from the sensor using the I2C interface. A number of libraries are available to simplify this process, such as the RTIMULib library, which provides a simple and easy-to-use interface to the MPU-6050.

Once you have the raw data from the MPU-6050, you can process it to obtain more useful information, such as the device's orientation in space.


// ////////////////Sample Code for reading mpu6050 using Rpi/////////////////////
// build with:  gcc -o mpu6050 mpu6050.c

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/i2c-dev.h>
#include <math.h>

#define MPU_GYRO_CONFIG 0x1b
#define MPU_ACCEL_CONFIG 0x1c

#define MPU_ACCEL_XOUT1 0x3b
#define MPU_ACCEL_XOUT2 0x3c
#define MPU_ACCEL_YOUT1 0x3d
#define MPU_ACCEL_YOUT2 0x3e
#define MPU_ACCEL_ZOUT1 0x3f
#define MPU_ACCEL_ZOUT2 0x40

#define MPU_GYRO_XOUT1 0x43
#define MPU_GYRO_XOUT2 0x44
#define MPU_GYRO_YOUT1 0x45
#define MPU_GYRO_YOUT2 0x46
#define MPU_GYRO_ZOUT1 0x47
#define MPU_GYRO_ZOUT2 0x48

#define MPU_TEMP1 0x41
#define MPU_TEMP2 0x42

#define MPU_POWER1 0x6b
#define MPU_POWER2 0x6c

    void selectDevice(int fd, int addr, char * name)
    {
       if (ioctl(fd, I2C_SLAVE, addr) < 0) {
          fprintf(stderr, "%s not present\n", name);
       }
    }

    void selectRegister(int fd, int reg)
    {
       char buf[1];
       buf[0]=reg;
       if (write(fd, buf, 1) != 1)  {
          fprintf(stderr, "Can't write\n");
       }
    }
   
  
    void writeToDevice(int fd, int reg, int val)
    {
       char buf[2];
       buf[0]=reg; buf[1]=val;
       if (write(fd, buf, 2) != 2)   {
          fprintf(stderr, "Can't write\n");
       }
    }
   

int main(int argc, char **argv)
{
    int fd;
    char *fileName = "/dev/i2c-2";
    int  address = 0x68;
    unsigned char buf[16];
    float T;
    float xa,ya,za,acc_scale=16384.0;
    float xg,yg,zg,gyro_scale=131.0;
    int8_t p;   

    if ((fd = open(fileName, O_RDWR)) < 0) {
        printf("Failed to open i2c port\n");
        exit(1);
    }
   
    selectDevice(fd,address,"MPU6050");

// MPU6050 is in sleep mode upon power on.
// To wake up, bit 6 of register MPU_POWER1 must be set to 0
    selectRegister(fd,MPU_POWER1);
    read(fd,buf,1);                                  // read the current value of MPU_POWER1
    p = buf[0];
    selectRegister(fd,MPU_POWER1);
    writeToDevice(fd,MPU_POWER1,~(1 << 6) & p); // set bit 6 to zero and write to MPU_POWER1

// set gyro scale to +/- 250   
    selectRegister(fd,MPU_GYRO_CONFIG);
    read(fd,buf,1);                                  // read the current value
    p = buf[0];
    selectRegister(fd,MPU_GYRO_CONFIG);
    writeToDevice(fd,MPU_GYRO_CONFIG,~(3 << 3) & p); // set bits 3 and 4 to 11    

// set accel scale to +/- 2g    
    selectRegister(fd,MPU_ACCEL_CONFIG);
    read(fd,buf,1);                                  // read the current value
    p = buf[0];
    selectRegister(fd,MPU_ACCEL_CONFIG);
    writeToDevice(fd,MPU_ACCEL_CONFIG,~(3 << 3) & p); // set bits 3 and 4 to 11   
   
    while (1) {
     selectRegister(fd,MPU_TEMP1);  // temperature
     read(fd,buf,2); // read 2 registers (low byte and high byte)
     int16_t  temp =  buf[0]<<8 | buf[1];  // combine the two bytes

     selectRegister(fd,MPU_ACCEL_XOUT1);
     read(fd,buf,2);
     int16_t  xaccel =  buf[0]<<8 | buf[1];
     xa = xaccel/acc_scale; // convert to g
    
     selectRegister(fd,MPU_ACCEL_YOUT1);
     read(fd,buf,2);
     int16_t  yaccel =  buf[0]<<8 | buf[1];
     ya = yaccel/acc_scale; // convert to g

     selectRegister(fd,MPU_ACCEL_ZOUT1);
     read(fd,buf,2);
     int16_t  zaccel =  buf[0]<<8 | buf[1];
     za = zaccel/acc_scale; // convert to g
    
     selectRegister(fd,MPU_GYRO_XOUT1);
     read(fd,buf,2);
     int16_t  xgyro =  buf[0]<<8 | buf[1];
     xg = xgyro/gyro_scale; // convert

     selectRegister(fd,MPU_GYRO_YOUT1);
     read(fd,buf,2);
     int16_t  ygyro =  buf[0]<<8 | buf[1];
     yg = ygyro/gyro_scale; // convert

     selectRegister(fd,MPU_GYRO_ZOUT1);
     read(fd,buf,2);
     int16_t  zgyro =  buf[0]<<8 | buf[1];
     zg = zgyro/gyro_scale; // convert
    
     T = temp / 340.0f + 36.53;
     printf("temp: %f\n",T );
     printf("accel x,y,z: %f, %f, %f\n", xa, ya,za);
     printf("gyro x,y,z:  %f, %f, %f\n\n", xg,yg,zg);
     sleep(1); // delay
    }
   
    return 0;
}

Search This Blog