Просмотр полной версии : PCF8576 + Arduino
Привет всем.
Сломал мозг уже, пытаясь оживить панель от старой магнитолы.
Подключил уже кнопки и энкодер, но аппетит приходит во время еды, поэтому хочу оживить и LCD индикатор.
В панели стоит PCF8576, подключенная к 8 разрядам на 14 символов и одному на 7 символов плюс несколько значков - FM, RDS, TA.
Хочу заставить на 14 символьные выводить произвольную инфу из Ардуины.
Подключил к ней Teensy 2.0 ++ по I2C.
За основу скетча взял код отсюда (http://www.blog.zapro.dk/?p=121)
Проблема в том, что не пойму, как правильно сконфигурить инициализацию и отправить нужные коды символов.
В идеале заполучить бы работающий образец кода именно под Ардуину, который выводит произвольную строку.
Адрес слэйва известен - 0x38
Конфиг тоже проходит вроде вот этим
Wire.send(B11001101);
А вот как сконфигурить правильно BIAS, Duty и собсно, отправить данные - непонятно.
Даташит читал, вроде подходят два варианта
11001101
11001110
Манипуляции с адресами и отправкой данных дают часть нужных символов, но не все, подозреваю, что все-таки сконфигурировано неправильно.
Еще трабла в том, что для отправки данных требуется 12 байт, а так как Ардуины 8-битные - нужно как-то разбивать пакеты отправки данных.
Пробовал сниффер I2C отсюда (http://hackaday.com/2011/05/21/arduino-i2c-sniffer/)
Подключил его к работающей магнитоле - там такой бешенный обмен по I2C, что с ним надо очень долго разбираться, кто что шлет. Может еще придется в этом разбираться.
В этой магнитоле еще и тюнер и аудиопроцессор подключены к I2C.
У кого есть какие мысли?
по поводу сниффера- то что по ссылке выше-шняга. с тинси он работает неправильно. я в качестве сниффера использовал из ардуиновской иде примеры, с небольшой правкой. с их помощью отснифил протокол тюнера, там тоже наркоманское управление, пачки байтов...
по поводу сниффера- то что по ссылке выше-шняга. с тинси он работает неправильно. я в качестве сниффера использовал из ардуиновской иде примеры, с небольшой правкой. с их помощью отснифил протокол тюнера, там тоже наркоманское управление, пачки байтов...
можешь кинуть сюда сниффер? и на чем построен тюнер, может у меня такой же?
AngelOfGrief
20.05.2013, 19:17
Я не понял, в итоге на экран вообще что-то выводится? Или не работает совсем? Проблема в конфигурации регистров PCF8576 или вообще
в настройке самого интерфейса?
Сниффер i2c я в молодости делал под DOS на LPT. В принципе можно самой Ардуиной и посниффить если найти библиотеки кода slave.
Если скорость слишком большая, можно в магнитоле кварц поменять на более медленный. i2c - статический протокол.
Я не понял, в итоге на экран вообще что-то выводится? Или не работает совсем? Проблема в конфигурации регистров PCF8576 или вообще
в настройке самого интерфейса?
Я же и говорю, выводится, но непонятно что.
Если выбираешь в MODE SELECT один режим - одно выводится, если другой режим - другое.
Метода была такая - по даташиту пытался подать команду
MODE SELECT
Wire.send(B11001101);
потом
выставляю адрес
Wire.send(B00100000); - это вроде адрес старшего разряда
потом шлю данные
Wire.send(B00100000);
получаю 1 на LCD в старшем разряде.
Все вроде ок.
Но, меняя данные, получаю только вертикальные символы в знакоместе, типа 1 слева разряда, 1 справа разряда, -1 и 1-.
Напоминаю, индикатор 15-ти разрядный.
Все, только комбинации таких символов, как бы я не извращался с байтом данных.
Меняя байт разряда получаю аналогичную картину на других знакоместах.
Вот и не пойму, где порылась собака?
Поэтому и спрашиваю, может кто-то имел дело с подобными микрухами?
Чувствую, что где-то близко, но не пойму, в чем трабла.
Может где-то тайминги нарушены? Может где-то напихать задержек?
Или все-таки ошибка в конфиге?
Пошел курить даташит до полного просветления...
#include <Wire.h>
#define ADDR 0x88 //адрес устройства
void setup()
{
Serial.begin(115200);//скорость обмена с компом
Wire.begin(ADDR); //определим как ведомый с указанным адресом
Wire.onReceive(receive_handler); //ждем данных от мастера, функция возвращает int число байт данных
}
void loop() {}
void receive_handler(int numbytes)
{
for (int i=0;i<numbytes;i++) //читаем весь пакет
{
Serial.print(Wire.receive(), HEX); // принимаем значение и передаем компьютеру
}
Serial.println(' '); //перенос строки
}
или
#include <Wire.h>
void setup()
{
Wire.begin(0x44); // join i2c bus with address #4
Wire.onReceive(receiveEvent); // regis-ter event
Serial.begin(9600); // start serial for output
}
void loop()
{
delay(100);
}
// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{
while(1 < Wire.available()) // loop through all but the last
{
// char c = Wire.read(); // receive byte as a character
// Serial.print(c); // print the character
}
int x = Wire.read(); // receive byte as an integer
Serial.println(x, HEX);
Serial.println(x, BIN); // print the integer
}
в зависимости от тупости железки работает либо тот, либо тот.
еще для тинси есть интересный проект: bus-ninja (https://github.com/jobytaffey/bus-ninja)
заработал первый скетч.
отснифал им HEX-коды, перевел в бинарный вид, запихнул в скетч - не палит.
По-прежнему показывает чушь.
Или он криво снимает или я опять туплю.
надпись CODE выдает последовательность
E0CBF000000A96311460A1000
E0CBF02000156CE062C1460000
перевожу в бинарный вид
11100000 11001011 11110000 00000000 00000000 00001010 10010110 00110001
11100000 11001011 11110000 00100000 00000000 00010101 01101100 11100000
первый байт всегда адрес слэйва, второй выбор режима, третий - управление миганием сегментов (всегда выключено), а дальше по идее идут сами байты данных.
Так как здесь используется drive mode 1:3 и bias соответственно одна треть, то по датaшиту должна быть соответствующая адресация данных.
Опять что-то не так, но что именно, не пойму.
Сейчас такой скетч, он должен показывать надпись CODE
#define I2C_ADDR B0111000
#include <Wire.h>
void setup()
{
Wire.begin();
/* init
E0CBF000000000000000
E0CBF020000000000000
E0CBF000000000000000
E0CBF020000000000000
11100000 11001011 11110000 00000000 00000000 00000000 00000000 00000000
11100000 11001011 11110000 00100000 00000000 00000000 00000000 00000000
11100000 11001011 11110000 00000000 00000000 00000000 00000000 00000000
11100000 11001011 11110000 00100000 00000000 00000000 00000000 00000000
*/
Wire.beginTransmission(I2C_ADDR);
Wire.send(B11001011); // MODE SElECT
Wire.send(B11110000); // BLINK OFF
Wire.send(B00000000);
Wire.send(B00000000);
Wire.send(B00000000);
Wire.send(B00000000);
Wire.send(B00000000);
Wire.endTransmission();
Wire.beginTransmission(I2C_ADDR);
Wire.send(B11001011); // MODE SElECT
Wire.send(B11110000); // BLINK OFF
Wire.send(B00100000);
Wire.send(B00000000);
Wire.send(B00000000);
Wire.send(B00000000);
Wire.send(B00000000);
Wire.endTransmission();
Wire.beginTransmission(I2C_ADDR);
Wire.send(B11001011); // MODE SElECT
Wire.send(B11110000); // BLINK OFF
Wire.send(B00000000);
Wire.send(B00000000);
Wire.send(B00000000);
Wire.send(B00000000);
Wire.send(B00000000);
Wire.endTransmission();
Wire.beginTransmission(I2C_ADDR);
Wire.send(B11001011); // MODE SElECT
Wire.send(B11110000); // BLINK OFF
Wire.send(B00100000);
Wire.send(B00000000);
Wire.send(B00000000);
Wire.send(B00000000);
Wire.send(B00000000);
Wire.endTransmission();
/* CODE
E0CBF000000A96311460A1000
E0CBF02000156CE062C1460000
E0CBF00000188404118000
E0CBF020004118840410000
11100000 11001011 11110000 00000000 00000000 00001010 10010110 00110001
11100000 11001011 11110000 00100000 00000000 00010101 01101100 11100000
*/
Wire.beginTransmission(I2C_ADDR);
Wire.send(B11001011); // MODE SElECT
Wire.send(B11110000); // BLINK OFF
Wire.send(B00000000);
Wire.send(B00000000);
Wire.send(B00001010);
Wire.send(B10010110);
Wire.send(B00110001);
Wire.endTransmission();
Wire.beginTransmission(I2C_ADDR);
Wire.send(B11001011); // MODE SElECT
Wire.send(B11110000); // BLINK OFF
Wire.send(B00100000);
Wire.send(B00000000);
Wire.send(B00010101);
Wire.send(B01101100);
Wire.send(B11100000);
Wire.endTransmission();
}
void loop()
{
}
Показывает вот что
Оказывается, что после первого же пакета возникает NACК - нет ответа от девайса...
Хм...
Проверь какая установлена скорость шины I2C с дуины.
Проверь какая установлена скорость шины I2C с дуины.
По умолчанию стоит 100 кГц, попробовал поставить 400, как здесь
http://copysol.blogspot.com/2013/01/arduino-i2c-twi-400-mhz-i2c-eeprom.html
перестартовал, пересобрал, перезалил - тоже самое.
Но проблема была в синтаксисе, правильно вот так
Wire.beginTransmission(I2C_ADDR);
byte dataArray[7] = {B11001011, B11110000, B00000000, B00000000, B00000000, B00000000, B00000000};
Wire.write(dataArray, 7);
Serial.print(Wire.endTransmission());
Теперь пакеты доходят, но по-прежнему показывает фигню...
а обязательно побитово слать? помню у меня тоже были проблемы с бинарной отправкой. в хексе все нормально слалось.
а обязательно побитово слать? помню у меня тоже были проблемы с бинарной отправкой. в хексе все нормально слалось.
уже перевел в hex, те же, только в профиль.
Завел частично индикатор
Вот скетч, выводящий слово CODE
#define I2C_ADDR 0x38
#define I2C_SEND_BUFFER_SIZE 17
#include <Wire.h>
void setup() {
delay(5000);
//Serial.begin(115200);//
Wire.begin();
initLCD();
/*
Wire.beginTransmission(I2C_ADDR);
uint8_t dataArray3[I2C_SEND_BUFFER_SIZE] = { 0xE0, 0xCB, 0xF0, 0, 0, 0, 0, 0, 169, 99, 1, 20, 96, 161, 0, 0, 0 };
// uint8_t dataArray3[I2C_SEND_BUFFER_SIZE] = { 0xE0, 0xCB, 0xF0, 0, 0, 0, 0, 0, 169, 0, 0, 0, 0, 0, 0, 0, 0 };
Wire.write(dataArray3, I2C_SEND_BUFFER_SIZE);
Wire.endTransmission();
*/
unsigned char data[14];
data[0] = 0x00;
data[1] = 0x00;
data[2] = 0x00;
data[3] = 0x00;
data[4] = 0x00;
data[5] = 0xA9;
data[6] = 0x63;
data[7] = 0x01;
data[8] = 0x14;
data[9] = 0x60;
data[10] = 0xA1;
data[11] = 0x00;
data[12] = 0x00;
data[13] = 0x00;
sendDataToLCD(data);
/*
Wire.beginTransmission(I2C_ADDR);
uint8_t dataArray4[I2C_SEND_BUFFER_SIZE] = { 0xE0, 0xCB, 0xF0, 2, 0, 0, 0, 21, 108, 224, 98, 12, 20, 96, 0, 0, 0 };
//uint8_t dataArray4[I2C_SEND_BUFFER_SIZE] = { 0xE0, 0xCB, 0xF0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
Wire.write(dataArray4, I2C_SEND_BUFFER_SIZE);
Wire.endTransmission();
*/
unsigned char data2[14];
data2[0] = 0x02;
data2[1] = 0x00;
data2[2] = 0x00;
data2[3] = 0x00;
data2[4] = 0x15;
data2[5] = 0x6C;
data2[6] = 0xE0;
data2[7] = 0x62;
data2[8] = 0x0C;
data2[9] = 0x14;
data2[10] = 0x60;
data2[11] = 0x00;
data2[12] = 0x00;
data2[13] = 0x00;
sendDataToLCD(data2);
}
void loop() {
}
void sendDataToLCD(unsigned char *data) {
unsigned char buffer[I2C_SEND_BUFFER_SIZE];
byte i = 0;
buffer[0] = 0xE0;
buffer[1] = 0xCB;
buffer[2] = 0xF0;
for (i = 3; i < I2C_SEND_BUFFER_SIZE; i ++) {
buffer[i] = data[i - 3];
}
Wire.beginTransmission(I2C_ADDR);
Wire.write(buffer, I2C_SEND_BUFFER_SIZE);
Wire.endTransmission();
}
void initLCD() {
/* init
E0CBF000000000000000
E0CBF020000000000000
E0CBF000000000000000
E0CBF020000000000000
*/
/*
Wire.beginTransmission(I2C_ADDR);
uint8_t dataArray[I2C_SEND_BUFFER_SIZE] = { 0xE0, 0xCB, 0xF0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
Wire.write(dataArray, I2C_SEND_BUFFER_SIZE);
Serial.print(Wire.endTransmission());
Wire.beginTransmission(I2C_ADDR);
uint8_t dataArray2[I2C_SEND_BUFFER_SIZE] = { 0xE0, 0xCB, 0xF0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
Wire.write(dataArray2, I2C_SEND_BUFFER_SIZE);
Serial.print(Wire.endTransmission());
*/
unsigned char data[14];
byte i = 0;
for (i = 0; i <= 14; i++) {
data[i] = 0x00;
}
sendDataToLCD(data);
data[0] = 0x20;
sendDataToLCD(data);
}
Дело за малым, написать кусок кода, который будет выводить произвольную строку. Проблема сейчас в том, что используется мультиплексирование для вывода данных.
Нашел только куски кода для 1:2
Может у кого-то есть готовый кусок кода для случая 1:3 ?
Раскурил индикатор.
Если кому понадобится, вот скетч для управления любым сегментом через COM-порт
#define I2C_ADDR 0x38
#define I2C_SEND_BUFFER_SIZE 17
#include <Wire.h>
void setup() {
Serial.begin(115200);//
Wire.begin();
initLCD();
}
void loop() {
String content = "";
char character;
while(Serial.available()) {
character = Serial.read();
content.concat(character);
}
if (content != "") {
Serial.println(content);
if (content == "!") {
Serial.println("Reset");
initLCD();
}
else {
int numArgs = 0;
int beginIdx = 0;
int idx = content.indexOf(",");
String arg;
Wire.beginTransmission(I2C_ADDR);
while (idx != -1) {
numArgs++;
arg = content.substring(beginIdx, idx);
Serial.println((byte)arg.toInt());
Wire.write((byte)arg.toInt());
if (numArgs == 17) {
Serial.println('#');
Wire.endTransmission();
Wire.beginTransmission(I2C_ADDR);
}
beginIdx = idx + 1;
idx = content.indexOf(",", beginIdx);
}
arg = content.substring(beginIdx);
Serial.println((byte)arg.toInt());
Wire.write((byte)arg.toInt());
Wire.endTransmission();
}
}
}
void sendDataToLCD(unsigned char *data) {
unsigned char buffer[I2C_SEND_BUFFER_SIZE];
byte i = 0;
Wire.beginTransmission(I2C_ADDR);
buffer[0] = 0xE0;
buffer[1] = 0xCB;
buffer[2] = 0xF0;
for (i = 3; i < I2C_SEND_BUFFER_SIZE; i ++) {
buffer[i] = data[i - 3];
}
Wire.write(buffer, I2C_SEND_BUFFER_SIZE);
Wire.endTransmission();
}
void initLCD() {
/* init
E0CBF000000000000000
E0CBF020000000000000
E0CBF000000000000000
E0CBF020000000000000
*/
unsigned char data[14];
byte i = 0;
for (i = 0; i <= 14; i++) {
data[i] = 0x00;
}
sendDataToLCD(data);
data[0] = 0x20;
sendDataToLCD(data);
}
Вот такая строка выводит слово CODE
224,203,240,0,0,0,0,0,169,99,1,20,96,161,0,0,0,224 ,203,240,2,0,0,0,21,108,224,98,12,20,96,0,0,0
Для удобного манипулирования такими строками написал маленькое веб-приложение на PHP, которое формирует и отправляет в указанный порт такие строки.
Проверено под Виндой под запущенным USBWebserver.
Установка проста - распаковать в корневую папку вебсервера, в файле index.php указать номер порта и скорость (сейчас COM3 и 9600).
Приложение будет доступно по адресу http://localhost/com/
Можно задавать значения в десятичном, шестнатеричном, бинарном форматах. Все значения будут немедленно отправлены в индикатор.
Можно стереть все символы кнопкой Reset.
Работает на vBulletin® версия 3.8.4. Copyright ©2000-2025, Jelsoft Enterprises Ltd. Перевод: zCarot