¿Cómo convertir el código Arduino a Mikrobasic (Electronica Co) para el sensor térmico IR?

0

Tengo un sensor térmico IR (mlx90614 con este hoja de datos ) De acuerdo con la hoja de datos, la comunicación con el sensor es de esta manera:

Algunosejemplosestánaquí: mlx90614 example arduino

El código para trabajar con Arduino Base está aquí:

#include <i2cmaster.h>
void setup(){
Serial.begin(9600);
Serial.println("Setup...");

i2c_init(); //Initialise the i2c bus
PORTC = (1 << PORTC4) | (1 << PORTC5);//enable pullups

}
void loop(){
int dev = 0x5A<<1;
int data_low = 0;
int data_high = 0;
int pec = 0;

i2c_start_wait(dev+I2C_WRITE);
i2c_write(0x07);

// read
i2c_rep_start(dev+I2C_READ);
data_low = i2c_readAck(); //Read 1 byte and then send ack
data_high = i2c_readAck(); //Read 1 byte and then send ack
pec = i2c_readNak();
i2c_stop();

//This converts high and low bytes together and processes temperature, MSB is a error bit and is ignored for temps
double tempFactor = 0.02; // 0.02 degrees per LSB (measurement resolution of the MLX90614)
double tempData = 0x0000; // zero out the data
int frac; // data past the decimal point

// This masks off the error bit of the high byte, then moves it left 8 bits and adds the low byte.
tempData = (double)(((data_high & 0x007F) << 8) + data_low);
tempData = (tempData * tempFactor)-0.01;

float celcius = tempData - 273.15;
float fahrenheit = (celcius*1.8) + 32;

Serial.print("Celcius: ");
Serial.println(celcius);

Serial.print("Fahrenheit: ");
Serial.println(fahrenheit);

delay(1000); // wait a second before printing again



}

SOY necesito cambiar este código para mi programación mikrobasic el avr, así que he cambiado esos códigos y he hecho este código:

    program mlx60914
symbol LCD_RS_my = PORTc7_bit
  symbol LCD_EN_my =PORTc6_bit
  symbol LCD_D4_my =PORTc2_bit
  symbol LCD_D5_my=PORTc3_bit
  symbol LCD_D6_my =PORTc4_bit
  symbol LCD_D7_my=PORTc5_bit

  symbol LCD_RS_Direction_my = DDc7_bit
  symbol LCD_EN_Direction_my =DDc6_bit
  symbol LCD_D4_Direction_my =DDc2_bit
  symbol LCD_D5_Direction_my=DDc3_bit
  symbol LCD_D6_Direction_my =DDc4_bit
  symbol LCD_D7_Direction_my=DDc5_bit
dim  celcius,fahrenheit as float
txt1 as string[6]

' Lcd module connections
dim LCD_RS as sbit at LCD_RS_my
dim LCD_EN as sbit at LCD_EN_my
dim LCD_D4 as sbit at LCD_D4_my
dim LCD_D5 as sbit at LCD_D5_my
dim LCD_D6 as sbit at LCD_D6_my
dim LCD_D7 as sbit at LCD_D7_my

dim LCD_RS_Direction as sbit at LCD_RS_Direction_my
dim LCD_EN_Direction as sbit at LCD_EN_Direction_my
dim LCD_D4_Direction as sbit at LCD_D4_Direction_my
dim LCD_D5_Direction as sbit at LCD_D5_Direction_my
dim LCD_D6_Direction as sbit at LCD_D6_Direction_my
dim LCD_D7_Direction as sbit at LCD_D7_Direction_my

dim Soft_I2C_Scl_Output    as sbit at PORTC0_bit
    Soft_I2C_Sda_Output    as sbit at PORTC1_bit
    Soft_I2C_Scl_Input     as sbit at PINC0_bit
    Soft_I2C_Sda_Input     as sbit at PINC1_bit
    Soft_I2C_Scl_Direction as sbit at DDC0_bit
    Soft_I2C_Sda_Direction as sbit at DDC1_bit


sub procedure Work_MLX90614()''dim celcius as ^double, dim fahrenheit as ^double)

dim  dev1,data_low1,data_high1, pec1,frac   as integer
dim  tempFactor,tempData as double
'dim  celcius,fahrenheit as float

dev1 = 0x5A<<1
data_low1 = 0
data_high1 = 0
pec1 = 0

'' Write
    Soft_I2C_Start()                         ' issue start signal
    Soft_I2C_Write(dev1)                 ' address dev
    Soft_I2C_Write(0x07)                   ' write 01 to year word (REG6)
'    Soft_I2C_Stop()                          ' issue stop signal
'
'' Read
'    Soft_I2C_Start()                         ' issue start signal
'    Soft_I2C_Write(dev1)                 ' address dev
    data_low1=Soft_I2C_Read(1)
    data_high1=Soft_I2C_Read(1)
    pec1=Soft_I2C_Read(0)
    Soft_I2C_Stop()   ' Issue stop signal

     tempFactor= 0.02 '' 0.02 degrees per LSB (measurement resolution of the MLX90614)
     tempData = 0x0000'' zero out the data


'   tempData=data_high and 0x007F
    tempData = ((data_high1 and 0x007F) << 8) + data_low1
    tempData = (tempData * tempFactor)-0.01

    celcius = tempData - 273.15
    fahrenheit = (celcius*1.8) + 32
    Lcd_Cmd(_LCD_CLEAR) FloatToStr(celcius,txt1) lcd_out(1,1,"Celcius: ")   lcd_out(2,1,txt1)


end sub


main:

 celcius=0
 Soft_I2C_Init()
 Lcd_Init()
 Lcd_Cmd(_LCD_CLEAR)               ' Clear display
 Lcd_Cmd(_LCD_CURSOR_OFF)          ' Cursor off
  while 1

'lcd_out(1,1,"Celcius: ")  FloatToStr(celcius,txt1) lcd_out(2,1,txt1)
   Work_MLX90614()  '' FloatToStr(celcius,txt1) lcd_out(1,1,"Celcius: ")   lcd_out(2,1,txt1)
   delay_ms(300)
  wend
end.

Así que no se muestra, pero la pantalla LCD no muestra el número correcto, es el número -273.00 o 378.00 o 59.00 o ... así que es la temperatura correcta de Mostrar la temperatura correcta solo algunas veces muestra la temperatura casi correcta grado !!!

Muestre estos números ¿La comunicación I2C se realizó correctamente o es una señal de falta de coincidencia en la configuración I2C?

Se debe recomendar que la comunicación del sensor IR (Conexión SPI) no muestre a veces el número correcto con Arduino, no se muestre también correcto.

Mi conjetura es que la conversión de código Arduino a Mikrobasic a partir de estos códigos es demasiado importante y puede haber algún error en mi conversión.

// read

i2c_rep_start(dev+I2C_READ);

Así que el código y la simulación en Proteus (sin la biblioteca mlx90614) están aquí: simulación en Proteus Muchas gracias.

    
pregunta 1st

1 respuesta

1

No uso mikroBasic, y algunas partes de su pregunta no están claras en inglés, pero puedo ver algunos errores en su código de mikroBasic, que he intentado solucionar a continuación.

Fondo

Con los dispositivos I²C (y SMBus), después de una condición de inicio (o inicio repetido), la dirección de la transferencia de datos se fija hasta el siguiente inicio (o inicio repetido). Por lo tanto, para cambiar entre usar Write para especificar un registro de dispositivo (en su caso, 0x07) y usar Read para leer los valores de ese registro (en su caso, el valor de la temperatura) ya sea un Stop + Start o un Inicio repetido es requerido. Normalmente se utiliza un inicio repetido.

También tenga en cuenta que debido a que \ $ \ small {R / \ overline {W}} \ $ bit es parte del byte de 8 bits que también contiene la dirección I²C de 7 bits, luego el byte completo de 8 bits después de que una condición de Inicio (o Inicio repetido) tenga un valor diferente, dependiendo de si el Maestro va a Write al Esclavo (Transmisor Maestro) o Read del Esclavo (Receptor Maestro).

En el código Arduino, vemos que contiene una llamada a i2c_rep_start() para realizar ese Comienzo Repetido con el \ $ \ small {R / \ overline {W}} \ $ bit establecido en 1 (ya que la constante I2C_READ = 1):

i2c_start_wait(dev+I2C_WRITE);
i2c_write(0x07);

// read
i2c_rep_start(dev+I2C_READ);
data_low = i2c_readAck(); //Read 1 byte and then send ack
data_high = i2c_readAck(); //Read 1 byte and then send ack
pec = i2c_readNak();
i2c_stop();

Pero en su código mikroBasic original, después de eliminar las líneas que son solo comentarios, vemos que no hay ninguna llamada a nada que pueda ser un inicio repetido y que establezca la \ $ \ small {R / \ overline {W}} \ $ bit a 1:

dev1 = 0x5A<<1

    Soft_I2C_Start()                         ' issue start signal
    Soft_I2C_Write(dev1)                 ' address dev
    Soft_I2C_Write(0x07)                   ' write 01 to year word (REG6)

    data_low1=Soft_I2C_Read(1)
    data_high1=Soft_I2C_Read(1)
    pec1=Soft_I2C_Read(0)
    Soft_I2C_Stop()   ' Issue stop signal

Por lo tanto, falta un inicio repetido entre la última llamada a Soft_I2C_Write() y la primera llamada a Soft_I2C_Read() . Supongo que esto podría ser lo que intentas decir cerca del final de tu pregunta.

Enfoque sugerido

La buena noticia es que la mikroBasic documentación para su "Software I2C Library" incluye un ejemplo de cómo debes manejar esta situación. Utilizando el ejemplo en esa página web, escribí esta versión modificada a continuación y sugiero que su código mikroBasic sea similar a este (pero tenga en cuenta que no lo he probado, y no puedo hacerlo, debe hacerlo usted mismo):

' 7-bit I2C slave address = 0x5A
dev1write = 0x5A<<1
dev1read = (0x5A<<1)+1

Soft_I2C_Start()
Soft_I2C_Write(dev1write)     ' Send I2C Address with R/-W bit = 0
Soft_I2C_Write(0x07)
Soft_I2C_Start()              ' Send I2C Repeated Start
Soft_I2C_Write(dev1read)      ' Send I2C Address with R/-W bit = 1
data_low = Soft_I2C_Read(1)
data_high = Soft_I2C_Read(1)
pec = Soft_I2C_Read(0)
Soft_I2C_Stop()               ' Send I2C Stop

Espero que sea un buen punto de partida para ti. Consulte la documentación de mikroBasic vinculada más arriba para obtener más información.

También le resultará más fácil solucionar problemas similares si obtiene un analizador lógico. O compre uno barato de las fuentes habituales y use el software de código abierto Sikrok (los costos iniciales son bajos, pero no hay soporte del fabricante y he visto limitaciones con algunos de los hardware) o compre uno de marca con su propio software (Los costos iniciales son más altos, pero hay soporte del fabricante).

Con uno de ellos, podría ver lo que está sucediendo en el bus I²C (y, si tiene un Arduino, podría ejecutar el código Arduino, luego ejecutar el código mikroBasic y comparar esas dos trazas de bus I²C del analizador lógico).

Si continúa teniendo problemas, y si decide no usar un analizador lógico, al menos elimine la parte de cálculo de temperatura de su código y examine los bytes sin procesar recibidos del sensor, en caso de que su código de cálculo de temperatura también contiene un error. No he revisado esa parte de su código.

    
respondido por el SamGibson

Lea otras preguntas en las etiquetas