Работа с драйвером TM1629a
- Войдите на сайт для отправки комментариев
Пнд, 05/11/2018 - 15:04
Приветствую ВСЕХ!!!
Нужна помощь спецов!!!
Имеются весы китайского производства (рабочие, все ок), нужно получить информацию о весе на пк, центральный контроллер HT68F40 отправляет данные на драйвер TM1629A 3мя линиями STB, CLK, DIO. Данные выводят на восьмисегментные индикаторы (5 на вес, 5 на цену, 6 на стоимость).
мне бы только массу перехватить
задача №1: заставить Ардуину уно работать с TM1629A (библиотек не нашел, даташит http://nic.vajn.icu/PDF/opto/led7segment/TM1629A-en.pdf);
задача №2: как с помощью Ардуино можно считать сигналы STB, CLK, DIO и выписать в COM-порт (если возможно - поделитесь скетчем)
Судя по даташиту это примерно такая же микросхема, как и TM1628, и TM1668. Работать с нею нужно точно также. Разница там совсем незначительная - только в количестве подключаемых светодиодов и кнопок.
Примеры работы с первой (посмотрите. мы там её долго и по-разному мучали), а вто со второй.
Смотрите код, разбирайтесь. Ваша - такая же.
Спиасибо, Огромное!!!, Ваш код помог запустить половину дисплея, вторую половину не получилось.
Подскажите - где в этом коде отрегулировать идет запись регистра на 2ю часть
#include <stdio.h> static int serial_fputchar(const char ch, FILE *stream) { ((void*)stream); Serial.write(ch); return ch; } static FILE *serial_stream = fdevopen(serial_fputchar, NULL); // // Подключение пинов // разъём отверстиями кверху и синей стороной шлейфа к себе, тогда рсапиновка: // GND 3,3V CLK DIO STB OUT-IR 5V // #define PIN_DIO 9 #define PIN_CLK 8 #define PIN_STB 7 #define INIT_7x11 3 ///////////////////////////////////////////////////////////// ///////////// ТИПА "библиотека" ДЛЯ TM1668 //////////// ///////////////////////////////////////////////////////////// // // при том подключении, что есть // достаточно 10 байтов на светодиоды и 2 на кнопки // #define LED_DATA_LENGTH 14 // // Маски нажатых кнопок (слева направо) // // // Подключено 5 "цифр". // 0-ая - это двоеточие, залействовано только два младших бита // 1-4 - собственно цифры слева направо. // В цифрах задействовано 7 битов под сегменты (с 0-го по 6-ой) // и 7-ой бит под доплнительный символ (питание, конверт и т.п.) // #define SEG_A 0x0020 #define SEG_B 0x0008 #define SEG_C 0x0080 #define SEG_D 0x0040 #define SEG_E 0x0002 #define SEG_F 0x0010 #define SEG_G 0x0004 #define SEG_DP 0x0001 // // Символы (цифры / буквы, можно ещё добавить всяких) // #define SYMBOL_0 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F) #define SYMBOL_1 (SEG_B | SEG_C) #define SYMBOL_2 (SEG_A | SEG_B | SEG_D | SEG_E | SEG_G) #define SYMBOL_3 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_G) #define SYMBOL_4 (SEG_B | SEG_C | SEG_F | SEG_G) #define SYMBOL_5 (SEG_A | SEG_C | SEG_D | SEG_F | SEG_G) #define SYMBOL_6 (SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G) #define SYMBOL_7 (SEG_A | SEG_B | SEG_C) #define SYMBOL_8 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G) #define SYMBOL_9 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G) //#define SYMBOL_MINUS (SEG_G) #define SYMBOL_A (SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G) #define SYMBOL_C (SEG_A | SEG_E | SEG_F | SEG_D) #define SYMBOL_E (SEG_A | SEG_D | SEG_E | SEG_F | SEG_G) #define SYMBOL_H (SEG_B | SEG_C | SEG_E | SEG_F | SEG_G) //#define SYMBOL_P (SEG_A | SEG_B | SEG_E | SEG_F | SEG_G) //#define SYMBOL_G (SEG_A | SEG_E | SEG_F) //#define SYMBOL_L (SEG_D | SEG_E | SEG_F) #define SYMBOL_F (SEG_A | SEG_E | SEG_F | SEG_G) #define SYMBOL_d (SEG_B | SEG_C | SEG_D | SEG_E | SEG_G) #define SYMBOL_b (SEG_C | SEG_D | SEG_E | SEG_F | SEG_G) //#define SYMBOL_rP (SEG_A | SEG_B | SEG_C | SEG_E | SEG_F) // // Глобальные переменные // static uint16_t ledGRID[LED_DATA_LENGTH / 2]; // текущее состояние экрана static uint8_t currentBrightness = 1; // текущая яркость static uint8_t digits[] = { SYMBOL_0, SYMBOL_1, SYMBOL_2, SYMBOL_3, SYMBOL_4, SYMBOL_5, SYMBOL_6, SYMBOL_7, SYMBOL_8, SYMBOL_9 }; // // Запись одиночной команды в TM1668 // void writeSingleCommand(const uint8_t command) { digitalWrite(PIN_STB, LOW); shiftOut(PIN_DIO, PIN_CLK, LSBFIRST, command); digitalWrite(PIN_STB, HIGH); delayMicroseconds(1); // Пауза до следующей команды } // // Запись состояния дисплея в TM1668 // void updateDisplay(void) { writeSingleCommand(0x40); // запись данных, автоматический адрес digitalWrite(PIN_STB, LOW); shiftOut(PIN_DIO, PIN_CLK, LSBFIRST, 0xC0); // Установка адреса в 0 uint8_t * p = (uint8_t *) ledGRID; for (int8_t i = 0; i < LED_DATA_LENGTH; i++, p++) shiftOut(PIN_DIO, PIN_CLK, LSBFIRST, *p); // запись данных digitalWrite(PIN_STB, HIGH); delayMicroseconds(1); // Пауза до следующей команды } // // Установить яркость от 0 (выключено) до 8 // (возвращает старую яркость) // static inline uint8_t setBrightness(const uint8_t newBrighness) { const uint8_t res = currentBrightness; currentBrightness = (newBrighness > 8) ? 8 : newBrighness; if (currentBrightness == 0) writeSingleCommand(0x80); // Выключить дисплей else writeSingleCommand(0x88 + (currentBrightness - 1)); // Установить яркость return res; } // // Показать цифру value (0-9) в позиции digit (1-4) // при этом, если у цифры горит дополнительный символ, сохраняем его // static inline void setDigit(const int8_t digit, const uint8_t value) { if (digit < 0 || digit > 15) return; // цифры у нас с 1-ой по 4-ую слева направо ledGRID[digit] = value; // не обижать дополнительный символ, если есть } ///////////////////////////////////////////////////////////// //////////// КОНЕЦ "библиотеки" ДЛЯ TM1668 //////////// ///////////////////////////////////////////////////////////// void setup(void) { stdout = serial_stream; // эта строка первая в setup Serial.begin(115200); // // Инициализация пинов pinMode(PIN_CLK, OUTPUT); pinMode(PIN_DIO, OUTPUT); pinMode(PIN_STB, OUTPUT); digitalWrite(PIN_STB, HIGH); digitalWrite(PIN_CLK, HIGH); // // Инициализация экрана writeSingleCommand(INIT_7x11); // Режим отображения (1 и 2 - ничего не меняется) setBrightness(currentBrightness); setDigit(0, SYMBOL_0 | SEG_DP); setDigit(1, 0x0088); setDigit(2, SYMBOL_2); setDigit(3, SYMBOL_3 | SEG_DP); setDigit(4, SYMBOL_4); setDigit(5, SYMBOL_5 | SEG_DP); setDigit(6, SYMBOL_6); setDigit(7, SYMBOL_7); //setDigit(8, SYMBOL_8); //setDigit(9, SYMBOL_9); //setDigit(10, SYMBOL_A); //setDigit(11, SYMBOL_b); //setDigit(12, SYMBOL_C); //setDigit(13, SYMBOL_d); //setDigit(14, SYMBOL_E); setDigit(15, SYMBOL_F); updateDisplay(); } void loop(void) { }Кстати , цифра 7 и светодиод под ней светятся независимо от моих настроек, даже если
После перезагрузки 7 и светодиод под ней исчезли и более не включались
Да, так все и получилось, пока Вы писали ответ, я воспользовался Вашим кодом с поста 44, именно ивсе это было сделано)))
Т.е. у Вас горит ВСЁ? Я правильно понял?
Ну, тогда у Вас нет никаких проблем.
Убирайте по одному биту и смотрите (записывайте) какой сведиод погас. Вот и составите "карту". Вы понимаете как это делать? Если нет - не стесняйтесь. спрашивайте.
Когда составите полную карту, поймёте нужны ли Вам все 16 байтов или достаточно первых N - столько и оставите.
Да, все загорелось, и карта составлена
#include <stdio.h> static int serial_fputchar(const char ch, FILE *stream) { ((void*)stream); Serial.write(ch); return ch; } static FILE *serial_stream = fdevopen(serial_fputchar, NULL); // // Подключение пинов // разъём отверстиями кверху и синей стороной шлейфа к себе, тогда рсапиновка: // GND 3,3V CLK DIO STB OUT-IR 5V // #define PIN_DIO 9 #define PIN_CLK 8 #define PIN_STB 7 #define INIT_7x11 3 ///////////////////////////////////////////////////////////// ///////////// ТИПА "библиотека" ДЛЯ TM1668 //////////// ///////////////////////////////////////////////////////////// // // при том подключении, что есть // достаточно 10 байтов на светодиоды и 2 на кнопки // #define LED_DATA_LENGTH 16 // // Подключено 5 "цифр". // 0-ая - это двоеточие, залействовано только два младших бита // 1-4 - собственно цифры слева направо. // В цифрах задействовано 7 битов под сегменты (с 0-го по 6-ой) // и 7-ой бит под доплнительный символ (питание, конверт и т.п.) // #define SEG_A 0x0020 #define SEG_B 0x0008 #define SEG_C 0x0080 #define SEG_D 0x0040 #define SEG_E 0x0002 #define SEG_F 0x0010 #define SEG_G 0x0004 #define SEG_DP 0x0001 #define SEG_A1 0x0100 #define SEG_B1 0x0400 #define SEG_C1 0x1000 #define SEG_D1 0x2000 #define SEG_E1 0x8000 #define SEG_F1 0x0200 #define SEG_G1 0x0800 #define SEG_DP1 0x4000 // // Глобальные переменные // static uint16_t ledGRID[LED_DATA_LENGTH / 2] = { 0x00fe, //2.5dp ; 1.1dp 0x0000, //3.1 ; 3.6 0x0000, //3.2 ; 3.5 0x0000, //3.3 ; 3.4 0x00fe, //2.3 ; 1.3 0x00ff, //2.4 ; 1.2dp 0x00fe, //2.2 ; 1.4 0x00fe //2.1dp ; 1.5dp }; // текущее состояние экрана static uint8_t currentBrightness = 1; // текущая яркость // // Запись одиночной команды в TM1668 // void writeSingleCommand(const uint8_t command) { digitalWrite(PIN_STB, LOW); shiftOut(PIN_DIO, PIN_CLK, LSBFIRST, command); digitalWrite(PIN_STB, HIGH); delayMicroseconds(1); // Пауза до следующей команды } // // Запись состояния дисплея в TM1668 // void updateDisplay(void) { writeSingleCommand(0x40); // запись данных, автоматический адрес digitalWrite(PIN_STB, LOW); shiftOut(PIN_DIO, PIN_CLK, LSBFIRST, 0xC0); // Установка адреса в 0 uint8_t * p = (uint8_t *) ledGRID; for (int8_t i = 0; i < LED_DATA_LENGTH; i++, p++) shiftOut(PIN_DIO, PIN_CLK, LSBFIRST, *p); // запись данных digitalWrite(PIN_STB, HIGH); delayMicroseconds(1); // Пауза до следующей команды } // // Установить яркость от 0 (выключено) до 8 // (возвращает старую яркость) // static inline uint8_t setBrightness(const uint8_t newBrighness) { const uint8_t res = currentBrightness; currentBrightness = (newBrighness > 8) ? 8 : newBrighness; if (currentBrightness == 0) writeSingleCommand(0x80); // Выключить дисплей else writeSingleCommand(0x88 + (currentBrightness - 1)); // Установить яркость return res; } // // Показать цифру value (0-9) в позиции digit (1-4) // при этом, если у цифры горит дополнительный символ, сохраняем его // //static inline void setDigit(const int8_t digit, const uint8_t value) { // if (digit < 0 || digit > 15) return; // цифры у нас с 1-ой по 4-ую слева направо // ledGRID[digit] = value; // не обижать дополнительный символ, если есть //} ///////////////////////////////////////////////////////////// //////////// КОНЕЦ "библиотеки" ДЛЯ TM1668 //////////// ///////////////////////////////////////////////////////////// void setup(void) { stdout = serial_stream; // эта строка первая в setup Serial.begin(115200); // // Инициализация пинов pinMode(PIN_CLK, OUTPUT); pinMode(PIN_DIO, OUTPUT); pinMode(PIN_STB, OUTPUT); digitalWrite(PIN_STB, HIGH); digitalWrite(PIN_CLK, HIGH); // // Инициализация экрана writeSingleCommand(INIT_7x11); // Режим отображения (1 и 2 - ничего не меняется) setBrightness(currentBrightness); updateDisplay(); } void loop(void) { }В строках 56-63, в комментариях карта сегментов (строка, столбец), следующим этапом думаю как развернуть программу, чтобы "слушать" нужный мне код, идущий от другого процессора, в последствии передавая его в Com порт, а далее - дело техники написать ПО
Я только просмотрел, что мне достаточно двух последних байтов
Ну, и отлично. Если какие-то байты не нужны,их можно не передавать. Там же при передаче указываешь адрес и потом шлёшь, разберётесь.
Теперь по поводу считывания, я так понял, что получаю не всю информацию, не все биты прописаны получаются:
#include <stdio.h> static int serial_fputchar(const char ch, FILE *stream) { Serial.write(ch); return ch; } static FILE *serial_stream = fdevopen(serial_fputchar, NULL); #define PIN_DIO 9 #define PIN_CLK 8 #define PIN_STB 7 byte a; void setup() { // put your setup code here, to run once: stdout = serial_stream; // эта строка первая в setup Serial.begin(115200); } void loop() { // put your main code here, to run repeatedly: while (digitalRead(PIN_STB) == LOW){ a = shiftIn(PIN_DIO, PIN_CLK, LSBFIRST); printf("0x%04x\n", a); } }вот что сыпеться в ком:
0x0043
16:45:17.164 -> 0x0001
16:45:17.164 -> 0x0000
16:45:17.164 -> 0x0008
16:45:17.164 -> 0x0003
16:45:17.164 -> 0x00c0
16:45:17.164 -> 0x0000
16:45:17.164 -> 0x0080
16:45:17.164 -> 0x0020
16:45:17.164 -> 0x00d0
16:45:17.164 -> 0x0000
16:45:17.164 -> 0x0001
16:45:17.164 -> 0x006f
16:45:17.164 -> 0x0031
16:45:17.164 -> 0x00a1
16:45:17.164 -> 0x00b4
16:45:17.164 -> 0x00ee
16:45:17.164 -> 0x00ea
16:45:17.164 -> 0x0084
16:45:17.164 -> 0x003e
16:45:17.164 -> 0x0007
16:45:17.164 -> 0x0010
16:45:17.164 -> 0x0000
16:45:17.164 -> 0x001c
16:45:17.164 -> 0x0030
16:45:17.164 -> 0x0026
16:45:17.164 -> 0x00e0
0x0027
0x0010
16:45:17.266 -> 0x0019
16:45:17.266 -> 0x00cd
16:45:17.266 -> 0x0064
16:45:17.266 -> 0x00a6
16:45:17.266 -> 0x0024
16:45:17.266 -> 0x00c1
16:45:17.266 -> 0x0099
16:45:17.266 -> 0x00f8
16:45:17.266 -> 0x0000
16:45:17.266 -> 0x000f
16:45:17.266 -> 0x004f
16:45:17.266 -> 0x0054
16:45:17.266 -> 0x0085
16:45:17.266 -> 0x00d0
16:45:17.266 -> 0x000e
16:45:17.266 -> 0x00b0
16:45:17.266 -> 0x001c
16:45:17.266 -> 0x003f
16:45:17.266 -> 0x0001
16:45:17.266 -> 0x0011
16:45:17.266 -> 0x0001
16:45:17.266 -> 0x000c
16:45:17.266 -> 0x0012
16:45:17.266 -> 0x0024
16:45:17.266 -> 0x00f8
0x0003
16:45:17.334 -> 0x0020
Не хватает пары байтов, Куда ковырять?
Вы читаете 1 байт. А там их 4. Просто прочитайте ещё три и их тоже печатайте.
Только Вы тут никакой команды чтения не деёте - на умолчание надеетесь. Лучше явно задайте (как у меня 0x42 было), а то там есть разница - чтение с инкременом адреса и без него. Хрен егознает, что по умолчанию - будете одно и тоже 4 раза читать.
Вот, кстати, более полный даташит. а то в том, что Вы дали, вообще ничего нет.
я прошу прощения за назойливость, но с портом я никогда не работал (с этой стороны), если не сложно поподробнее расскажите как?
Да, нормальный у Вас printf - он-то чем виноват.
Вы читаете один байт (я по ссылке, что давал, читал 2),а Вам надо для начала читать все 4. Потом разберётесь, какие не нужны.
Вот я переделал свою функция на 4 байта
void readKeyData(uint32_t * data) { digitalWrite(PIN_STB, LOW); shiftOut(PIN_DIO, PIN_CLK, LSBFIRST, 0x42); // чтение данных pinMode(PIN_DIO, INPUT_PULLUP); delayMicroseconds(1); * data = (uint32_t)shiftIn(PIN_DIO, PIN_CLK, LSBFIRST) + ((uint32_t)shiftIn(PIN_DIO, PIN_CLK, LSBFIRST) << 8) ((uint32_t)shiftIn(PIN_DIO, PIN_CLK, LSBFIRST) << 16) ((uint32_t)shiftIn(PIN_DIO, PIN_CLK, LSBFIRST) << 24); pinMode(PIN_DIO, OUTPUT); digitalWrite(PIN_STB, HIGH); }А вызывать её будете так:
uint32_t data; readKeyData(& data); printf("0x%08ld\n", data);Вот и увидите 32 бита вместо нынешних 8-ми.
нашел проблему!, может повторюсь, но ардуинка у меня не занимает место ЦП,
система такая:
мне не нужно TM1629a опрашивать,
есть в весах свой проц, который посылает комманды на 2 табло.
я подключают ардуинку также как табло к процессору (как 3е табло),
но мне нужна именно та информация что на табло, только в ПК.
Изучив ПО что Вы создали, в Вашем случае идет прос драйвера.
В конечном итоге я хочу оставить весы такими как были, только добавить порт коммуникации
Ну, тогда думайте, смотрите. Если Весы как-то опрашивают, то значит, подключившись "параллельно" можно эту информацию тырить, наверное, тут я плохой помошник.
Евгений, БЛАГОДАРЮ ВАС, с Вашей помощью половину дела сделано, буду пытать далее по поводу перехвата данных
По теории, выше - попытался подключить ардуинку в "разрез" между табло и контроллером - результат говорит - что вероятность получить данные в этом месте почти 0;
при простом коде
#define PIN_DIOO 9 #define PIN_CLKO 8 #define PIN_STBO 7 #define PIN_DIOI 5 #define PIN_CLKI 4 #define PIN_STBI 3 void setup() { // put your setup code here, to run once: pinMode(PIN_CLKO, OUTPUT); pinMode(PIN_DIOO, OUTPUT); pinMode(PIN_STBO, OUTPUT); pinMode(PIN_CLKI, INPUT); pinMode(PIN_DIOI, INPUT); pinMode(PIN_STBI, INPUT); } void loop() { // put your main code here, to run repeatedly: digitalWrite(PIN_CLKO, digitalRead(PIN_CLKI)); digitalWrite(PIN_DIOO, digitalRead(PIN_DIOI)); }получил хаотичное зажигание всех сегментов
мне кажеться что частота в том процессоре HT68F40 на порядок выше, чем у ардуинки, дайте знать - если что не так.
Да всё не так. Берете осциллограф или логический анализатор и смотрите частоту. Затем думаете - зачем пропускать через МК траффик, если его можно подслушать.
Осцилографа неимею, подслушать хотел, но отработать несмог, может есть какие наработки?
про драйвер почти все известно, а про HT68F40- мало, учитывая что там внутри
Осцилографа неимею, подслушать хотел, но отработать несмог, может есть какие наработки?
Наработки есть две, называются "осциллограф" и "логический анализатор".
Вот, допустим, кулинарный форум: люди обсуждают особенности температурного режима, применения специй и пр. И тут возникает некто, кто спрашивает: а как мне приготовить борщ без кастрюли, воды и огня?
Это вопрос для форума по выживанию в экстремальных ситуациях, а не для кулинарного форума.
Так же и здесь: как Вы собираетесь настраивать устройство без осциллографа?
(может, если нет осциллографа, хрустальный шар поможет?)
задача изначально была простая - Подключить весы к пк (стянуть информацию о весе)
вот и решил что в этом месте будет удобнее, если разобраться с TM1629A (т.е. какая информация ему нужна).с этим разобрался.
Я даже не догадывался что здесь могут понадобиться какие-либо другие приборы
Видите-ли, салат можно приготовить и без кастрюли, воды и огня. Но если Вы собираетесь заниматься приготовлением пищи, а не только салатов, то и кастрюля, и вода, и огонь Вам рано или поздно понадобятся.
И если Вы не разбираетесь в приготовлении какого-то конкретного блюда, вряд ли можете заранее определить, что из кухонной утвари Вам не понадобится.
тогда вопрос на засыпку - если подключить к тензодатчику 2 потребителя-считывателя - все живы остпнуться?
Евгений, добрый день! не смотря на давность поста, решусь написать.
У меня возникла следующая ситуация. Имеется устройство с установленными сегментниками, stm и tm1629A.
Задача заключается в подслушивании общения между stm и tm1629a, для дальнейшего понимания о отображенных данных на сегментниках.
На данном этапу было сделано и получено следующее:
1) сканирую передаваемые биты:
if (digitalRead(PIN_STB) == LOW ) { if (digitalRead(PIN_CLK) == LOW) { a=shiftIn(PIN_DIO, PIN_CLK, LSBFIRST); printf("L %x\n",a); } else { a=shiftIn(PIN_DIO, PIN_CLK, LSBFIRST); printf("H %x\n",a); } }Почему так? Потому, что в исходной функции shiftIn я отключил отправку данных в CLK и заменил на чтение, т.к. отправлять данные мне никакие ну нежно а нужно их считать и разграничить. Возможно и не правильно. Для этого и пишу.
2) По итогу я получаю данные с кучей пропусков, мои подозрения падают на скорость работы кода в ардуинки.
Вот что я получаю в сериал порт:
Вопрос- как получить полный набор данных? Были подозрения что данные теряются из-за постоянного вызова сериал порта. Пробовал их выводить буфером, но к сожалению результат тот же.
Евгений, у меня к вам вопрос. Вопрос находится выше)