Mostrando entradas con la etiqueta BMP180. Mostrar todas las entradas
Mostrando entradas con la etiqueta BMP180. Mostrar todas las entradas

martes, 4 de octubre de 2022

Raspberry pi pico, Programación C, Sensores: LDR - DHT22 (AM2302) - BMP180 - 18B20 OLED DS1302

  Página principal

Raspberry pi pico
Programación C
Sensores:
LDR - DHT22 (AM2302) - BMP180 - 18B20
OLED DS1302


Anteriormente había realizado un visualizador de sensores con el ESP32.
Algún tiempo después lo hice en la Raspberry pi pico programándolo en
microPython - PICO4
En este artículo lo realizo con la Raspberry pi pico y programando en C.

El final del montaje queda de la siguiente forma:





sen_p1 y sen_p2
El primer paso es colocar un led a modo de piloto de alimentación, y hacer parpadear el led que viene en la placa.

#include <stdio.h>
#include <pico/stdlib.h>


#define OUTPUT 1
#define INPUT 0
#define HIGH 1
#define LOW 0

void pinMode(unsigned int port, char modo);
void digitalWrite(unsigned int port, char val);
void delay(long t);

#define MILED 25

int main()
{
    stdio_init_all();
    delay(1000);
    printf("-----------------------\n");
    printf("----Hola SENSORES------\n");
    pinMode(MILED, OUTPUT);
    while(1)
    {
      printf("Estado %d\n",0);
      digitalWrite(MILED, LOW);
      delay(1000);
      printf("Estado %d\n",1);
      digitalWrite(MILED, HIGH);
      delay(2000);
    }
}


//---------------I/O----------------
void pinMode(unsigned int port, char modo)
{
    gpio_init(port);
    if(modo==OUTPUT)
        gpio_set_dir(port, GPIO_OUT);
     else
        gpio_set_dir(port, GPIO_IN);
}

void digitalWrite(unsigned int port, char val)
{
    gpio_put(port, val);
}

void delay(long t)
{
    sleep_ms(t);
}

Como me parece más fácil el modo de configurar los puertos de la forma que loa hace arduino , he creado un par de funciones tipo arduino.
A partir de ahora, las funciones se meterán en un fichero ardu.h donde se incluirán las funciones.


sen_p3
En este paso colocamos un sensor de temperatura y humedad

El sensor es el DHT22 o su equivalente AM2302.


#include <stdio.h>
#include <pico/stdlib.h>

#include "ardu.h"

#define MILED 25

//----DHT-----------
#define PIN_DHT 15
unsigned int humedad,temperatura,control;
unsigned char dataSensor[5];
unsigned int ck;
void leerDHT(void);

int main()
{
    stdio_init_all();
    delay(1000);

    printf("----Hola SENSORES------\n");
    pinMode(MILED, OUTPUT);
    while(1)
    {
      leerDHT();
      printf("AM2302_H=%.1f%%   T=%.1f ºC   Control=%d\n",(float)humedad/10,(float)temperatura/10,control);
     
      digitalWrite(MILED, LOW);
      delay(1000);
      digitalWrite(MILED, HIGH);
      delay(2000);
      printf("-----------------------\n");
    }
}


//----------DHT--------------------
void leerDHT(void)
{
  unsigned char n,z,x;
  unsigned char contador1,contador0;
  unsigned char datos[45];
  control=temperatura=humedad=0;
 
  pinMode(PIN_DHT,OUTPUT);
  digitalWrite(PIN_DHT,LOW);
  delay(2);
  digitalWrite(PIN_DHT,HIGH);
  pinMode(PIN_DHT,INPUT);
 
  for(n=0;n<42;n++)
  {
    contador0=contador1=0;
    while(1==digitalRead(PIN_DHT))
    {
      delayMicroseconds(5);
      contador1++;
      if(contador1>250)goto salir;
    }
    while(0==digitalRead(PIN_DHT))
    {
      delayMicroseconds(5);
      contador0++;
      if(contador1>250)goto salir;     
    }
    datos[n]=contador1;   
  }

  z=0;
  x=0;
  for(n=2;n<42;n++)
    {
      dataSensor[z]<<=1;
      if(datos[n]>=contador0) { (dataSensor[z])|=1;}
      x++;
      if(x==8) { x=0;  z++;  }      
    }

  humedad=dataSensor[0];
  humedad<<=8;
  humedad|=dataSensor[1];
  temperatura=dataSensor[2];
  temperatura<<=8;
  temperatura|=dataSensor[3];
  control=dataSensor[4];
salir: 
;
}
//---------------------------------
En este caso he tenido que crear yo las funciones de lectura.
Primero la hice sobre arduino y luego trasladé el código a la Raspberry pi pico.
El paso de una placa a otra fue fácil, no tuve que hacer ningún cambio.



El protocolo
1-wire, es bastante sencillo de programar.

----Hola SENSORES------
AM2302_H=39.4%   T=22.5 ºC   Control=108
-----------------------
AM2302_H=40.7%   T=22.5 ºC   Control=121


sen_p4
En este paso ponemos un sensor de luz tipo LDR,
y leemos el valor mediante un conversor ADC.

...
#include "hardware/gpio.h"
#include "hardware/adc.h"
...

//---Voltios LDR---
uint16_t result;
...

main()
{
...
 //INIT --ADC-- 
    adc_init();
    adc_gpio_init(28);    // Select ADC input 0 (GPIO26)
    adc_select_input(2);
    const float conversion_factor = 3.3f / 4096;
...

while(1)
    {
....
      result = adc_read();
      printf("LDR-> RAW=%d, voltaje=%f V\n", result, result * conversion_factor);
...
    }
}
En este caso solo  muestro el código correspondiente a la conversión A/D.
Este código no tiene demasiado explicación, configuración pin 28, y lectura del valor.

----Hola SENSORES------
AM2302_H=38.8%   T=23.5 ºC   Control=112
LDR-> RAW=402, voltaje=0.323877 V
-----------------------
AM2302_H=40.1%   T=23.5 ºC   Control=125
LDR-> RAW=403, voltaje=0.324683 V
-----------------------


sen_p5
En este paso colocamos un sensor de presión que además dispone de un sensor de temperatura.

El sensor viene en un módulo BMP180, los datos se mandan mediante el bus I2C.


