РУКОДЕЛКИ ATtiny2313 и LCD (LCM1602C) экран

Evgeniy2020

✩✩✩✩✩✩✩
12 Июл 2020
91
0
Всем доброго времени суток! Будет длинный сказ о проекте =)
Посетила меня идея сделать устройство для "работы" с аккумуляторами Li-on. Данная устройство занималось бы зарядкой аккумов и измерением их ёмкости. У Гайвера был видос по данной теме, от туда и пошли корни моего проекта. Зарядкой занималась бы микруха tp4056, планирую сделать на два аккумулятора (две банки). Разряжать на батарею резисторов (20 шт 4.7 Ом) Общее сопротивление около 3,76 ом. Что при рабочем напряжении аккумулятора около 3.7-3.8В дало б около 1А тока разрядки. Думаю для банок 18650 и др. Ток великоват) но что поделать =). Теперь встал вопрос с камнем. Из старой сигнализации я выпаял ATtiny2313 и долго думал куда бы его впихнуть, вот думаю самое время. До этого с голыми камнями не работал, да и честно говоря не стал я еще и "гуру" ардуино (если так высказаться можно), но захотелось попробовать. 2Кб флэша тяжело конечно но надеюсь влезу =)

Подвигаемся к теме отображения. У меня есть два LCD дисплея. Один LCD1602 без переходника вот такой (LCM1602C)1625839949022.png

И LCD 2004 с переходником на I2C(TWI). I2C на микрухе PCF8574T. Сам дисплей такой(SunStar 2004A)
1625840203075.png

Ну думаю два провода лучше чем подключать 1602. В общем в ходе долгих мучительных поисков как запустить на тиньке I2C узнал много нового) В общем в тиньке нету аппаратной поддержки I2C(TWI) но есть не что, с чем как я понял играться можно вечно модуль USI. Много прочитал про него, многие так и говорят что мол нормального I2C добиться тяжко. Долго подумав вспомнил что чего нету аппаратно можно сделать программно. Погуглил нашел пару библеотек в которых чисто функционал минимальный. Может функций 5 на всю либу. И тут уже 1/4 памяти хоба) И испарилась, так дислпей на I2C и не заработал. Ну ладно, есть же 1602. Ног у тиньки не много, но и не мало, найдеться куда впихнуть дислпей. По гуглил и тд. Нашел целую серию видео и статью от одного автора Narod Stream. (Статья). Код я там по видео писал, получился вот такой.
Основной код:
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>

//-------------------------------------------------------------------
#define e1 PORTB |= 0b00001000 //Установка пина Е в 0, и в 1
#define e0 PORTB &= 0b11110111

#define rs1 PORTB |= 0b00000100 //Установка пина RS в 0, и в 1
#define rs0 PORTB &= 0b11111011
//-------------------------------------------------------------------
void SendHalfByte(unsigned char c){
    c<<=4;
    e1;
    _delay_us(50);
    PORTB&=0b00001111;
    PORTB |= c;
    e0;
    _delay_us(50);
}
void sendByte(unsigned char c, unsigned char mode){
    if (mode == 0)
    {
        rs0;
    }
    else
    {
        rs1;
    }
    unsigned char Hc = 0;
    Hc=c>>4;
    SendHalfByte(Hc);
    _delay_us(20);
    SendHalfByte(c);
    _delay_us(20);
}
void sendStr(const char *s){
    int i;
    for(i =0; s[i] != '\0';i++){
        sendByte(s[i],1);
    }
}
void port_init(void){
    DDRB = 0xFF;
    PORTB = 0x00;
}
void lcd_clear(void){
    sendByte(0b00000001,0);
    _delay_ms(1);
}
void lcd_init(void){
    _delay_ms(15);//Ждем пока дисплейный контролер очухаеться
    SendHalfByte(0b00000011);
    _delay_ms(4);
    SendHalfByte(0b00000011);
    _delay_us(100);
    SendHalfByte(0b00000011);
    _delay_ms(1);
    SendHalfByte(0b00000010);
    _delay_ms(1);
    sendByte(0b00101000,0);
    _delay_ms(1);
    sendByte(0b00001100,0);
    _delay_ms(1);
    sendByte(0b00000110,0);
    _delay_ms(1);
}
void setPos(unsigned char x, unsigned char y){
    unsigned char addr = 0;
    addr = (0x40*y+x)|0b10000000;
    sendByte(addr,0);   
}
int main(void){
    port_init();
    lcd_init();
    setPos(0,0);
    sendByte('n',1);
    sendStr("Hello");
    setPos(4,1);
    sendStr("Word");

    while (1){

    }
}
Да знаю задержки все дела, тут можно оптимизировать и оптимизировать но этом потом =)
Сделал в протеусе проект, там все настроил и тд. В общем работает.
1625841291917.png


