ATtiny 用错误的值写数组 |阿杜诺 IDE |微线机
ATtiny writing arrays with wrong values | Arduino IDE | TinyWireM
这是我的第一个问题,我希望我没有踩到任何人的拖车:-)
目前我正在为我的电动滑板车开发一个模块化电池管理系统,该系统基于一个 ATtiny85 作为主机,多个 ATtiny85 作为从机。每个从属单元都在监视一个单元(或一组并联的多个单元),并使用该单元为自身供电。为了安全起见,它读取电池的电压并读取该电池的温度传感器。它通过隔离的 I2C 总线将这两个信息发送到主站,主站将对其进行分析并最终发送一个响应,以确定该电池是否应激活平衡。
因此,我正在使用 digispark 引导加载程序并使用 USB 刷新软件。我正在使用 Arduino IDE.
编程的软件本身
到目前为止,我设法在使用 TinyWireS 的从属设备和使用 TinyWireM 的主设备之间建立了良好的连接。我成功地将数据从多个从站发送到主站,反之亦然。
但是当我以某种方式从总线上移除一个或多个从站时,读取例程会用之前接收到的数据填充未接收到的数据,并且不会写入空行或零。
这是相关例程,我在其中轮询从站地址并分别向每个从站询问 4 字节的有效载荷。从机会将测得的电压和温度分别分成两个字节,并将生成的 4 个字节分别通过 I2C 总线发送。
master会收到这4个独立的bytes,然后将它们再次组合成voltage和temperature,然后将它们写入数组中与它的cell-number相匹配的位置。
for (int cell_num = 1; cell_num <= CELL_COUNT; cell_num++) //poll data from all cells, start with cell 1 to max
{
int slave_add = 0x3F+cell_num; //connect to cell, adress offset 0x3F, first cell is 0x40
v_data[cell_num] = 0;
t_data[cell_num] = 0;
TinyWireM.requestFrom(slave_add, 4); //request from selected cell 4 bytes
while(TinyWireM.available())
{
v_low = TinyWireM.receive(); //read first byte as low byte of voltage
v_high = TinyWireM.receive(); //read second byte as hight byte of voltage
t_low = TinyWireM.receive(); //read third byte as low byte of temp
t_high = TinyWireM.receive(); //read fourth byte as hight byte of temp
v_data[cell_num] = 0;
t_data[cell_num] = 0;
v_data[cell_num] = (v_high<<8) | v_low; //shift high byte of voltage and combine with low byte
t_data[cell_num] = (t_high<<8) | t_low; //shift high byte of temp and combine with low Byte
v_high = 0;
v_low = 0;
t_high = 0;
t_low = 0;
}
一个演示错误的小例子:
总线上应该有 14 个从站(CELL_COUNT = 14),一个或多个从站(比方说 5 号和 6 号)有错误并且没有传输 4 个字节。
所以主机在一个小的 OLED 显示器上显示从机的所有数据。
master 没有在第 5 行和第 6 行显示 0,而是显示与第 4 行相同的值。
显示的前半部分将如下所示:
4125
4035
4156
4137
4137
4137
4089
此外,您还可以在下面找到完整代码:
//1MHz Speed!!!!
#include <TinyWireM.h>
#include "SSD1306_minimal.h"
#define CELL_COUNT 14 //from 1 to cell amout, number of cells on bus
SSD1306_Mini oled;
uint16_t v_data[CELL_COUNT];
uint16_t v_data_max = 0;
uint16_t t_data[CELL_COUNT];
uint16_t t_data_max = 0;
char cast1[8] = {};
char cast2[8] = {};
uint8_t v_low;
uint8_t v_high;
uint8_t t_low;
uint8_t t_high;
void setup()
{
pinMode(1, OUTPUT); //led pinset digispark
digitalWrite(1, LOW); //disable led
oled.init(0x3c); //init oled adress 0x3c
oled.clear(); //clear oled display
oled.startScreen(); //start oled routine to write
TinyWireM.begin(); //start i2c lib for com
}
void loop()
{
v_data_max = 0;
t_data_max = 0;
//read received data
for (int cell_num = 1; cell_num <= CELL_COUNT; cell_num++) //poll data from all cells, start with cell 1 to max
{
int slave_add = 0x3F+cell_num; //connect to cell, adress offset 0x3F, first cell is 0x40
v_data[cell_num] = 0;
t_data[cell_num] = 0;
TinyWireM.requestFrom(slave_add, 4); //request from selected cell 4 bytes
while(TinyWireM.available())
{
v_low = TinyWireM.receive(); //read first byte as low byte of voltage
v_high = TinyWireM.receive(); //read second byte as hight byte of voltage
t_low = TinyWireM.receive(); //read third byte as low byte of temp
t_high = TinyWireM.receive(); //read fourth byte as hight byte of temp
v_data[cell_num] = 0;
t_data[cell_num] = 0;
v_data[cell_num] = (v_high<<8) | v_low; //shift high byte of voltage and combine with low byte
t_data[cell_num] = (t_high<<8) | t_low; //shift high byte of temp and combine with low Byte
v_high = 0;
v_low = 0;
t_high = 0;
t_low = 0;
}
}
for (int cell_num = 1; cell_num <= CELL_COUNT; cell_num++) //pring voltage and temp data to oled
{
oled.startScreen(); //start oled routine to write
if (cell_num<=7) //check if first half of cells (cell number = 14) or second half
{
oled.cursorTo(0,cell_num-1); //jump to right line for cell
}
else
{
oled.cursorTo(66,cell_num-8); //jump to right line for cell
}
oled.printString(itoa(v_data[cell_num], cast1, 10)); //change data from int to str and print on oled
oled.startScreen();
if (cell_num<=7)
{
oled.cursorTo(30,cell_num-1); //jump to right line for cell
}
else
{
oled.cursorTo(96,cell_num-8); //jump to right line for cell
}
oled.printString(itoa(t_data[cell_num], cast2, 10)); //change data from int to str and print on oled
}
delay(5000);
oled.cursorTo(0,0);
oled.clear();
}
我希望有人能指出正确的方向来解决这个问题...
我把范围缩小了一点...
在下面的代码中,如果没有收到新数据,函数 TinyWireM 将循环前的数据写入变量 v_high、v_low、T_high 和 t_low。但奇怪的是,它们并不都是相等的,它们在之前的循环中都具有完全相同的值。所以 v_high(旧)= v_high(新)等等。
如果它们都使用相同的函数设置,这怎么可能 运行 4 次,所以每个变量一次?
相关部分如下:
v_low = TinyWireM.receive(); //read first byte as low byte of voltage
v_high = TinyWireM.receive(); //read second byte as hight byte of voltage
t_low = TinyWireM.receive(); //read third byte as low byte of temp
t_high = TinyWireM.receive(); //read fourth byte as hight byte of temp
我在 lib TinyWireM 中发现了一点不便。
如果您收到一些数据,库会将其存储在缓冲区中。如果您读取缓冲区,它将显示内容。如果没有收到新数据,缓冲区将保持原样,如果您再次读取缓冲区,您将读取完全相同的数据。
因此我更改了 TinyWireM.ccp 以便如果读取一次缓冲区将被删除。
现在,如果您在没有收到新数据的情况下再次读取缓冲区,它将显示 0。
这是我的第一个问题,我希望我没有踩到任何人的拖车:-)
目前我正在为我的电动滑板车开发一个模块化电池管理系统,该系统基于一个 ATtiny85 作为主机,多个 ATtiny85 作为从机。每个从属单元都在监视一个单元(或一组并联的多个单元),并使用该单元为自身供电。为了安全起见,它读取电池的电压并读取该电池的温度传感器。它通过隔离的 I2C 总线将这两个信息发送到主站,主站将对其进行分析并最终发送一个响应,以确定该电池是否应激活平衡。
因此,我正在使用 digispark 引导加载程序并使用 USB 刷新软件。我正在使用 Arduino IDE.
编程的软件本身到目前为止,我设法在使用 TinyWireS 的从属设备和使用 TinyWireM 的主设备之间建立了良好的连接。我成功地将数据从多个从站发送到主站,反之亦然。
但是当我以某种方式从总线上移除一个或多个从站时,读取例程会用之前接收到的数据填充未接收到的数据,并且不会写入空行或零。
这是相关例程,我在其中轮询从站地址并分别向每个从站询问 4 字节的有效载荷。从机会将测得的电压和温度分别分成两个字节,并将生成的 4 个字节分别通过 I2C 总线发送。
master会收到这4个独立的bytes,然后将它们再次组合成voltage和temperature,然后将它们写入数组中与它的cell-number相匹配的位置。
for (int cell_num = 1; cell_num <= CELL_COUNT; cell_num++) //poll data from all cells, start with cell 1 to max
{
int slave_add = 0x3F+cell_num; //connect to cell, adress offset 0x3F, first cell is 0x40
v_data[cell_num] = 0;
t_data[cell_num] = 0;
TinyWireM.requestFrom(slave_add, 4); //request from selected cell 4 bytes
while(TinyWireM.available())
{
v_low = TinyWireM.receive(); //read first byte as low byte of voltage
v_high = TinyWireM.receive(); //read second byte as hight byte of voltage
t_low = TinyWireM.receive(); //read third byte as low byte of temp
t_high = TinyWireM.receive(); //read fourth byte as hight byte of temp
v_data[cell_num] = 0;
t_data[cell_num] = 0;
v_data[cell_num] = (v_high<<8) | v_low; //shift high byte of voltage and combine with low byte
t_data[cell_num] = (t_high<<8) | t_low; //shift high byte of temp and combine with low Byte
v_high = 0;
v_low = 0;
t_high = 0;
t_low = 0;
}
一个演示错误的小例子: 总线上应该有 14 个从站(CELL_COUNT = 14),一个或多个从站(比方说 5 号和 6 号)有错误并且没有传输 4 个字节。 所以主机在一个小的 OLED 显示器上显示从机的所有数据。 master 没有在第 5 行和第 6 行显示 0,而是显示与第 4 行相同的值。
显示的前半部分将如下所示:
4125
4035
4156
4137
4137
4137
4089
此外,您还可以在下面找到完整代码:
//1MHz Speed!!!!
#include <TinyWireM.h>
#include "SSD1306_minimal.h"
#define CELL_COUNT 14 //from 1 to cell amout, number of cells on bus
SSD1306_Mini oled;
uint16_t v_data[CELL_COUNT];
uint16_t v_data_max = 0;
uint16_t t_data[CELL_COUNT];
uint16_t t_data_max = 0;
char cast1[8] = {};
char cast2[8] = {};
uint8_t v_low;
uint8_t v_high;
uint8_t t_low;
uint8_t t_high;
void setup()
{
pinMode(1, OUTPUT); //led pinset digispark
digitalWrite(1, LOW); //disable led
oled.init(0x3c); //init oled adress 0x3c
oled.clear(); //clear oled display
oled.startScreen(); //start oled routine to write
TinyWireM.begin(); //start i2c lib for com
}
void loop()
{
v_data_max = 0;
t_data_max = 0;
//read received data
for (int cell_num = 1; cell_num <= CELL_COUNT; cell_num++) //poll data from all cells, start with cell 1 to max
{
int slave_add = 0x3F+cell_num; //connect to cell, adress offset 0x3F, first cell is 0x40
v_data[cell_num] = 0;
t_data[cell_num] = 0;
TinyWireM.requestFrom(slave_add, 4); //request from selected cell 4 bytes
while(TinyWireM.available())
{
v_low = TinyWireM.receive(); //read first byte as low byte of voltage
v_high = TinyWireM.receive(); //read second byte as hight byte of voltage
t_low = TinyWireM.receive(); //read third byte as low byte of temp
t_high = TinyWireM.receive(); //read fourth byte as hight byte of temp
v_data[cell_num] = 0;
t_data[cell_num] = 0;
v_data[cell_num] = (v_high<<8) | v_low; //shift high byte of voltage and combine with low byte
t_data[cell_num] = (t_high<<8) | t_low; //shift high byte of temp and combine with low Byte
v_high = 0;
v_low = 0;
t_high = 0;
t_low = 0;
}
}
for (int cell_num = 1; cell_num <= CELL_COUNT; cell_num++) //pring voltage and temp data to oled
{
oled.startScreen(); //start oled routine to write
if (cell_num<=7) //check if first half of cells (cell number = 14) or second half
{
oled.cursorTo(0,cell_num-1); //jump to right line for cell
}
else
{
oled.cursorTo(66,cell_num-8); //jump to right line for cell
}
oled.printString(itoa(v_data[cell_num], cast1, 10)); //change data from int to str and print on oled
oled.startScreen();
if (cell_num<=7)
{
oled.cursorTo(30,cell_num-1); //jump to right line for cell
}
else
{
oled.cursorTo(96,cell_num-8); //jump to right line for cell
}
oled.printString(itoa(t_data[cell_num], cast2, 10)); //change data from int to str and print on oled
}
delay(5000);
oled.cursorTo(0,0);
oled.clear();
}
我希望有人能指出正确的方向来解决这个问题...
我把范围缩小了一点... 在下面的代码中,如果没有收到新数据,函数 TinyWireM 将循环前的数据写入变量 v_high、v_low、T_high 和 t_low。但奇怪的是,它们并不都是相等的,它们在之前的循环中都具有完全相同的值。所以 v_high(旧)= v_high(新)等等。
如果它们都使用相同的函数设置,这怎么可能 运行 4 次,所以每个变量一次?
相关部分如下:
v_low = TinyWireM.receive(); //read first byte as low byte of voltage
v_high = TinyWireM.receive(); //read second byte as hight byte of voltage
t_low = TinyWireM.receive(); //read third byte as low byte of temp
t_high = TinyWireM.receive(); //read fourth byte as hight byte of temp
我在 lib TinyWireM 中发现了一点不便。 如果您收到一些数据,库会将其存储在缓冲区中。如果您读取缓冲区,它将显示内容。如果没有收到新数据,缓冲区将保持原样,如果您再次读取缓冲区,您将读取完全相同的数据。
因此我更改了 TinyWireM.ccp 以便如果读取一次缓冲区将被删除。
现在,如果您在没有收到新数据的情况下再次读取缓冲区,它将显示 0。