...
#include "pico/binary_info.h"
#include "hardware/i2c.h"

#include <math.h>
...

//----I2C-------
i2c_inst_t *XXi2c = i2c0;        //i2c1 para 26-27   12c0 para 0-1 ...
#define    SDA_PIN 0
#define    SCL_PIN 1
 
#define  BMP180_ADDR 0x77 // 7-bit address
#define  BMP180_WRITE_MODE _u(0xFE)
#define  BMP180_READ_MODE _u(0xFF)
#define     BMP180_REG_CONTROL 0xF4
#define     BMP180_REG_RESULT 0xF6
#define     BMP180_COMMAND_TEMPERATURE 0x2E

void bmpGetData(void);
void bmpComand(uint8_t cmd);
int bmpInput(char address);
void getVarBMP(void);
void scanI2C(void);

long Temperatura, Presion, PresionBase;
...

main()
{
...
//INIT --I2C--
    printf("SDA=%d  SDL=%d \n", SDA_PIN, SCL_PIN);
    i2c_init(i2c_default, 100000);
    gpio_set_function( SDA_PIN, GPIO_FUNC_I2C);
    gpio_set_function( SCL_PIN, GPIO_FUNC_I2C);
    gpio_pull_up( SDA_PIN);
    gpio_pull_up( SCL_PIN);
    bi_decl(bi_2pins_with_func( SDA_PIN,  SCL_PIN, GPIO_FUNC_I2C));
   
    scanI2C();  
    getVarBMP();
    delay(50);
    bmpGetData();    //Calcula la presión base......
    PresionBase=Presion;
...

while(1)
    {
....
     bmpGetData();
     printf("BMP_TempGRADOS=%0.2f ºC\n",(float)Temperatura/100);
     printf("BMP_Presion=%0.2f bares\n",(float)Presion/100); 
...
    }
}


Solo muestro el código correspondiente a la comunicación I2C y al cálculo de la presión.
En este caso el código del arduino es totalmente diferente al de la Raspberry.
Me costó mucho tiempo y trabajo el descubrir la diferencia entre los tipos de enteros.
En arduino el tamaño de int es de 16bit, en la raspberry es de 32bit.
Y se me ocurrió utilizar el tipo sort, y resulto erroneo su tamaño, por lo que lo mejor es utilizar int16_t o uint16_t.
Hay que tener en presente que existen varios I2C en la raspberry y debemos especificar el que usamos.
Por ejemplo: i2c1 para 26-27  e  12c0 para 0-1 .........
Aunque la librería es mia, he utilizado algún código de otros, en bibliografía  pongo las fuentes.
-----------------------
AM2302_H=41.0%   T=23.7 ºC   Control=136
LDR-> RAW=915, voltaje=0.737183 V
BMP_TempGRADOS=22.21 ºC
BMP_Presion=934.37 bares
-----------------------

Señales del bus I2C cuando lee datos, funcion void bmpGetData(void)

sen_p6
En este paso colocamos un sensor de temperatura 18B20.

Este chip se comunica mediante una sola línea de datos, y si se quiere se puede utilizar solo dos lineas para hacer funcionar el sensor.
Además se pueden colocar varios chip en paralelo, que se podrán leer sus temperaturas independientemente.


//----DS18B20------
#define ONE_WIRE_PIN 22
void onewire_reset();
void onewire_write(unsigned char data);
int onewire_read();
int ds1820_read();

float temp18B;
...

main()
{

while(1)
    {
....
      temp18B=ds1820_read();
      printf("DS18b20_Temp=%0.2f ºC\n",temp18B/10);
...
    }
}


//-------------ONEWIRE-------------
void onewire_reset()
{
    pinMode(ONE_WIRE_PIN,OUTPUT); digitalWrite(ONE_WIRE_PIN,LOW);  
    delayMicroseconds(500);
    digitalWrite(ONE_WIRE_PIN,HIGH);  pinMode(ONE_WIRE_PIN,INPUT);
    delayMicroseconds(500);                
    digitalWrite(ONE_WIRE_PIN,HIGH);  pinMode(ONE_WIRE_PIN,INPUT);
}


void onewire_write(unsigned char data)
{
    unsigned char count;
    for(count = 0; count < 8; ++count)
    {
        pinMode(ONE_WIRE_PIN,OUTPUT); digitalWrite(ONE_WIRE_PIN,LOW);
        delayMicroseconds(2);              
        if(data & 1)
          {  digitalWrite(ONE_WIRE_PIN,HIGH);  }
          else
          {  digitalWrite(ONE_WIRE_PIN,LOW);   }
        data>>=1;

        delayMicroseconds(60);               
        digitalWrite(ONE_WIRE_PIN,HIGH);  pinMode(ONE_WIRE_PIN,INPUT);
        delayMicroseconds(2);                // for more than 1us minimum.
    }
}


int onewire_read()
{
    unsigned char count;
    unsigned char data;
    for(count = 0; count < 8; ++count)
    {
        data>>=1;
        pinMode(ONE_WIRE_PIN,OUTPUT);
        digitalWrite(ONE_WIRE_PIN,LOW);
        delayMicroseconds(2);             
        pinMode(ONE_WIRE_PIN,INPUT);
        delayMicroseconds(10);              
        if(digitalRead(ONE_WIRE_PIN)&1 )  {  data|=128;  }
        delayMicroseconds(50); 
    }
    delayMicroseconds(100);
    return data;
}

int ds1820_read()
{
    unsigned char busy=0, tempL, tempH; 
    long  temp;
   
    onewire_reset();
    onewire_write(0xCC);              
    onewire_write(0x44);  
    delay(10);
    onewire_reset();
    onewire_write(0xCC);           
    onewire_write(0xBE);           
   
    tempL = onewire_read();
    tempH = onewire_read();
 
    temp=tempH; temp<<=8; temp|=tempL;
    //Serial.print(" HEX ");Serial.print(temp,HEX);
    temp=(temp*625)/1000;
  return(temp); 
}

1-Wire es un protocolo de comunicaciones en serie diseñado por Dallas Semiconductor.
Está basado en un bus, un maestro y varios esclavos de una sola línea de datos en la que se alimentan.
En este protocolo se pueden colocar varios 18B20 en paralelo, por lo cual debería colocar una función de detección de elementos.
Otra forma es saber la identificación en ROM de cada elemento.
En mi caso uno de los 18B20 tiene la siguiente dirección:  byte addr[8]={0x28,0xDC,0x5C,0x16,0xA8,1,0x3C,0x28};
Esto me hubiese costado mucho, además solo voy a colocar un 18B20, por lo que utilizo un modo de lectura diferente.