Но на реальном устройстве дисплей не заработал. Схема в реальности подобная только подведено питание, и потенциометр на контрастность. И вот я не знаю куда копать. Два дисплея не один не завелся. Документацию на 1602 толковую не нашел, да и врядли-бы починил бы если бы нашел =)
Ув. формучане подскажите может кто сталкивался с такими Lcd1602. Может тайминги не те выбрал, может байты инициилизации или команд отличаються ? Или же проще USI запустить да юзать 2004.. Нуждаюсь в вашей помощи!
 

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,407
976
58
Марий-Эл
статью от одного автора Narod Stream
Не ходи туда. Там плохому научат.
А вообще библиотека запуска дисплея по 4 проводам пишется на коленке за день.
Правда, если он поддерживает.
Не все это умеют.
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,969
632
44
Если подключаешь без I2C-контроллера как показано на схеме, то:
1) VDD подключен к питанию?
2) VEE подключен через переменный резистор для регулирования контрастности?

3) Попробуй для начала помигать светодиодом, может МК нерабочий.

Документацию на 1602 толковую не нашел
Там все до ужаса просто: 没有幻灯片标题 (waveshare.com)
 
Изменено:

Evgeniy2020

✩✩✩✩✩✩✩
12 Июл 2020
91
0
@Эдуард Анисимов, та читал что много говорят что плоховато, но единственный нормальный код который нашёл.
По 4 проводам что проц магёт, этот дисплей с набора ардуино стартер пак, и по схеме с книги (с того же набора) он подключается по 4 проводам(фактически 6 кнш, тип RS и Е но не суть)

@Геннадий П, по поводу МК рабочий сто проц, светодиодами мигал. Правда не на этих выводах, на порте Д мигал, но думаю не суть.
Тут даже чуть уточню вопрос) Может как-то по другому индикацию замутить. Просто заряд можно и светодиодами показывать, но вот ёмкость..... Можно конечно UART но чую опять этот USI. Я чёт совсем не вкурил эго работу)
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,969
632
44
@Evgeniy2020, Еще раз проверьте какую частоту контроллеру задаете, т.к. код жестко под 8МГц сделан

C++:
#define F_CPU 8000000UL
 

Evgeniy2020

✩✩✩✩✩✩✩
12 Июл 2020
91
0
@Геннадий П, Да по дефолту стоит тактование от 8мгц но включен делитель частоты на 8, (Фьюз CKDIV8 или как-то так =)
Но его я офнул (т.е теперь тактуюсь от внутреннего на 8мгц), и когда мигал светодиодами то используя технологию слова "триста тридцать три"(говориться примерно за секунду) наблюдал мигание светодиодов частотой в 1с.
Купил пару кварцов на 8мгц, попробую с ними. Без конденсаторов можно ?)
 

Evgeniy2020

✩✩✩✩✩✩✩
12 Июл 2020
91
0
@Геннадий П, тогда от внутреннего =)
Я ещё не шарю, там возле частоты пишутся миллисекунды, как я понял это время старта чего-то, чем больше тем видимо точнее. В общем по дефолту во фьзах стоит максимальная цыфра, я и не менял =)
А вообще библиотека запуска дисплея по 4 проводам пишется на коленке за день.
Та вот написал на каленке - не пашет =)
Upd:
Думал может дисплей из семи сегментных индикаторов(завалялось сдвиговые регистры заодно) ...
 

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,407
976
58
Марий-Эл

Evgeniy2020

✩✩✩✩✩✩✩
12 Июл 2020
91
0
Можете у Вас завалялось где-то что-нибудь подобное но рабочие =)
UPD:
Попробовал другой код, поменял дефайны под себя в протеусе работает, на моем экране - не пашет =)
C++:
#define F_CPU 8000000UL            /* Define CPU Frequency e.g. here 8MHz */
#include <avr/io.h>            /* Include AVR std. library file */
#include <util/delay.h>            /* Include Delay header file */

