martes, 18 de octubre de 2022

Transistor Téster para Arduino Nano - Visualización en Android

  Página principal



Transistor Téster para Arduino Nano
Visualización en Android


En un montaje anterior había realizado un analizador de componentes llamado  TransistorTester, cuyo autor era  Karl-Heinz Kübbeler .
Según la configuración del programa se podía utilizar diferentes tipos de visualizadores, en mi caso había utilizado un OLED.
También posteriormente había realizado un programa en gambas y Visual Basic  para representar datos.
  12/12/2021 - Transistor Tester para Arduino Nano.representación en PC con Gambas (VB linux). GTESTER
Para los que deseen utilizar un dispositivo android a modo de presentación de resultados del téster, he programado una aplicación en android para representar los resultados.
Como el arduino no tiene conexión bluetooth, he añadido un módulo de bluetooth a serie HC-05.
Anteriormente había realizado :
  03/06/2021 - Balanza con XFW-HX711 - ESP32 - Bluetooth -Interface Android. ESP_Bluetooth
He utilizado parte del código de android y lo he modificado para este montaje.


El módulo HC-05 debemos conectarlo con 3 cables al arduino, GND-VCC- (TX.arduino->RX.hc05).
Si queremos cambiar el nombre y contraseña del dispositivo bluetooth  HC05, podéis ver el modo en ardisx.html.

Circuito montado.


Programa android.


PROGRAMAS ANDROID Y ARDUINO

VIDEO DEMOSTRATIVO

Saludos.
Juan Galaz



Bibliografía:

https://github.com/kr4fty/Ardutester
https://www.sysadminsdecuba.com/2020/08/ardutester-tester-de-componentes-con-arduino/
https://create.arduino.cc/projecthub/mircemk/diy-super-simple-electronic-component-tester-234752
https://create.arduino.cc/projecthub/plouc68000/ardutester-v1-13-the-arduino-uno-transistor-tester-dbafb4
12/12/2021 - Transistor Tester para Arduino Nano.representación en PC con Gambas (VB linux). GTESTER
03/06/2021 - Balanza con XFW-HX711 - ESP32 - Bluetooth -Interface Android. ESP_Bluetooth

miércoles, 12 de octubre de 2022

Raspberry pi pico - Programación C - Vídeo-tutorial.

 

Raspberry pi pico
Programación C
Vídeo-tutorial.



 

Es simplemente un video-tutorial de un montaje de sensores en la placa Raspberry pi pico.
Aunque veréis que se hace las conexiones con la alimentación puesta, yo recomiendo que se la quitéis.
Para mas detalle sobre las librerías, recomiendo ver mi anterior montaje. pidc.html

VÍDEO

PROGRAMAS



Saludos.

Juan Galaz

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