SKIP ROM [CCh] Este comando puede ahorrar tiempo en un sistema de bus de caída única al permitir que el bus maestro acceda al funciones de memoria sin proporcionar el código ROM de 64 bits. Si hay más de un esclavo presente en el bus y se emite un comando de lectura después del comando Saltar ROM, se producirá una colisión de datos en el bus como múltiples esclavos transmiten simultáneamente (los pulldowns de drenaje abierto producirán un resultado AND cableado). www.dalsemi.com

-----------------------

AM2302_H=42.3%   T=24.7 ºC   Control=159

LDR-> RAW=236, voltaje=0.190137 V
BMP_TempGRADOS=23.30 ºC
BMP_Presion=933.90 bares
-----------------------


sen_p7
Por último colocamos un visualizardor tipo OLED
, el modelo SSD1306.
Lo bueno de colocar este modelo es que se conecta en el bus I2C, lo que resulta muy práctico y sencillo.

...
#include "ole.h"
char miBuffer[40];
...
main()
{
...
while(1)
    {
...
      xclearDisplay();
      StringAT(0,0,"--SETA43--");
     
      sprintf(miBuffer,"LDR=%d  %0.3fV",result,result * conversion_factor);
      StringAT(0,1,miBuffer);
     
      sprintf(miBuffer,"DHT_Hum. %.1f %c",(float)humedad/10,37);
      StringAT(0,2,miBuffer);
     
      sprintf(miBuffer,"DHT_Temp. %.1f %cC",(float)temperatura/10,127);
      StringAT(0,3,miBuffer);
     
      sprintf(miBuffer,"DS18b20_=%0.2f %cC",temp18B/10,127);
      StringAT(0,4,miBuffer);
     
      sprintf(miBuffer,"BMP_Pres.=%0.1f b ",(float)Presion/100);
      StringAT(0,5,miBuffer);
      sprintf(miBuffer,"BMP_Temp.=%0.1f %cC",(float)Temperatura/100,127);
      StringAT(0,6,miBuffer);
...
    }
}
Para utilizar el OLED, he empleado una biblioteca mía que realicé en arduino hace años.
Es simple de utilizar, solo hay que añadir el fichero ole.h , no tiene muchas funciones, pero hace su trabajo.

Cuando empecé a programar la raspberry pi pico, pensé que la transición sería más fácil, pero no fue así.
La cantidad de bibliotecas que existe en arduino no existen en raspberry.
El paso de programas entre arduino y rasberry no es inmediata, y muchos de los programas y biblitecas no funcionan,
Debemos pensar que los int en arduino son de 16bit, y en raspberry es de 32bit, esto genera muchos problemas.
Si queremos utilizar enteror de 16bit en raspberry, se debe utilizar
int16_t o uint16_t.

PROGRAMAS

Espero que este montaje os haya parecido interesante.

Saludos.

Juan Galaz



Bibliografía:

https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf
https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf
https://www.puntoflotante.net/termometro.htm
espgrs.html

28/02/2016 - Arduino - Predicción del tiempo. GY-68 - BMP-180.  Predicción
21/02/2016 - Arduino power low - Termómetro máximos y mínimos con gráfica - DS18B20 LCD Nokia PCD8544. Tempe
09/02/2016 - Arduino -Barómetro - Termómetro. GY-68 -  BMP-180. Parte 2 (librería propia). ArduBer
03/02/2016 - Arduino -Barómetro - Termómetro. GY-68 -  BMP-180. Parte 1.  ArduBar

viernes, 2 de septiembre de 2022

Raspberry pi pico - Programación microPython - Sensores

  Página principal

Raspberry pi pico
Programación microPython
Sensores:
LDR
DHT22 (AM2302)
BMP180
18B20
OLED DS1302



Anteriormente había realizado un visualizador de sensores con el ESP32.
En este artículo lo realizo con la Raspberry pi pico y programando en microPython.
Todo el montaje lo realizo en pasos, y grabado en vídeo, paso a paso.

El final del montaje queda de la siguiente forma:



El primer paso es colocar un led a modo de piloto de alimentación, y hacer parpadear el led que viene en la placa.

# SETA43
# seta43.duckdns.org
# seta43.blogspot.com
# Palencia / España
# 31-08-2022

import machine
import utime

led = machine.Pin(25, machine.Pin.OUT)

while True:
    led.value(0)
    utime.sleep(0.5)
    led.value(1)
    utime.sleep(0.5)


En este paso colocamos un sensor de temperatura y humedad
El sensor es el DHT22 o su equivalente AM2302.

# SETA43
# seta43.duckdns.org
# seta43.blogspot.com
# Palencia / España
# 31-08-2022

import machine
import utime

led = machine.Pin(25, machine.Pin.OUT)

from DHT22 import DHT22
from machine import Pin

dht_sensor=DHT22(Pin(15),dht11=False)

while True:
    #--DHT22--------------------------------------------   
    T, H = dht_sensor.read()
    if T is None:
        print("Error en el sensor!")
    else:
        print("Sensor DHT22->","{}ºC  {}%".format(T,H))

    led.value(0)
    utime.sleep(0.5)
    led.value(1)
    utime.sleep(0.5)


En este paso ponemos un sensor de luz tipo LDR, y leemos el valor mediante un conversor ADC.

# SETA43
# seta43.duckdns.org
# seta43.blogspot.com
# Palencia / España
# 31-08-2022

import machine
import utime

led = machine.Pin(25, machine.Pin.OUT)

from DHT22 import DHT22
from machine import Pin

dht_sensor=DHT22(Pin(15),dht11=False)

analog_value = machine.ADC(28)


while True:
    #--DHT22--------------------------------------------   
    T, H = dht_sensor.read()
    if T is None:
        print("Error en el sensor!")
    else:
        print("Sensor DHT22->","{}ºC  {}%".format(T,H))
       
    #--LDR--------------------------------------------
    reading = analog_value.read_u16()    
    print("LDR-> ADC: ",reading)   

    led.value(0)
    utime.sleep(0.5)
    led.value(1)
    utime.sleep(0.5)