#define LCD_Dir  DDRB            /* Define LCD data port direction */
#define LCD_Port PORTB            /* Define LCD data port */
#define RS PB2                /* Define Register Select pin */
#define EN PB3                 /* Define Enable signal pin */


void LCD_Command( unsigned char cmnd )
{
    LCD_Port = (LCD_Port & 0x0F) | (cmnd & 0xF0); /* sending upper nibble */
    LCD_Port &= ~ (1<<RS);        /* RS=0, command reg. */
    LCD_Port |= (1<<EN);        /* Enable pulse */
    _delay_us(1);
    LCD_Port &= ~ (1<<EN);

    _delay_us(200);

    LCD_Port = (LCD_Port & 0x0F) | (cmnd << 4);  /* sending lower nibble */
    LCD_Port |= (1<<EN);
    _delay_us(1);
    LCD_Port &= ~ (1<<EN);
    _delay_ms(2);
}


void LCD_Char( unsigned char data )
{
    LCD_Port = (LCD_Port & 0x0F) | (data & 0xF0); /* sending upper nibble */
    LCD_Port |= (1<<RS);        /* RS=1, data reg. */
    LCD_Port|= (1<<EN);
    _delay_us(1);
    LCD_Port &= ~ (1<<EN);

    _delay_us(200);

    LCD_Port = (LCD_Port & 0x0F) | (data << 4); /* sending lower nibble */
    LCD_Port |= (1<<EN);
    _delay_us(1);
    LCD_Port &= ~ (1<<EN);
    _delay_ms(2);
}

void LCD_Init (void)            /* LCD Initialize function */
{
    LCD_Dir = 0xFF;            /* Make LCD port direction as o/p */
    _delay_ms(20);            /* LCD Power ON delay always >15ms */
    
    LCD_Command(0x02);        /* send for 4 bit initialization of LCD  */
    LCD_Command(0x28);              /* 2 line, 5*7 matrix in 4-bit mode */
    LCD_Command(0x0c);              /* Display on cursor off*/
    LCD_Command(0x06);              /* Increment cursor (shift cursor to right)*/
    LCD_Command(0x01);              /* Clear display screen*/
    _delay_ms(2);
}


void LCD_String (const char *str)        /* Send string to LCD function */
{
    int i;
    for(i=0;str[i]!=0;i++)        /* Send each char of string till the NULL */
    {
        LCD_Char (str[i]);
    }
}

void LCD_String_xy (char row, char pos, const char *str)    /* Send string to LCD with xy position */
{
    if (row == 0 && pos<16)
    LCD_Command((pos & 0x0F)|0x80);    /* Command of first row and required position<16 */
    else if (row == 1 && pos<16)
    LCD_Command((pos & 0x0F)|0xC0);    /* Command of first row and required position<16 */
    LCD_String(str);        /* Call LCD string function */
}

void LCD_Clear()
{
    LCD_Command (0x01);        /* Clear display */
    _delay_ms(2);
    LCD_Command (0x80);        /* Cursor at home position */
}

int main()
{

    LCD_Init();            /* Initialization of LCD*/

    LCD_String("ElectronicWINGS");    /* Write string on 1st line of LCD*/
    LCD_Command(0xC0);        /* Go to 2nd line*/
    LCD_String("Hello World");    /* Write string on 2nd line*/
    while(1);
}
 
Изменено:

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,407
976
58
Марий-Эл
Вот. Смотрите. Может чем поможет. Но честно говоря я бы её сейчас заново переписал в свете тог, что я сейчас знаю.
Она довольна неуклюжа.
 

Вложения

Evgeniy2020

✩✩✩✩✩✩✩
12 Июл 2020
91
0
@Эдуард Анисимов, Спасибо. Уже посмотрел, стяну у Вас в будущем байты инициализации.

Правда я тут заметил что камушек похоже по моей не осторожности под горел.

Может вечер, из-за чего не могу понять причину. Может камень и вправду подгорел. Программа такая
C++:
#define F_CPU 8000000UL

#include <avr/io.h>

#include <util/delay.h>

#define MIG 300

#define VD PORTD

int main(void)

