Комментарии 22
Хорошо бы увидеть прибор в действии — тогда это будет завершенная разработка.
В следующий раз лучше материал подготовить в полной мере: читать будет интереснее, а проделанная Вами работа-нягляднее.
Если на схеме все правильно нарисовано, не совсем понятно, как будет VT1 открываться.
Посмотрел схему. Ой-ей… Вот VT1 — это действительно. Я бы на месте автора поставил P-канальный MOSFET и подтягивал затвор к массе, а не вот так.
По схеме транзистор в целом будет открываться, но окажется в режиме стабилизатора тока. Так как затвор притягивается к стоку, а при достаточном затворном напряжении, сопротивление канала будет стремиться к нулю, соответственно и разница напряжений между стоком и затвором, соответственно, транзистор будет закрвыаться… Ой-ой-ой. А это для схемы окажется фатальным вследствие выделения большого количества тепла на транзисторе.

> после чего наш оптрон открывается и питание идет на затвор полевого транзистора VT1, полевик открывается и на наш эл. клапан подается полноценные 12 вольт.
Полноценных 12V не будет в этой схеме.
Все работает ничего не греется и на выходе ровно столько сколько подал.
Не должно. Попробуйте нагрузить транзистор чем-то потребляющим несколько больший ток, а затем замерьте падение напряжения на нём. Так, как у Вас на схеме нарисовано, транзистор будет греться и поддерживать на себе падение напряжения в пределах 0.7~3V.
Человека сложно переубедить, если он увидел, например, тестером, что все открывается и работает. Но имхо схемное решение выбрано абсолютно неправильно. Тут или ключ другой проводимости, оставив управление «плюсом», или той же проводимости, но тогда управлять «минусом», при этом, если подобрать правильный транзистор, то управлять можно прямо с ножки МК.
Автор не хочет комментировать, а я себе уже мозг сломал :)

AlanDrakes, возможно мы с вами были не правы. На схеме то нарисован транзистор со встроенным каналом, при отрицательном смещении на затворе он должен закрываться. Но все равно схема так себе… :)
Судя по описанию работы схемы канал там индуцированный да и встроенный — экзотика.
Просто нарисовано как встроенный.
Тоже возможно.
К сожалению, он не указан, так что мы с вами действительно гадаем на чайной гуще.
Но встреная точка зрения всё же бывает полезной. Благодарю. =)
Вот блин… купил пару месяцев назад на Али такие же индикаторы, а в сети все исходники для них на Ардуино. А я хотел сделать вариант на пике. Плюс мне ещё i2c отладить не на чем, потому в итоге я даже не могу со 100% вероятностью пройти процесс инициализации модуля — в сети валяется три варианта (один из старой PDF-ки по дисплеям 1602, другой из библиотеки для ардуино и третий из переводов с китайских спеков) стоит хоть что-то поменять в алгоритме, на экране билиберда, а где ошибся не понять…

Никто не знает какой у них должен быть алгоритм инициализации и есть ли универсальный вариант?
Использую такой алгоритм для HD44780*
Код
// E = PORTB3
// RS = PORTB2
// R/W = PORTB1

#define LCD_E		(1<<PORTB3)
#define LCD_RS		(1<<PORTB1)
#define LCD_RW		(1<<PORTB2)

#define LCD_PORT_DDR	DDRB
#define LCD_PORT	PORTB
#define LCD_PORT_READ	PIND
#define LCD_DATA_MASK	0xF0

void LCD_SendNibble(char Nibble, char IsCMD)
{
	LCD_PORT_DDR |= LCD_DATA_MASK;	// OUT
	if (IsCMD)
	{
		LCD_PORT &= ~LCD_RS;	// Instruction
	} else {
		LCD_PORT |= LCD_RS;	// Data
	};
	LCD_PORT &= ~LCD_RW;		// Write
	LCD_PORT &= ~LCD_DATA_MASK;	// Data...
	LCD_PORT |= (Nibble << 4);	// Actually, data
	_delay_us(100);
	LCD_PORT |= LCD_E;		// Strobe
	_delay_us(300);
	LCD_PORT &= ~LCD_E;		// Strobe end.
	_delay_us(100);
};

void LCD_SendByte(char Data, char IsCMD)
{
	LCD_SendNibble(Data>>4, IsCMD);
	LCD_SendNibble(Data & 0x0F, IsCMD);
};