En este paso colocamos un sensor de presión que además dispone de un sensor de temperatura.
El sensor viene en un módulo BMP180, los datos se mandan mediante el bus I2C.
Con este sensor se puede calcular la altura.

# SETA43
# seta43.duckdns.org
# seta43.blogspot.com
# Palencia / España
# 31-08-2022

import machine
import utime
from bmp180 import BMP180
from machine import I2C, Pin

led = machine.Pin(25, machine.Pin.OUT)

from DHT22 import DHT22
from machine import Pin

dht_sensor=DHT22(Pin(15),dht11=False)

analog_value = machine.ADC(28)

i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=200000) 
bmp180 = BMP180(i2c)
bmp180.oversample_sett = 2
baseline = bmp180.pressure/100
ALTURA = 790

print ("Doble sensor DHT22 y DS18x20")
#Write in cmd found addresses

i2cScan = i2c.scan()
counter = 0
for i in i2cScan:
    print('I2C Address ' + str(counter) + '      : '+hex(i).upper())
print ("**************************")
#---------------


while True:
    #--DHT22--------------------------------------------   
    T, H = dht_sensor.read()
    if T is None:
        print("Error en el sensor!")
    else:
        print("Sensor DHT22->","{}ºC  {}%".format(T,H))
       
    #--LDR--------------------------------------------
    reading = analog_value.read_u16()    
    print("LDR-> ADC: ",reading)
   
    #..BMP180---------------------------------------------   
    temperatura = bmp180.temperature
    presion = bmp180.pressure/100
    alt2=44330.0* (1-pow(presion/baseline,1/5.255) )   
    alt2=ALTURA+alt2
       
    alt2=round(alt2)
    temperatura=round(temperatura,1)
    presion=round(presion)
           
    print("Tem_BMP180=",temperatura,"ºC Presion=", presion," ALTITUD=",alt2)

    led.value(0)
    utime.sleep(0.5)
    led.value(1)
    utime.sleep(0.5)


En este paso colocamos un sensor de temperatura 18B20.
Este chip se comunica mediante una sola línea de datos, y si se quiere se puede utilizar solo dos lineas, para hacer funcionar el sensor.
Además se pueden colocar varios chip en paralelo, que se podrán leer sus temperaturas independientemente.
El esquema solo utilizo un sensor, en la practica utilizo 2 chip con sus respectivas lecturas.

# SETA43
# seta43.duckdns.org
# seta43.blogspot.com
# Palencia / España
# 31-08-2022

import machine
import utime
from bmp180 import BMP180
from machine import I2C, Pin
import onewire, ds18x20, time

led = machine.Pin(25, machine.Pin.OUT)

from DHT22 import DHT22
from machine import Pin

dht_sensor=DHT22(Pin(15),dht11=False)

analog_value = machine.ADC(28)

i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=200000) 
bmp180 = BMP180(i2c)
bmp180.oversample_sett = 2
baseline = bmp180.pressure/100
ALTURA = 790

print ("Doble sensor DHT22 y DS18x20")
#Write in cmd found addresses

i2cScan = i2c.scan()
counter = 0
for i in i2cScan:
    print('I2C Address ' + str(counter) + '      : '+hex(i).upper())
print ("**************************")
#---------------

ds_pin = machine.Pin(22)
ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin))
roms = ds_sensor.scan()

while True:
    #--DHT22--------------------------------------------   
    T, H = dht_sensor.read()
    if T is None:
        print("Error en el sensor!")
    else:
        print("Sensor DHT22->","{}ºC  {}%".format(T,H))
       
    #--LDR--------------------------------------------
    reading = analog_value.read_u16()    
    print("LDR-> ADC: ",reading)
   
    #..BMP180---------------------------------------------   
    temperatura = bmp180.temperature
    presion = bmp180.pressure/100
    alt2=44330.0* (1-pow(presion/baseline,1/5.255) )   
    alt2=ALTURA+alt2
       
    alt2=round(alt2)
    temperatura=round(temperatura,1)
    presion=round(presion)
           
    print("Tem_BMP180=",temperatura,"ºC Presion=", presion," ALTITUD=",alt2)
   
    #--DS18B20--------------------------------------------
    ds_sensor.convert_temp()
    time.sleep_ms(750)
    x=0
    for rom in roms:
        #print ("Sensor=",x,"  ",rom,"  Temperatura=",ds_sensor.read_temp(rom))
        print ("Sensor_DS18B20_nº",x,"  ","  Temperatura=",ds_sensor.read_temp(rom))
        x=x+1
   
    print("---------------------")
    led.value(0)
    utime.sleep(0.5)
    led.value(1)
    utime.sleep(0.5)


Por último colocamos un visualizardor tipo OLED , el modelo SSD1306.
Lo bueno de colocar este modelo es que se conecta en el bus I2C, lo que resulta muy práctico y sencillo.

# SETA43
# seta43.duckdns.org
# seta43.blogspot.com
# Palencia / España
# 31-08-2022

import machine
import utime
from bmp180 import BMP180
from machine import I2C, Pin
import onewire, ds18x20, time

from DHT22 import DHT22
from machine import Pin
from ssd1306 import SSD1306_I2C

led = machine.Pin(25, machine.Pin.OUT)

dht_sensor=DHT22(Pin(15),dht11=False)

analog_value = machine.ADC(28)

i2c = I2C(0, scl=Pin(1), sda=Pin(0), freq=200000) 
bmp180 = BMP180(i2c)
bmp180.oversample_sett = 2
baseline = bmp180.pressure/100
ALTURA = 790

WIDTH  = 128                                            # oled display width
HEIGHT = 64
oled = SSD1306_I2C(WIDTH, HEIGHT, i2c)

print ("Doble sensor DHT22 y DS18x20")
#Write in cmd found addresses

i2cScan = i2c.scan()
counter = 0
for i in i2cScan:
    print('I2C Address ' + str(counter) + '      : '+hex(i).upper())
print ("**************************")
#---------------

ds_pin = machine.Pin(22)
ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin))
roms = ds_sensor.scan()