{

    DDRD = 0b000000011;

    while (1)

    {

        VD = 0b000000001; // Включаем 1-й светодиод

        _delay_ms(MIG);     // Ждем 0,5 секунды

        VD = 0b000000000; // Выключаем 1-й

        _delay_ms(MIG);     // Ждем 0,5 секунды

        VD = 0b000000010; // Включаем 2-й

        _delay_ms(MIG);     // Ждем 0,5 секунды

        VD = 0b000000000; // Выключаем 2-й

        _delay_ms(MIG);     // Ждем 0,5 секунды

    }

}
Фьюзы ставлю полностью дефолтные (знаю что делитель на 8 вкл)
1626034053988.png
И на пине которые отвечают за горение светодиода, НЕ пропадает напряжение и не становиться равным 5В
Напряжение с подкл. светодиодом колеблиться между 1.98В (логический 0) и 3.92 (логическая 1) причем на контакте без светодиода напряжение поднимаеться до 5В.

При прошивки правильными фьюзами
1626034825258.png
Вообще мистика, напряжение после первой пары секунд устаканиваеться и все, не чего не мигает. То через время начинает мигать. Напряжение не выше 2.90В

Но раньше все было нормально......

UPD: Может же быть причина в том что я разок тыкнул землю в питание =) Просто я ожидал что МК просто умрет от такого, но чтобы полностью читаться аврдудой, проходить верефикацию флеша и тд. Но на пинах что-то странное твориться

UPD2: Камушек помер, на запросы дуды не отвечает, уже не чего не соовсем не мигает. Для будующих поколений которые столнуться с таким дисплеем нашел нормальный даташит
даташит
На всякий случай прикреплю файл сюда, может на искомом сайте его удалят )
 

Вложения

Изменено:

bort707

★★★★★★✩
21 Сен 2020
3,062
912
@Evgeniy2020, сорри за глупый вопрос, надеюсь светодиоды подключали через резистор?
 

Evgeniy2020

✩✩✩✩✩✩✩
12 Июл 2020
91
0
@bort707, Светодиод подсветки дисплея да. А обычные к пинам - напрямую, там же секунды работы, да и светодиод не жалко, что насчёт пина МК то ток светодиода не превышал 23мА, что в свою очередь не превышает 40мА пина МК. Просто понять мигает или нет.
 

poty

★★★★★★✩
19 Фев 2020
3,230
940

@Evgeniy2020, да уж... Решение из разряда можно ли подключать блок питания на 5А к устройству, которое потребляет 0,5А.
Откуда известно, что светодиод потреблял 23мА?
 

poty

★★★★★★✩
19 Фев 2020
3,230
940

@Evgeniy2020, ЛБП на какой ток отсечки был настроен? Под каким напряжением измеряли?
 

Evgeniy2020

✩✩✩✩✩✩✩
12 Июл 2020
91
0
@poty, заведомо мерял на 5В, ток отсечки стоял 1А. При этом потреблялось около 23мА
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,969
632
44
@Evgeniy2020, Никогда не подключай светодиод к источнику напряжения без токоограничительного резистора. Светодиоду нужен ток, а не напряжение.
Резистор расчитывается по формуле: R = (Uпит - Uотс) / Iном
Где: Uпит - напряжение питания, Uотс - напряжение отсечки светодиода, Iном - номинальный ток светодиода
Например для светодиода с напряжением отсечки 2.5 В и номинальным током 10 мА при 5 В питании резистор должен быть не меньше 250 Ом
UP: (в реальности резисторов с таким номиналом обычно не бывает, поэтому ставим в бОльшую сторону - 270 Ом)
 
Изменено:

poty

★★★★★★✩
19 Фев 2020
3,230
940
@Evgeniy2020, не верю, если честно. Возможно какой-то хитровымудренный светодиод, конечно, но обычный, думаю, просто бы сгорел.
 

Evgeniy2020

✩✩✩✩✩✩✩
12 Июл 2020
91
0
@poty, не кто и не говорит что светодиоду легко. Но работал же, припускаю что амперметр плохо отрабатывает на таком низком диапазоне. @Геннадий П, Понял
 

Evgeniy2020

✩✩✩✩✩✩✩
12 Июл 2020
91
0
@poty, надеюсь что нет. В любом случае окончательно добил его 5В на землю.