TODOPIC
Otros Microcontroladores / Dispositivos programables => Arduino => Mensaje iniciado por: elreypic2 en 08 de Marzo de 2021, 12:36:40
-
Que tal amigos del foro,
Acudo a ustedes para solicitar su ayuda en un problema que estoy enfrentando.
Estoy intentado realizar la emulación de un dispositivo con comunicación 1-wire, específicamente quiero emular un dispositovo DS1990A. Lo que deseo es emular solaente el comando para leer el ID ROM que consta de 1 byte de Family code, 48 bits de número serial y 1 byte del CRC8.
He encontrado una librería para Arduino llamada OneWireHub, pero esta librería es demasiado grande para la aplicación final que deseo.
En el código que estoy realizando thengo resuelto la detección del RESET y la generación del pulso de presencia, así como la recepción del comando para realizar la lectura del ID ROM (que según el protocolo 1-wire es un 0x33). Mi problema viene cuando ya intento enviar el número ID ROM. Acá el código que esoy usando:
#include <SendOnlySoftwareSerial.h>
SendOnlySoftwareSerial mySerial (4);
//This is an attemp to emulate a 1-wire slave device as a ROM only
//Microcontroller: ATTiny85
//Oscillator: Internal RC at 8MHz
#define GO_LO DDRB |= (1<<0); PORTB&=~(1<<0) //Macro to set 1-wire bus on OUTPUT mode and Low level
#define GO_HI DDRB &= ~(1<<0); //Macro to set 1-wire bus on INPUT mode
#define DQ PINB1 //Define DQ slave bus for debuging purposes
#define LED PINB2 //Define LED on PORTB.2
byte SN[8] = {0xFF, 0x00, 0x00, 0x11, 0x22, 0x87, 0x59, 0x01};
byte ow_buffer;
byte i;
//detect reset pulse and return 1 if a pulse was detected
byte OW_reset_pulse_detect()
{
byte del_count = 50; //Set del_count variable to 50
while (del_count--) //Decrementa del_count variable
{
_delay_us(10); //Delay of 10us
if (bit_is_set(PINB,0)) //1-wire bus is on high level?
break; //Break while cycle
}
if (del_count > 40) //del_count variable is greater than 40?
return 0; //Yes, reset pulse detected is too short!
return 1; //No, then correct reset pulse was detected
}
// Function to generate a presence pulse
// indicating to master that a slave device is present on the 1-wire bus
void OW_presence_pulse()
{
GO_LO; //Drive 1-wire bus LOW
PORTB &= ~_BV(DQ); //Clear DQ bus for debuging
_delay_us(120); //Keep it LOW for 120us
GO_HI; //Release 1-wire bus
PORTB |= _BV(DQ); //Set DQ bus for debuging
}
//1-wire slave write bit
//must be run inmmediately after line is pulled down by master
void OW_write_bit(byte bit_write)
{
if (bit_write)
{
//Writing a bit '11
_delay_us(35); //1-wire bus is already pulled high by pullup resistor, so just wait
}
else
{
//Writing a bit '0'
GO_LO; //Drive the 1-wire bus LOW
_delay_us(50); //Keep it LOW for 50 us
GO_HI; //Drive the 1-wire bus HIGH (PB0 as input)
_delay_us(10); //Keep it HIGH for 10 us
}
}
// 1-wire slave write byte
// must be initiated immediately after line is pulled down by master
void OW_write_byte(byte write_data)
{
byte j;
for (j=0; j<8; j++)
{
while (bit_is_set(PINB,0)); //Wait for master set 1-wire bus LOW
//OW_write_bit(write_data & 0x01); //Send LSB first
//_delay_us(6);
if (write_data & 0x01)
{
//Writing a bit '1'
GO_HI; //Drive 1-wire bus HIGH
_delay_us(50); //1-wire bus is already pulled high by pullup resistor, so just wait
}
else
{
//Writing a bit '0'
GO_LO; //Drive the 1-wire bus LOW
_delay_us(50); //Keep it LOW for 50 us
GO_HI; //Drive the 1-wire bus HIGH (PB0 as input)
_delay_us(10); //Keep it HIGH for 10 us
}
if (j<7)
write_data >>= 1;
//while (bit_is_set(PINB,0)); //Wait for master set 1-wire bus LOW
}
}
// 1_wire slave read bit
// must be run immediately after 1-wire bus line is pulled down by master
byte OW_read_bit (void)
{
byte read_data;
byte del_count;
_delay_us(15); //15
read_data = PINB & _BV(0); //Read the status of 1-wire bus
_delay_us(35);
if (bit_is_set(PINB,0));
return read_data; //Return data when 1-wire bus is released
del_count = 40;
do
{
if (bit_is_set(PINB,0)) //Wait for master to release 1-wire bus
return read_data;
} while (del_count--);
return 0;
}
// 1-wire slave read byte
// must be run immediately after line is pulled down by master
byte OW_read_byte (void)
{
byte j;
byte result = 0;
byte read_data;
/*
for (j=0; j<8; j++)
{
if (OW_read_bit())
result |= 0x80; // if result is one, then set MS-bit
while(bit_is_set(PINB,0));
result >>= 1; // shift the result to get it ready for the next bit to receive
}*/
for (j=0;j<8;j++)
{
while(bit_is_set(PINB,PINB0)); //Wait until a falling edge be detected on 1 wire bus
PORTB &= ~_BV(DQ); //Clear DQ slave (for debuging)
_delay_us(15); //Wait 15us before sampling 1-wire bus
read_data = PINB & 1; //Read data bit from 1-wire bus
//For debuging
if(read_data)
PORTB |= _BV(DQ); //If received data bit is HIGH, set DQ slave bus
else
PORTB &= ~_BV(DQ); //If received data bit is LOW, clear DQ slave bus
_delay_us(35); //Wait for 35us
while(!bit_is_set(PINB,PINB0)); //Wait for the 1-wire bus to be released
PORTB |= _BV(DQ); //Set DQ slave bus //For debuging
if(read_data) //Is the data bit a '1'?
{
result |= 0x80; //Yes, then result = result LOR 0x80
}
if (j<7)
result >>= 1; //Right shift 1 position result
} //Continue receiving data bits until get all of them
return result; //Finish function and return the value
}
// these functions are for 1-wire serial number checksum generation
void C_CRC(byte *CRCVal, byte value) {
byte odd, bcnt;
for (bcnt = 0; bcnt < 8; bcnt++) {
odd = (value ^ *CRCVal) & 0x01;
*CRCVal >>= 1;
value >>= 1;
if (odd != 0)
*CRCVal ^= 0x8C;
}
}
byte CalcCRC(byte code_len, byte *code) {
byte i, CRCVal = 0;
for (i = code_len; i > 0; i--)
C_CRC(&CRCVal, code[i]);
return CRCVal;
}
void setup() {
GO_HI; //Release 1-wire bus
DDRB |= (1<<DQ); //Define DQ pin as OUTPUT
DDRB |= (1<<LED); //Define LED pin as OUPUT
PORTB&=~(1<<LED); //Turn LED OFF
PORTB |= _BV(DQ); //Set DQ slave bus for dubiging
SN[0] = CalcCRC(7,SN); //CRC8 calculation
mySerial.begin(9600); //Init software UART at 9600 bps
mySerial.print("Welcome\n\r");
}
void loop() {
while (bit_is_set(PINB,0)); //Wait until a falling edge be detected on 1-wire bus
PORTB &= ~_BV(DQ); //Clear DQ slave bus for debuging
while(!OW_reset_pulse_detect()); //Wait until a slave device be detected
PORTB |= _BV(DQ); //Set DQ slave bus for debuging
_delay_us(30); //Wait 30us before sending a presence pulse
OW_presence_pulse(); // generate presence pulse
//PORTB |= (1<<LED); //Turn LED on
//_delay_ms(1000);
//PORTB &= ~_BV(LED); //Turn LED off
//while(bit_is_set(PINB,PINB0)); //Wait until a falling edge be detected on 1 wire bus
ow_buffer = OW_read_byte(); //Read command received
//if (ow_buffer<16) //Print the command received
//mySerial.write("0"); //If the command received is lesser than 16 print an ASCII 0
//mySerial.print(ow_buffer,HEX); //Print the HEX ASCII value received
if (ow_buffer == 0x33) //Read ROM command was received?
{
PORTB |= _BV(LED); //Yes, then turn LED on for debuging
SN[0] = CalcCRC(7,SN); //Check CRC8
OW_write_byte(0x01); //Send Family Code 0x01
//i = 7;
//do {
//while(bit_is_set(PINB,0));
//OW_write_byte(SN[i]);
//} while (i--);
}
}
Encontrarán que hay varias secciones que uso para poder ir depurando, pero mi primera intención es tratar de enviar solamente el byte del Family Code (0x01), pero este no se logra enviar correctamente, y no entiendo la razón. Es muy claro el datasheet con respecto al protocolo, pero por más que he intentado buscar el problema no doy con este.
Les comento que estoy usando un Attiny85 en el entorno de Arduino, pero al final solmanete estoy usando el compilador C GCC, que es el que usa Arduino.
Ojalá me puedan ayudar con este problema que estoy enfrentando. Si necesitan algo más de información, por favor háganmelo saber.
Gracias de antemano
elreypic.
-
No hay mas apuros.
Yo mismo he encontrado el problema. Una tontería.
Estaba realizando el cálculo del CRC justo después de recibir el comando de READ ROM (0x33) y eso desincronizaba el tiempo para realizar el envío de los datos.
if (ow_buffer == 0x33) //Read ROM command was received?
{
PORTB |= _BV(LED); //Yes, then turn LED on for debuging
SN[0] = CalcCRC(7,SN); //Check CRC8
OW_write_byte(0x01); //Send Family Code 0x01
}
Saludos :-/ :-/ :-/ :-/ :-/
elreypic.