while True:
    #--DHT22--------------------------------------------   
    T, H = dht_sensor.read()
    if T is None:
        print("Error en el sensor!")
    else:
        print("Sensor DHT22->","{}ºC  {}%".format(T,H))
       
    #--LDR--------------------------------------------
    reading = analog_value.read_u16()    
    print("LDR-> ADC: ",reading)
   
    #..BMP180---------------------------------------------   
    temperatura = bmp180.temperature
    presion = bmp180.pressure/100
    alt2=44330.0* (1-pow(presion/baseline,1/5.255) )   
    alt2=ALTURA+alt2
       
    alt2=round(alt2)
    temperatura=round(temperatura,1)
    presion=round(presion)
           
    print("Tem_BMP180=",temperatura,"ºC Presion=", presion," ALTITUD=",alt2)
   
    #--DS18B20--------------------------------------------
    ds_sensor.convert_temp()
    time.sleep_ms(750)
    x=0
    for rom in roms:
        #print ("Sensor=",x,"  ",rom,"  Temperatura=",ds_sensor.read_temp(rom))
        print ("Sensor_DS18B20_nº",x,"  ","  Temperatura=",ds_sensor.read_temp(rom))
        x=x+1
   
    oled.fill(0)
    oled.text("-Seta43- ",0,8)
    tmp=str(T)+" C  DHT22"
    oled.text(tmp,0,16)
    tmp=str(H)+" %  DHT22"
    oled.text(tmp,0,24)
    tmp=str(presion)+" mBa BMP180"
    oled.text(tmp,0,32)
    tmp=str(alt2)+   " m   BMP180"
    oled.text(tmp,0,40)
    tmp=str(reading)+" luz LDR"
    oled.text(tmp,0,48)
    oled.show()

   
    print("---------------------")
    led.value(0)
    utime.sleep(0.5)
    led.value(1)
    utime.sleep(0.5)


Como se puede entender, para el funcionamiento de todo, se hace uso de varias librerías.
Para que funcione las librerías deben ser copiadas a la raspberry pi pico.

 

PROGRAMAS Y LIBRERÍAS

VÍDEO


Espero que este montaje os haya parecido interesante.

Saludos.

Juan Galaz



Bibliografía:

https://datasheets.raspberrypi.com/pico/raspberry-pi-pico-c-sdk.pdf
https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf
seta_PIB
seta_PIA
https://lindevs.com/set-up-raspberry-pi-pico-sdk-on-ubuntu
https://www.electroniclinic.com/raspberry-pi-pico-rp2040-programming-in-micropython-with-examples/
https://www.youtube.com/watch?v=2gihPgEkvL8
https://picockpit.com/raspberry-pi/es/todo-sobre-la-frambuesa-pi-pico/


miércoles, 26 de mayo de 2021

ESP32 - SENSORES II , BMP180, XFW-HX711.

ESP32-  SENSORES II

BMP180
XFW-HX711


En el anterior artículo ESP32 - SENSORES había realizado con el ESP32 un visualizador de sensores, en este proyecto añado otros dos, BMP180, XFW-HX711.
El BMP180 es un detector de presión, y el XFW-HX711 es un detector de peso.
Este montaje también lo he realizado con un arduino nano, bmp180.html , por lo cual no explicare mucho el montaje.
La explicación de la calibración del módulo de peso se encuentra en
bmp180.html .
Para la lectura del BMP180 he utilizado una rutina propia, que al proceder de un arduino, he tenido que modificar el tipo de datos, de int a int16_t, y de long a int32_t .
Por lo demás no he modificado nada al traspasar el programa, salvo los pins de conexión.


Esquema realizado con https://easyeda.com.


Circuito montado.

Peso de 5 monedas de 50 Céntimos.


Visualización de los datos en un navegador.


Diagrama de señales en el
XFW-HX711, convertidor A/D de 24bits.

Este proyecto me ha servido para ponerme en contacto con el ESP32, y ver todas sus posibilidades.
Espero que les haya gustado.


PROGRAMAS Y LIBRERÍAS

Saludos.
Juan Galaz


Bibliografía:

https://naylampmechatronics.com/blog/25_tutorial-trasmisor-de-celda-de-carga-hx711-balanza-digital.html
28/02/2016 - Arduino - Predicción del tiempo. GY-68 - BMP-180.  Predicción
21/02/2016 - Arduino power low - Termómetro máximos y mínimos con gráfica - DS18B20 LCD Nokia PCD8544. Tempe
09/02/2016 - Arduino -Barómetro - Termómetro. GY-68 -  BMP-180. Parte 2 (librería propia). ArduBer
03/02/2016 - Arduino -Barómetro - Termómetro. GY-68 -  BMP-180. Parte 1.  ArduBar
https://randomnerdtutorials.com/esp32-dht11-dht22-temperature-humidity-sensor-arduino-ide/
https://randomnerdtutorials.com/installing-the-esp32-board-in-arduino-ide-windows-instructions/
https://www.profetolocka.com.ar/2020/07/09/programando-el-esp-32-con-el-arduino-ide/
https://www.prometec.net/presentando-el-esp32/


lunes, 24 de mayo de 2021

ARDUINO - SENSORES - BMP180- XFW-HX711.

ARDUINO - SENSORES

BMP180
XFW-HX711


