¿Cómo edito la EEPROM de un sensor de CO2 K30?

EDITAR: el código corregido se encuentra en la parte inferior del OP.

Fondo

Mientras trabajaba en un circuito para registrar el dióxido de carbono con un sensor de CO2 K30 usando un escudo de registro de datos de Adafruit , me encontré con un problema. La dirección I2C del RTC en el escudo tiene una colisión con la dirección del sensor de CO2. La dirección del RTC está integrada en el silicio y no se puede cambiar , pero la dirección del sensor K30 es mutable . De acuerdo con la guía I2C ( consulte el PDF en I2C/I2C_comm_guide , ¡advertencia en PDF comprimido!), la dirección I2C del sensor puede tener cualquier valor:

0x00 a 0x7F

Precedente

Esto parece ser un problema común. He encontrado varios hilos (ver a , b , c , d , e , f ) que han intentado resolver este desafío. La mayoría fracasa con los resultados positivos o sugiere usar una interfaz diferente. SIN EMBARGO, según la hoja de datos, debería ser posible piratear este cambio en la EEPROM.

Soluciones alternativas que estoy evitando

  • K30 RX/TX: dado que el K30 tiene pines I2C y RX/TX, ¿por qué no cambiar a RX/TX y omitir todo este lío? El sensor está montado en una placa de conexiones con muchas otras partes y un escudo protector adherido con resina epóxica. Me gustaría evitar excavar en el hardware para llegar a estos pines.
  • Software GasLab: el fabricante proporciona el software GasLab para piratear los sensores mediante una GUI a través de USB. Desafortunadamente, solo funciona para Windows.
  • Elija un RTC diferente: necesito algo rápido y fácil para registrar valores ya que tengo poco tiempo. No quiero reinventar la rueda cuando el escudo de Adafruit funciona tan bien.
  • Dirección 0x7F: según la hoja de datos, debería poder llamar a todos los sensores K30 usando esta dirección, sin embargo, no pude hacer que funcionara en la práctica cuando estaba en el mismo circuito que el RTC.

Mi hardware

Estoy ejecutando un clon de Arduino Uno conectando el I2C a A4 y A5. Las líneas I2C tienen pullups de 2.2K. El K30 está funcionando a ~9V.

Prueba de cordura

Al ejecutar el código Arduino proporcionado por el fabricante, puedo leer la respuesta del sensor y tiene sentido.

Codigo para cambiar EEPROM

#include <Wire.h>

byte CheckSum(byte * buf, byte count) {
    byte sum=0;
    while (count>0) {
        sum += *buf;
        buf++;
        count--;
    }
    return sum;
}

void setup() {
    Serial.begin(9600);
    Wire.begin();
    delay(1000);

    byte changebuf[4] = {0x31, 0x00, 0x69, 0x00};
    changebuf[3] = CheckSum(changebuf, 3);
    
    Wire.beginTransmission(0x68<<1);
    for (size_t i = 0; i<sizeof(changebuf); i++) {
        Wire.write(changebuf[i]);
    }
    Wire.endTransmission();
}

void loop() {}

El mensaje 0xD0, 0x31, 0x00, 0x69, 0x9Aes Los bytes son:

  1. La dirección predeterminada se desplazó a la izquierda en uno (también probé simple 0x68)
  2. Comando para escribir 1 byte en EEPROM
  3. Dirección en EEPROM a escribir
  4. Carga útil para escribir
  5. Suma de verificación

Estos valores se basan en la hoja de datos.

Tabla de formato de bytes para acceso a EEPROM/RAM desde la hoja de datos del sensor K30.

Después de ejecutar esto, enciendo y enciendo el dispositivo para que los valores de EEPROM se propaguen a la RAM según la hoja de datos.

Observaciones

Después de ejecutar el código anterior, la dirección no cambia. El dispositivo sigue respondiendo a la dirección predeterminada original 0x68y no responde a la nueva dirección 0x69.

La pregunta replanteada

¿Por qué está fallando mi intento de ordenar a la EEPROM del K30 que cambie el valor asociado con la dirección I2C del dispositivo? ¿Hay algún problema con la secuencia de bytes que envío?

SOLUCIÓN: según la solución aceptada, me perdí el LSB adicional obvio en la cadena de bytes. Ahora puedo cambiar la dirección. Aquí está el código completo corregido para lograr esto:

#include <Wire.h>

byte CheckSum(byte * buf, byte count) {
    byte sum=0;
    while (count>0) {
        sum += *buf;
        buf++;
        count--;
    }
    return sum;
}

void setup() {
    Serial.begin(9600);
    Wire.begin();
    delay(1000);

    byte changebuf[5] = {0x31, 0x00, 0x00, 0x69, 0x00};
    changebuf[4] = CheckSum(changebuf, 4);
    
    Wire.beginTransmission(0x68);
    for (size_t i = 0; i<sizeof(changebuf); i++) {
        Wire.write(changebuf[i]);
    }
    Wire.endTransmission();
}

void loop() {}

Respuestas (3)

La dirección de la eeprom es de dos bytes. Usted solo proporcionó uno. La dirección de eeprom que desea es 0x00 0x00

Me encanta cuando un problema con el que luché durante horas es una solución obvia que pasé por alto. Cambiar el código pasado a 0xD0, 0x31, 0x00, 0x00, 0x69, 0x9Ahizo el truco. Tenga en cuenta que utilicé la dirección original de 0x68sin cambio de bits. Agregaré el código corregido al OP.

Una cosa, si la dirección predeterminada era 0x68, desplazada por uno es 0xd0, no 0x69.

Gracias por el comentario. Estoy tratando de cambiar de 0x68 a 0x69. El valor desplazado a la izquierda para 0x68 es 0xD0 y, tras un cambio de dirección exitoso a 0x69, el valor desplazado a la izquierda será 0xD2.
Gracias @WesH, por no golpearme. :-) Volveré más tarde y comprobaré si todavía te estás preguntando. Mientras tanto, si necesitas empujar, llévame aquí. Trataré de ayudar.
No te preocupes @jay. ¡La solución que acepté muestra que también me cuesta leer cosas!

Sensor de CO2 K30 que cambia la dirección predeterminada de I2C. La referencia con la que estoy trabajando es la guía de comunicaciones I2C 2.15 del sitio Gaslab.com. http://co2meters.com/Documentation/Other/SenseAirCommGuide.zip El ZIP tiene manuales para la operación de UART e I2C. El final de la guía I2C tiene ejemplos de sintaxis.

Suponiendo que está leyendo con éxito la medición de CO2 desde la ubicación de RAM del sensor 0x08, entonces sabemos que tiene I2C operativo. También puede leer la ubicación de RAM 0x20 y la dirección EEPPROM 0x0 para la dirección actual, que debería ser 0x68. Escriba la ubicación de RAM 0x20 en su dirección deseada, verifique que la suma de verificación sea correcta para el mensaje, recuerde no incluir el byte de dirección I2C. ver 9.0 Al cambiar la dirección base, lo que muchos pasan por alto es enviar el comando para escribir RAM en EEPROM antes de apagar y encender el sensor. Use el registro de comando especial SCR 0x60 para escribir RAM en EEPROM, vea 8.7.

El método alternativo que uso es escribir EEPROM directamente. Cambie el comando de escribir RAM a escribir EEPROM. Escriba la dirección 0 de la EEPROM en la dirección deseada y luego apague y encienda.

VBR

Gracias por hacerte una cuenta para responder aquí Ray. En el OP, incluí un enlace al mismo documento que sugiere y se me ocurrió la misma solución, escribiendo directamente en la EEPROM con 0x3_. Resulta que me faltaba un 0x00byte en mi mensaje original. Al final del OP, publiqué una versión corregida del código simple para realizar esta tarea para futuros usuarios.