char LCD_GetNibble(char IsCMD)
{
	char i;
	LCD_PORT_DDR &= ~LCD_DATA_MASK;	// IN
	LCD_PORT |= LCD_DATA_MASK;	// Pull-UP
	if (IsCMD)
	{
		LCD_PORT &= ~LCD_RS;	// Instruction
	} else {
		LCD_PORT |= LCD_RS;	// Data
	};
	LCD_PORT |= LCD_RW;		// Read
	_delay_us(100);
	LCD_PORT |= LCD_E;		// Strobe
	_delay_us(300);
	LCD_PORT &= ~LCD_E;		// Strobe end.
	_delay_us(100);
	i = ((LCD_PORT_READ & LCD_DATA_MASK) >> 4);
	return i;
};

char LCD_GetByte(char IsCMD)
{
	char i;
	i = LCD_GetNibble(IsCMD);
	i |= (LCD_GetNibble(IsCMD) >> 4);
	return i & 0x80;
};

char LCD_IsBusy(void)
{
	return LCD_GetByte(1);
};

void LCD_Init(void)
{
	DDRB |= 0xFE;
	while (LCD_IsBusy());
	LCD_SendNibble(0x02, 1);
	while (LCD_IsBusy());
	LCD_SendByte(0x28, 1);
	while (LCD_IsBusy());
	LCD_SendByte(0x0F, 1);
	while (LCD_IsBusy());
	LCD_SendByte(0x06, 1);
	while (LCD_IsBusy());
	LCD_SendByte(0x80, 1);
	while (LCD_IsBusy());
};


После этого можно писать в дисплей.

И это самый универсальный вариант как раз для 44780-совместимых.
Опять же, часть кода, который уже выводит текст на экран:
Скрытый текст
while (LCD_IsBusy());   // Дожидаемся, пока экран будет готов
LCD_SendByte(0x85, 1);  // Переход на 1 знакоместо 1 строки
for (t_val=0;t_val<i;t_val++) // Перебираем байты в массиве с текстом
{
	while (LCD_IsBusy()); // Снова пауза до готовности
	LCD_SendByte(data2[t_val], 0); // Передаём символ
}; // Цикл

(Опечатался)
Извините, когда вы делаете «LCD_PORT &= ~LCD_DATA_MASK;»
Получается что вы в младший полубайт PORTB отправляете единицы, тогда как у вас на них, я так понимаю, управляющие пины сидят (RS, RW, E). И только потом шлёте полубайт данных.

Это так и надо по стандарту делать? Или я что-то не догнал по неопытности?
У меня весь порт является шиной данных и управления (одновременно) для дисплея.
Константа "LCD_DATA_MASK" — это те биты, что отвечают за собственно данные, а потому в начале, для некоей экономии тактов контроллера, часть порта обнуляется и потом туда же заводится новый ниббл данных.

#define LCD_DATA_MASK   0xF0
//7------0
//1111xxxx - Биты шины данных от старшего к младшему)
//xxxx111x - Биты управления E, RW, RS</source>
0-й бит пуст.
Разберу по порядку инструкции:
LCD_PORT &= ~LCD_DATA_MASK;
LCD_PORT - он же "#define LCD_PORT  PORTB" превращается в PORTB
Конструкция вида &= сокращение языка. Подразумевает A = A & B
Символ "~" - побитовая инверсия
LCD_DATA_MASK - тоже константа.
Теперь получаем:
PORTB = PORTB & (~0xF0 = 0x0F)
PORTB = PORTB & 0x0F
PORTB = 0000xxxx
Где xxxx - старое значение пинов.
То есть, обнуляется только верхний ниббл (полубайт).
Спасибо вам большое, со всем разобрался!

Единственное что не смог понять — что это у вас за регистр DDRB?
DDRB — Сокращение от DataDirectionRegisterB — РегистрНаправленияДанныхБ. Иными словами, он контроллирует, какие пины порта будут выходными, а какие — входными.
Я бы рекомендовал обратиться к… хотя бы, к русскому переводу мануала на ATMega контроллер. По поводу отличия именно контроллера можете не беспокоиться — общие принципы остаются. Ядро то же самое. Кристаллы отличаются в основном начинкой и количеством памяти.
слишком много восклицательных знаков.
на R1 напряжение надо подавать через резистор. иначе неверное движение отвёрткой — и контроллер кончился.
для чего оптопара? нет гальванической развязки же.
да, и чего кроме такого ключа управления клапаном сомнительной схемотехники, автор хотел донести аудитории? фамилию при включении?
Ужас, вы в электронике вообще понимаете что нибудь?.. Куча глупых вопросов на которые даже отвечать не хочется!
Удачи!!!
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.