El otro día me llego dos módulos que había pedido, el BMP180 (un viejo conocido con el cual había realizado 3 proyectos, y el XFW-HX711, un sensor  de peso.
Quería añadir los dos módulos al ESP32, pero quería antes probarlos en un arduino nano.

En primer lugar he realizado el montaje del sensor de presión, que muestra los datos en un OLED y en el terminal serie.
Para este montaje he utilizado el antiguo montaje :
Barómetro - Termómetro. GY-68 -  BMP-180. Parte 2 (librería propia). ArduBer , pero adaptándolo al OLED.
Como se puede observar lo he alimentado con 3V3 , para probar si funcionaría con el ESP32, aunque funciona también a 5V.
Lo bueno de este proyecto es que utilizan los dos módulos el protocolo I2C, lo que facilita mucho el diseño.




PROGRAMA


Como ya tenía montado el circuito de sensor de presión, he añadido el sensor de peso.
Como tutorial he seguido los pasos de:https://naylampmechatronics.com/blog/25_tutorial-trasmisor-de-celda-de-carga-hx711-balanza-digital.html
He añadido una línea donde figura el peso en gramos.
Empezamos explicando un poco el funcionamiento del módulo de pesaje.

Cuando un conductor se estira, su resistencia aumenta. Cuando está comprimido, su resistencia disminuye.
A estas piezas de metal la llamaremos Celdas De Carga.
Esta resistencia se mide con un convertidor A/D de 24bits , HX711, que transmite los dados mediante protocolo serie propio al arduino.

 



Una vez que tenemos montado el circuito, debemos calibrarlo.
El método es utilizar un objeto que sepamos su peso, yo he utilizado uno que antes había pesado en una báscula.
En mi caso había utilizado dos POWER_BANK que en total pesaban 133 grs.
Lo ideal es utilizar un peso que se ajuste al máximo de peso de la celda de carga, no es mi caso.
Ahora con el siguiente programa mido el valor que nos devuelve el módulo.

#include "HX711.h"
const int DOUT=2;
const int CLK=3;

HX711 balanza;
void setup() {
  Serial.begin(9600);
  balanza.begin(DOUT, CLK);
  Serial.print("Lectura del valor del ADC:t");
  Serial.println(balanza.read());
  Serial.println("No ponga ningún objeto sobre la balanza");
  Serial.println("Destarando...");
  balanza.set_scale(); //La escala por defecto es 1
  balanza.tare(20);  //El peso actual es considerado Tara.
  Serial.println("Coloque un peso conocido:");
}

void loop() {

  Serial.print("Valor de lectura: t");
  Serial.println(balanza.get_value(10),0);
  delay(100);
}


Con un peso de 133 grs nos proporciona una medida de 261425 .
Con el dato obtenido  hacemos un cálculo:
    261425:0.133 grs =1965601
El valor obtenido de la operación lo colocamos en:

    #define AJUSTE 1965601
    balanza.set_scale(AJUSTE);

Con esto ya podemos medir el peso de un objeto.
Debemos saber que cuando se reinicia el programa toma un primer peso que coloca como tara, para luego restarlo del peso total.



Peso de una POWER-BANK de 65grs, que corresponde al peso real.




Detalle de la celda de carga.



Peso de dos monedas de 50 CENT, que corresponde al valor real.
El circuito funciona muy bien, con una precisión alta.

Espero que les guste este proyecto.

PROGRAMA Y LIBRERÍA

Saludos.
Juan Galaz

Bibliografía:
https://naylampmechatronics.com/blog/25_tutorial-trasmisor-de-celda-de-carga-hx711-balanza-digital.html
28/02/2016 - Arduino - Predicción del tiempo. GY-68 - BMP-180.  Predicción
21/02/2016 - Arduino power low - Termómetro máximos y mínimos con gráfica - DS18B20 LCD Nokia PCD8544. Tempe
09/02/2016 - Arduino -Barómetro - Termómetro. GY-68 -  BMP-180. Parte 2 (librería propia). ArduBer
03/02/2016 - Arduino -Barómetro - Termómetro. GY-68 -  BMP-180. Parte 1.  ArduBar



lunes, 29 de abril de 2019

Sensores 18B20 LDR BMP180 DHT22, Arduino - Gambas - Python

Página principal


Sensores

18B20 LDR BMP180 DHT22

Arduino - Gambas - Python


Debía realizar un circuito electrónico para añadir a una página web donde indicara la temperatura ambiente.
La idea era solo colocar un sensor de temperatura 18B20, pero se me ocurrió añadir mas sensores.
En este circuito coloco varios sensores:
-18B20 sensor de temperatura.
-LDR sensor de luz.
-BMP180 sensor de presión y temperatura.
-DHT220 sensor de temperatura y humedad. (he utilizado el equivalente AM2302)


Todos los datos de estos sensores se transmiten al PC mediante el terminal serie.

Circuito montado.


Circuito.

Para la representación de los datos he utilizado dos programas.
El primero está realizado en Gambas (VB para linux).
El segundo realizado en Python.
En ambos programas busca la placa de sensores dentro de todos los posibles puertos serie.
Si encuentra el módulo de sensores los representa en pantalla.
Toda la programación se ha realizado en el entorno Linux con la distribución Debian 9.
La información de sensores se manda cada 5 segundos.
Su transformación para que funcionase en Windows en el caso de Phyton es fácil, solo cambiar la lista de dispositivos serie.

Programa Gambas (VB para linux).


Programa Phyton.

El montaje es perfecto para probar sensores.
Si no tenéis alguno de los sensores, deberéis anular el código correspondiente al sensor en el programa del arduino.

PROGRAMAS

VIDEO





Saludos.
Juan Galaz


Bibliografía:
predi.html
raspb.html
arterec.html
tm16tem.html




domingo, 28 de febrero de 2016

Arduino-Predicción del tiempo - BMP180

Arduino
Barómetro - Termómetro
Predicción del tiempo
GY-68    BMP-180
Parte 3


Para terminar con esta serie de artículos sobre el BMP-180, voy a intentar realizar un aparato de predicción del tiempo tomando como referencia la variación de la presión.
En este montaje mostramos la presión y la temperatura actual, y una gráfica de variación de la presión atmosférica.
En esta gráfica de la variación de la presión atmosférica se muestran 84 valores, tomados cada 15 minutos, que corresponden a 21 horas.
Para predecir el tiempo debemos interpretar la gráfica. Como yo no tengo los suficientes conocimientos, he tenido que buscar en internet información. Unas explicaciones sencillas que he encontrado son las siguientes:

Reglas de predicción casera

Si la presión desciende lentamente, por debajo del nivel normal de referencia (  unos 6 mm. cada 24 horas), la borrasca pasa lejos.
Si la presión desciende rápida ( 1 mm. cada hora), se acerca una profunda borrasca.
Si el barómetro sube lentamente por encima del valor normal, se afianza buen tiempo seco y encalmado, de anticiclón.
Si el barómetro sube muy bruscamente, la mejoría puede ser pasajera, por tratarse del paso de una dorsal anticiclónica entre dos borrascas.
En general, los cambios bruscos de presión -subida o bajada- son bastante indecisos para asegurar persistencia del tiempo. Habrá que seguir observando.
Las subidas de presión en zonas costeras o valles, donde el aire tiene mucha densidad incorporada, no siempre dan buen tiempo de cielo despejado y seco, ya que pueden formarse persistentes bancos de niebla. De ésto saben mucho ciudades como Zaragoza, Lérida, Valladolid, Salamanca… o bien Pontevedra, Bilbao, Barcelona…
El refranero popular  recoge el comportamiento del barómetro en expresiones como
    "Cuando sube la presión, te puedes ir de excursión"
    "Si la presión baja y viene mezquino, mejor quedarse en el casino"
    "Si baja y viene borrasca, puedes quedarte en la tasca"

Ya hemos indicado que no siempre es seguro  el asociar a la subida de la presión el buen tiempo, ni a su bajada el mal tiempo,  nubes, viento o lluvia … De ahí que los rótulos del barómetro no sean fiables. ¡ Si fuese todo tan fácil!


Donde 1 mm. = 4/3 mb. = 1,3 mb

Fuente:  http://www.tiempo.com/ram/150/adecuado-uso-del-barometro/#more-150



La regla general es:

-Si observamos una bajada de presión de menos de 1 milibar (o hectopascal) cada hora la borrasca pasará lejos y el viento será flojo o moderado.
-Si el descenso de presión es de 1 mb por hora, el tiempo irá empeorando a un ritmo mayor y el frente que se descuelga de la borrasca nos llegará a afectar. Viento moderado.
-Descensos de 1,5 a 2  mb por hora ya nos avisan de que el viento será fuerte y la mar empeorará rápido.
-Descensos de más de 2 mb por hora indican algo serio. Borrascas fuertes, galernas o ciclogénesis explosivas. Hay que tener cuidado en la mar.


Fuente: http://isocero.blogspot.com.es/2012/09/el-barometro.html

En nuestra gráfica muestra variaciones de presión respecto a la presión actual de 1 mb por unidad del eje Y , con un máximo de mas-menos 12 mb. En el eje X hay 84 unidades tomada cada 15 minutos, 21 horas.

Esquema del circuito.

Como vemos el esquema está realizado en arduino uno y el montaje en arduino nano, se ha hecho por lo fácil que resulta montarlo con un arduino nano, pero la representación en esquema es mejor en arduino uno.
La alimentación del LCD se hace a 3.3V, aunque funciona también a 5V, pero no he querido forzar el LCD.


Circuito montado.



Gráfica de lluvia.
Gráfica de mejora de tiempo.

Para el cálculo de la predicción utilizo los 16 últimos valores (4 horas), y según la variación de presión determino una predicción. No siempre es seguro  el asociar a la subida de la presión el buen tiempo, ni a su bajada el mal tiempo,  nubes, viento o lluvia. Para un mejor previsión  se debería tener en cuenta la temperatura y humedad, pero eso es tema de otro montaje.

Me acuerdo cuando mi madre me comentaba que iba a cambiar el tiempo cuando una escalera de piedra se humedecía.
Tenía mucha razón, el aumento de temperatura y humedad en contraste con la temperatura de la piedra, hacía que se condensara agua sobre la piedra. Esto casi siempre adelantaba un frente de agua.
También mi madre me comentaba que los cambios de luna traían un cambio de tiempo. Mi padre sobre esta cuestión tenía dudas, decía que si la luna cambiaba cada 7 días, alguna vez se tenía que acertar.

Hay muchos indicios sobre el cambio de tiempo en la naturaleza, y el que tengo como más fiable son las hormigas. Cuando el hormiguero se pone alborotado, y salen las hormigas voladoras, es un preludio de lluvias.



PROGRAMA


Saludos.
Juan Galaz

Bibliografía:

http://www.tiempo.com/ram/150/adecuado-uso-del-barometro/#more-150
https://prezi.com/2imcmqrc0mhk/como-se-predice-el-estado-del-tiempo/
http://isocero.blogspot.com.es/2012/09/el-barometro.html
http://www.eldiario.es/hojaderouter/ciencia/meteorologia-moviles-aplicaciones-tiempo-prediccion_0_284522231.html
http://msrobotics.net/index.php/laboratorio-ard/110-sensor-de-presion-atmosferica-con-arduino-y-gy-68-bmp180
https://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf
http://casanchi.com/fis/modeloteorico/modeloteorico.htm
https://es.answers.yahoo.com/question/index?qid=20100212141717AAJTMI4

martes, 9 de febrero de 2016

Arduino Barómetro - Termómetro GY-68 BMP-180 Parte 2

Página principal


Arduino
Barómetro - Termómetro
GY-68    BMP-180

Parte 2


En esta segunda parte realizo mi propia librería para leer los datos del BMP-180.
Otra de las cosas que me he propuesto en el programa, es no utilizar los tipos de datos  double o float para los cálculos, de esta manera reduzco considerablemente el tamaño del programa, de 12,5K a 8,2K.
También he querido poner todo el conjunto del programa en un único fichero, de esta forma no se necesita ninguna librería aparte.



Para facilitar el programa he puesto el modo Oss controls the oversampling ratio of the pressure measurement (register F4h <7:6>): a modo 00b single. Esto repercute en la exactitud de la medida de la presión, de ser la lectura de 3 bytes a ser de 2 bytes. Aunque se lean 3 bytes para la presión, el último byte en este modo es 0.
Lo primero que se hace es leer 11 palabras de 16bit, es un coeficiente de calibración que se encuentra en una memoria EPROM del propio chip.
Con todos los datos leídos de la calibración del chip se realizan los cálculos.
En la página 15 del Data sheet del chip BMP180 se explica todos los cálculos.


  b6=b5-4000;
  x1=b6*b6;  x1=x1>>12;  x1=x1*VB2;  x1=x1>>11;
  x2=AC2;  x2=x2*b6; x2=x2>>11;
  x3=x2+x1;
  b3=AC1; b3=b3<<2; b3=b3+x3; b3=b3+2; b3=b3>>2;
  x1=AC3; x1*=b6;  x1=x1>>13;
  x2=b6*b6; x2=x2>>12; x2=x2*VB1; x2=x2>>16;
  x3=x1+x2;  x3=x3+2; x3=x3>>2;
  b4=x3;  b4=b4+32768;  b4=b4*AC4;  b4=b4>>15;
  b7=mpu-b3;  b7=b7*50000;
  if(b7<0x80000000)
    {
      p=b7; p=p<<1; p=p/b4;
    }
    else
    {
      p=b7/b4;  p=p<<1;
    }
  x1=p;  x1=x1>>8;  x1=x1*x1;
  x1=x1*3038;  x1=x1>>16;
  x2=-7357;  x2*=p;  x2=x2>>16;
  x1+=x2;  x1=x1+3791; x1=x1>>4;  p+=x1;
  Presion=p;
Ejemplo de como se realiza el cálculo de la presión.

Como podéis observar he troceado las fórmulas en cálculos sencillos, no empleando mas de dos operadores por operación. Ha sido una tarea un tanto trabajosa, pero creo que ha merecido la pena.

Una vez que tenemos la temperatura y la presión en la variables globales long Temperatura,Presion, nos toca representar los cálculos.
Para los cálculos de diferencia de altura, debemos haber realizado al inicio del programa un cálculo de la presión, para luego compararla con la presión nueva a diferente altura y hacer los cálculos.
Existe una formula que emplea números del tipo de coma flotante double, pero como mi intención es solo utilizar números enteros he tenido que emplear otra formula reducida pero que tiene margen de error.

 
 Fórmula para el cálculo de variación de altura a diferentes presiones.

A nivel del mar la variación de altura por 1hPa es de 8,43m , en lo cálculos que he hecho ami me salió 8,33m para obtener el menor error.
A  mayores altitudes como 790m la variación llega a 9 m por 1hPa, es el que he empleado yo.





Tablas de los diferentes cálculos a diferentes cambios de presión.

Para hacer las pruebas prácticas he tenido que recurrir a mi edificio de 12 plantas. La altura de cada planta es de 2,73 m, por lo que el total de altura es de 32,76 m.
En la prueba la medida obtenida fue de 33 m, aunque variaba constantemente arriba y abajo.

Espero que os haya gustado, y si os sirve para algo me comentéis vuestras  impresiones.


PROGRAMA


Saludos.
Juan Galaz

Bibliografía:

http://msrobotics.net/index.php/laboratorio-ard/110-sensor-de-presion-atmosferica-con-arduino-y-gy-68-bmp180
https://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf
http://casanchi.com/fis/modeloteorico/modeloteorico.htm
https://es.answers.yahoo.com/question/index?qid=20100212141717AAJTMI4

miércoles, 3 de febrero de 2016

Arduino Barómetro - Termómetro. GY-68 BMP-180 . Parte 1

Página principal


Arduino
Barómetro - Termómetro
GY-68    BMP-180

Parte 1


En este montaje utilizo el módulo GY-68  que está formado por el chip BMP-180 y el regulador de 3.3V para alimentar el chip.


GY-68
 Esquema del modulo GY-68 (BMP180 y regulador de 3.3V)
Existen otros módulos que llevan el BMP180 y no llevan regulador, por lo cual lo debemos alimentar a 3.3V. En este caso el módulo GY-68 lo podemos alimentar a 5V.

El BMP180 está fabricado por Bosch y en  su hoja de características explica lo siguiente:

3.2 General function and application schematics
The BMP180 consists of a piezo-resistive sensor, an analog to digital converter and a control unit
with E 2 PROM and a serial I 2 C interface. The BMP180 delivers the uncompensated value of pressure
and temperature. The E 2 PROM has stored 176 bit of individual calibration data. This is used to
compensate offset, temperature dependence and other parameters of the sensor.
    -UP = pressure data (16 to 19 bit)
    -UT = temperature data (16 bit)

Pressure range:  
     300 ... 1100hPa (+9000m ... -500m relating to sea level)
Storage temperature
    -40 +85 °C
Supply voltage:
    1.8 ... 3.6V (V DD )
    1.62V ... 3.6V (V DDIO )


De lo que podemos entender que tiene un sensor de presión  que mide presiones entre 300 y 1100 hPa.
Además tenemos un sensor de temperatura que puede medir entre -40 y +85 ºC.
Todo esto alimentado por una tensión entre 1.8 ... 3.6V.
El consumo es entre 3uA y 1mA dependiendo del modo en que trabaje.

En este montaje montaremos el arduino  junto con el GY-68, y visualizaremos los datos en un LCD Nokia 3310 además de por el terminal serie.


Esquema del circuito.

Montaje de circuito.
Montaje de circuito.

Como vemos el esquema está realizado en arduino uno y el montaje en arduino nano, se ha hecho por lo fácil que resulta montarlo con un arduino nano, pero la representación en esquema es mejor en arduino uno.
La alimentación del LCD se hace a 5V, aunque funciona también a 5V, pero no he querido forzar el LCD.
Todo el conjunto funciona también alimentado con 3.3V , pero en este caso conviene alimentar el LCD directamente a 3.3V.

Para el programa en arduino he utilizado la librería SFE_BMP180   https://github.com/LowPowerLab/SFE_BMP180 que ahorra considerablemente la programación del BMP180. En dicha librería hay dos ejemplos, uno de ellos he utilizado para mi programa , modificándolo a mi gusto.
He añadido al programa las rutinas para controlar el LCD Nokia 3310 donde se representan las diferentes medidas.
Para poder medir el cambio altitud, debemos introducir la altura donde se encuentra el circuito en ese momento.
En el programa se introduce en la línea:
// altura en Palencia
#define ALTURA 790

Cuando se inicia el programa se toma la presión de referencia a esa altura. Entonces cualquier variación de dicha presión la interpreta como variación de altura.
Debemos tener en cuenta que la presión varía en función del tiempo atmosférico, por lo cual no serviría la altitud si no se reinicia el programa para tomar la presión de referencia.
La prueba que he realizado para comprobar de que funciona la detección del cambio de altitud la he realizado en un ascensor, donde lo he verificado perfectamente como cambiaba. Desde la planta baja que me medía 755m hasta la planta 12 que me medía 790m de referencia.
Si por ejemplo no hubiese apagado el circuito y hubiese cambiado las condiciones atmosférica, nos hubiéramos dado cuenta que se subía o bajaba de altitud sin habernos movido.

En esta primera parte vemos como funciona el chip BMP180, en un próximo montaje quiero realizar un montaje que prediga el tiempo atmosférico por cambio de presión, además de un medidor de temperatura.

PROGRAMA


Saludos.
Juan Galaz

Bibliografía:

http://msrobotics.net/index.php/laboratorio-ard/110-sensor-de-presion-atmosferica-con-arduino-y-gy-68-bmp180
https://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf