Разработка фена для пайки на Arduino

Аватара
Автор темы
Дим M
Администратор
Администратор
Сообщения: 1123
Репутация: 70
С нами: 5 лет 1 месяц

Разработка фена для пайки на Arduino

Сообщение #1 Дим » 15 февраля 2018, 20:58


В данной теме не скоро будет готовый вариант фена для пайки. Это скорее моя записная книжка - черновик, так сказать мысли вслух. В дальнейшем после окончания всех работ, будет выложена ссылка на готовый проект.

Небольшое вступление - что меня с подвигло к данным действиям. В очередной раз выпаивая микросхемку - понял что мне нужен паяльный фен. Посмотрев у китайцев цены - долго не решался приобрести его. Но как то попалась на глаза ручка паяльного фена - решил сделать станцию сам. Благо в инете всевозможных проектов множество, стал выбирать который бы мне подошёл. Но чем дальше я углублялся в данный процесс - тем больше я убеждался что не так то просто взять слизать чужое и сделать. То одно то другое меня не устраивало и я решился на создание своей станции. С чего начать? Вот и я задался таким вопросом, но не сам себе а на очень хорошем форуме Compcar.ru, где очень отзывчивый и терпеливый администратор Chip, без поддержки которого я бы даже и не стал заворачиваться над такой работой, а просто бы копил деньги на готовую станцию. Ну что ж предисловие закончено и в последующих сообщения данной темя, я буду последовательно выкладывать все наработки (дабы не забыть и не потерялось). В которых мне помогает Chip
i love you mxIni Mysql

! ! !


Аватара
Автор темы
Дим M
Администратор
Администратор
Сообщения: 1123
Репутация: 70
С нами: 5 лет 1 месяц

Сообщение #2 Дим » 17 февраля 2018, 18:18

Ну что же, сказано - сделано, заказал Горячий воздух desolder пайки Термовоздуходувы ручка для 858 8858d 878a 878 паяльная станция с 5 шт. сопел
фен ручка для паяльной станции.png
фен ручка для паяльной станции
фен ручка для паяльной станции.png (302.54 КБ) 475 просмотров

так написано в описании товара, на сайте интернет магазина. Но так как в Китае сейчас бурно отмечается Новый год, на скорейшее получение я не рассчитываю и буду пока делать код для будущей станции. Так же заказал GX16 разъем 16 мм 8 пинов, который будет расположен на корпусе станции, для подключения ручки к контроллеру.
GX16 разъем 16 мм 8 пинов.png
GX16 разъем 16 мм 8 пинов
GX16 разъем 16 мм 8 пинов.png (270.29 КБ) 475 просмотров

Сначала думать простое управление - вкл / выкл, MOSFET с потенциометром для регулировки оборотов турбинки и диммер с вольтметром - напряжение на нагревательный элемент.
Но показалось что это простовато, до и захотелось задействовать энкодер и LED дисплей 128x64 1.3" SPI, который заказал по не внимательности (нужен был IIC интерфейс подключения), и теперь валялся без дела.
Первым делом буду делать регулировку оборотов вентилятора по нижеследующей схеме:
регулировка оборотов вентилятора.png
регулировка оборотов вентилятора
регулировка оборотов вентилятора.png (214.62 КБ) 475 просмотров

И залив вот такой скетч, любуемся результатом

Код: Выделить всё

#include <Encoder.h>

#define PIN_ENCODER_CLK 8
#define PIN_ENCODER_DT 9
#define PIN_ENCODER_SW 10
Encoder myEnc(PIN_ENCODER_DT, PIN_ENCODER_CLK);

int motorPin = 11;
int motorSpeed = 75;                   // Изначальная скорость двигателя
int accel = 1;
int i = 0;
long oldPosition = 0;

void setup() {
Serial.begin(9600);
pinMode(motorPin, OUTPUT);
}
void loop(){
  analogWrite(motorPin, motorSpeed);  // Устанавливаем первоначальную скорость
//=== ручка энкодера/регулироака
  long newPosition = myEnc.read() / accel;    
  if 
(newPosition > oldPosition) 
  
{      
    analogWrite
(motorPin, newPosition);
    motorSpeed += 5;                  // Прибавляем скорость
    Serial.println(">>>");
    if ( motorSpeed > 255 )
    motorSpeed = 255;
  }
  else
  if 
(newPosition < oldPosition)
  {
    analogWrite(motorPin, newPosition);        
    motorSpeed 
-= 5;                  // Убавляем скорость
    Serial.println("<<<");
    if ( motorSpeed < 75 )
    motorSpeed = 75;
  } 
  if 
( newPosition != oldPosition)
  {
    i = (+ 1)%16;
    oldPosition = newPosition;
    analogWrite( motorPin, motorSpeed );
  } 

Вроде бы ни чего сложного но столкнулся с небольшой проблемой - писк вентилятора на всех оборотах кроме максимального.
phpBB [media]

Поискав информацию - нашёл что для этого нужно изменить частоту MOSFET. Нужно вставить в void setup() строчку TCCR2B = TCCR2B & 0b11111000 | 7;
Как оказалось это тоже наработка Chip Ну на сегодня это всё, далее буду делать регулировку мощности нагревателя.
i love you mxIni Mysql

Аватара
Автор темы
Дим M
Администратор
Администратор
Сообщения: 1123
Репутация: 70
С нами: 5 лет 1 месяц

Сообщение #3 Дим » 18 февраля 2018, 12:15

В схеме используется 220 вольт, будьте осторожны

Но регулировку 220 вольт на MOSFET не организовать, и тут опять мне помог Chip, дав ссылку на многоканальный Dimmer, работающий в фоновом режиме, своей разработки. Так же можно обсудить на форуме.
Схема диммера
Многоканальный Dimmer, работающий в фоновом режиме.png
Многоканальный Dimmer, работающий в фоновом режиме
Многоканальный Dimmer, работающий в фоновом режиме.png (112.16 КБ) 472 просмотра

Многоканальный Dimmer, работающий в фоновом режиме1.jpg
Многоканальный Dimmer, работающий в фоновом режиме
Многоканальный Dimmer, работающий в фоновом режиме1.jpg (33.79 КБ) 472 просмотра

Многоканальный Dimmer, работающий в фоновом режиме2.png
Многоканальный Dimmer, работающий в фоновом режиме
Многоканальный Dimmer, работающий в фоновом режиме2.png (111.85 КБ) 472 просмотра
Так как схема не очень сложная и дефицита комплектующих в магазинах не наблюдается, решил собрать его сам. На удивление получилось - и даже работает.
Диммер 220 вольт управляемый Ардуино.JPG
Диммер 220 вольт управляемый Ардуино
Диммер 220 вольт управляемый Ардуино.JPG (137.96 КБ) 472 просмотра

Так как у меня на выходе не будет индуктивной нагрузки, конденсатор и резистор на 36 Om, из схемы я исключил.
Диммер 220 вольт управляемый Ардуино1.png
Диммер 220 вольт управляемый Ардуино
Диммер 220 вольт управляемый Ардуино1.png (88.04 КБ) 472 просмотра

Подключаем по вышеприведенной схеме, устанавливаем библиотеку CyberLib - заливаем нижеследующий скетч и любуемся результатом.
Скетч

Код: Выделить всё

#include <Encoder.h>
#include <CyberLib.h> //Библиотека от Cyber-Place.ru
volatile unsigned long Dimmer; 

#define PIN_ENCODER_CLK 12
#define PIN_ENCODER_DT 11
#define PIN_ENCODER_SW 10
Encoder myEnc(PIN_ENCODER_DT, PIN_ENCODER_CLK);


int accel = 1;
int i = 0;
long oldPosition = 0;

void setup() {
  D4_Out;  //Настраиваем порты на выход
  D4_Low;  //установить на выходах низкий уровень сигнала
  D2_In; //настраиваем порт на вход для отслеживания прохождения сигнала через ноль
  
  attachInterrupt
(0, detect_up, RISING);  // настроить срабатывание прерывания interrupt0 на pin 2 на низкий уровень
 Dimmer = 4500;
}
//********************обработчики прерываний*******************************

void  detect_up()  // обработка внешнего прерывания. Сработает по переднему фронту
{
  delay_us(Dimmer);
  D4_High;
  delay_us(40); //формируем импульс включения симистора
  D4_Low;
}

//*************************************************************************
void loop(){

//=== ручка энкодера/регулироака
  long newPosition = myEnc.read() / accel;    
  if 
(newPosition > oldPosition) 
  
{      
    Dimmer 
-= 100;
    if ( Dimmer < 500 )
    Dimmer = 500;
  }
  else
  if 
(newPosition < oldPosition)
  {        
    Dimmer 
+= 100;                
    if 
( Dimmer > 9500 )
    Dimmer = 9500;
  } 
  if 
( newPosition != oldPosition)
  {
    i = (+ 1)%16;
    oldPosition = newPosition;
    Dimmer = Dimmer;
  } 

phpBB [media]


Ну вот теперь у меня есть и диммер управляемый микроконтроллером, а именно - Ардуино. Далее буду объединять с регулятором оборотов турбины, в одну схему.
i love you mxIni Mysql

Аватара
Автор темы
Дим M
Администратор
Администратор
Сообщения: 1123
Репутация: 70
С нами: 5 лет 1 месяц

Сообщение #4 Дим » 19 февраля 2018, 18:55

При "скрещивании" вентилятора с лампочкой выявились подводные камни, а именно - при уменьшении мощности лампочки, она начала периодически вспыхивать. А вентилятор регулировался нормально.
Видео вспышек
phpBB [media]
Как вследствие оказалось, что я использовал не тот код для регулировки напряжения. Благо на путь истинный меня опять де наставил Chip. Хотя в начале я не мог разобраться что к чему, но потом наткнулся на скетчь, по подобии которого я и соорудил свой.
Пример

Код: Выделить всё

#include <CyberLib.h> //Библиотека от Cyber-Place.ru
volatile uint8_t tic, Dimmer1, Dimmer2, Dimmer3, Dimmer4;
uint8_t data;

void setup()
{
D4_Out; D5_Out; D6_Out; D7_Out; //Настраиваем порты на выход
D4_Low; D5_Low; D6_Low; D7_Low; //установить на выходах низкий уровень сигнала
D2_In; //настраиваем порт на вход для отслеживания прохождения сигнала через ноль

//CHANGE – прерывание вызывается при любом изменении значения на входе;
//RISING – вызов прерывания при изменении уровня напряжения с низкого (Low) на высокий(HIGH)
//FALLING – вызов прерывания при изменении уровня напряжения с высокого (HIGH) на низкий (Low)
attachInterrupt(0, detect_up, LOW); // настроить срабатывание прерывания interrupt0 на pin 2 на низкий уровень
StartTimer1(halfcycle, 40); //время для одного разряда ШИМ
StopTimer1(); //остановить таймер
UART_Init(115200); //инициализация порта
}
//********************обработчик и прерываний******************** ***********
void halfcycle() //прерывания таймера
{
tic++; //счетчик
if(Dimmer1 < tic ) D4_High; //управляем выходом
if(Dimmer2 < tic ) D5_High; //управляем выходом
if(Dimmer3 < tic ) D6_High; //управляем выходом
if(Dimmer4 < tic ) D7_High; //управляем выходом
}

void detect_up() // обработка внешнего прерывания. Сработает по переднему фронту
{
tic=0; //обнулить счетчик
ResumeTimer1(); //запустить таймер
attachInterrupt(0, detect_down, HIGH); //перепрограммировать прерывание на другой обработчик
}

void detect_down() // обработка внешнего прерывания. Сработает по заднему фронту
{
StopTimer1(); //остановить таймер
D4_Low; D5_Low; D6_Low; D7_Low; //логический ноль на выходы
tic=0; //обнулить счетчик
attachInterrupt(0, detect_up, LOW); //перепрограммировать прерывание на другой обработчик
}
//**************************************** *********************************
void loop()
{
Start
Dimmer1
=random(155, 175);
delay(random(10, 300));
Dimmer2=random(155, 175);
delay(random(10, 300));
Dimmer3=random(155, 175);
delay(random(10, 300));
Dimmer4=random(155, 175);
delay(random(10, 300));
End
Мой код

Код: Выделить всё

#include <CyberLib.h> //Библиотека от Cyber-Place.ru
#include <Encoder.h>
#define PIN_ENCODER_CLK 5
#define PIN_ENCODER_DT 6
#define PIN_ENCODER_SW 7
Encoder myEnc(PIN_ENCODER_DT, PIN_ENCODER_CLK);
int motorPin = 3;
int motorSpeed = 75;                   // Изначальная скорость двигателя
int fanPower = 155;                    // Изначальная мощность фена
int selectMode = 0;                    // Что изменять, скорость или мощность фена
int accel = 1;
int i = 0;
long oldPosition = 0;
volatile uint8_t tic, Dimmer1;
// =================================== Кнопка энкодера   =====================
bool     button_state      = false;
bool     button_auto_state = false;
uint32_t ms_button         = 0;
uint32_t ms_auto_click     = 0;
// =================================== Кнопка энкодера   =====================
void setup()
{
  //Serial.begin( 9600 );
  TCCR2B = TCCR2B & 0b11111000 | 7;
  pinMode(motorPin, OUTPUT);
  D4_Out;  //Настраиваем порты на выход
  D4_Low;  //установить на выходах низкий уровень сигнала
  D2_In; //настраиваем порт на вход для отслеживания прохождения сигнала через ноль
  pinMode(PIN_ENCODER_SW, INPUT_PULLUP); // =================================== Кнопка энкодера
  attachInterrupt(0, detect_up, LOW); // настроить срабатывание прерывания interrupt0 на pin 2 на низкий уровень
  StartTimer1(halfcycle, 40); //время для одного разряда ШИМ
  StopTimer1(); //остановить таймер
}
//********************обработчик и прерываний******************** ***********
void halfcycle() //прерывания таймера
{
  tic++; //счетчик
  if(Dimmer1 < tic ) D4_High; //управляем выходом
}

void detect_up() // обработка внешнего прерывания. Сработает по переднему фронту
{
  tic=0; //обнулить счетчик
  ResumeTimer1(); //запустить таймер
  attachInterrupt(0, detect_down, HIGH); //перепрограммировать прерывание на другой обработчик
}

void detect_down() // обработка внешнего прерывания. Сработает по заднему фронту
{
  StopTimer1(); //остановить таймер
  D4_Low; //логический ноль на выходы
  tic=0; //обнулить счетчик
  attachInterrupt(0, detect_up, LOW); //перепрограммировать прерывание на другой обработчик
}
//**************************************** *********************************
void loop()
{
// =================================== Кнопка энкодера   =====================
  uint32_t ms    = millis();
  bool pin_state = digitalRead(PIN_ENCODER_SW); 
  if
( pin_state  == LOW && !button_state && ( ms - ms_button ) > 50 )// Фиксируем нажатие кнопки  
  {
    button_state      = true;
    button_auto_state = false;  
    ms_button         
= ms;
    if(selectMode == 0)
    {
      selectMode = 1;  
//      Serial.println("Press key");
    }
    else
    
{
      selectMode = 0;
    }
  }
  if( pin_state  == LOW && ( ms - ms_button ) > 2000 && ( ms - ms_auto_click )>500 ) // После 2000 мс нажатия кнопки каждые 500 мс фиксируем событие нажатия  
  {
    button_auto_state = true;
    ms_auto_click     = ms;
//    Serial.println("Auto press key");    
  }  
  if
( pin_state == HIGH && button_state && ( ms - ms_button ) > 50  ) // Фиксируем отпускание кнопки 
  {
    button_state      = false;   
    ms_button         
= ms;
    if( !button_auto_state )
    Serial.println("No Press key");
  }
// =================================== Кнопка энкодера   =====================   
  analogWrite(motorPin, motorSpeed);  // Устанавливаем первоначальную скорость
//=== ручка энкодера/регулироака
  long newPosition = myEnc.read() / accel;    
  if 
(newPosition > oldPosition) 
  
{ 
    if 
(selectMode == 0)  
    
{  
      motorSpeed 
+= 5;                  // Прибавляем скорость
      if ( motorSpeed > 255 )
      motorSpeed = 255;
    }
    else
    
{
      fanPower -= 5;                   // Прибавляем мощность фена
      if ( fanPower < 0)
      fanPower = 0;
    }
  }
  else
  if 
(newPosition < oldPosition)
  {
    if (selectMode == 0)  
    
{       
      motorSpeed 
-= 5;                  // Убавляем скорость
      if ( motorSpeed < 75 )
      motorSpeed = 75;
    }
    else
    
{
      fanPower += 5;                   // Убавляем мощность фена
      if ( fanPower > 255)
      fanPower = 255;
    }
  } 
  if 
( newPosition != oldPosition)
  {
    i = (+ 1)%16;
    oldPosition = newPosition;
    analogWrite( motorPin, motorSpeed );
    Dimmer1= fanPower;
//    Serial.println(motorSpeed);
  } 
Схема подключения
Регулировка паяльного фена.jpg
Регулировка паяльного фена
Регулировка паяльного фена.jpg (196.29 КБ) 452 просмотра
Теперь всё работает почти хорошо, есть небольшие недоработки, но они не критичны. При вращении ручки энкодера, регулируется скорость вращения вентилятора. Если нажать на шток энкодера, переходим в режим регулировки мощности нагрева. При следующем нажатии - опять вентилятор, и так циклично. В общем то и всё - уже можно подключать фен и работать. Но нужно сделать отключении нагревателя при простое. Но этим я займусь позже, так как не знаю принцип работы, встроенного в ручку фена, геркона и термопары. А пока займусь визуализацией станции, а именно буду думать как пристроить экран.
i love you mxIni Mysql

Аватара
Автор темы
Дим M
Администратор
Администратор
Сообщения: 1123
Репутация: 70
С нами: 5 лет 1 месяц

Сообщение #5 Дим » 26 февраля 2018, 16:56

Начав работать с библиотекой u8glib, для дисплея, обнаружил следующую проблему. Энкодер не захотел корректно работать, при повороте ручки показания в основном не хотели убавляться. Иногда убавлялись но всё равно это было хаотично. Тогда решил попробовать оставшуюся, рабочую библиотеку HCuOLED. С ней всё заработало отлично. Вот некоторые примеры что я соорудил.
Картинки
дисплей для паяльного фена.jpg
дисплей для паяльного фена
дисплей для паяльного фена.jpg (45.85 КБ) 435 просмотров
дисплей для паяльного фена 5.jpg
дисплей для паяльного фена
дисплей для паяльного фена 5.jpg (45.88 КБ) 435 просмотров
дисплей для паяльного фена 1.jpg
дисплей для паяльного фена
дисплей для паяльного фена 1.jpg (46.55 КБ) 435 просмотров
дисплей для паяльного фена 2.jpg
дисплей для паяльного фена
дисплей для паяльного фена 2.jpg (42.81 КБ) 435 просмотров
дисплей для паяльного фена 3.jpg
дисплей для паяльного фена
дисплей для паяльного фена 3.jpg (43.72 КБ) 435 просмотров
дисплей для паяльного фена 4.jpg
дисплей для паяльного фена
дисплей для паяльного фена 4.jpg (45.43 КБ) 435 просмотров
Код

Код: Выделить всё

#include "HCuOLED.h"
#include <Encoder.h>

const PROGMEM byte Termometr[] ={
0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x02, 0xA9, 0xFF, 0x02, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x80, 0x40, 0x7F, 0x80, 0xFE, 0xFF, 0x80, 0x7F, 0x40, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1F, 0x20, 0x4E, 0x5F, 0x9F, 0xBF, 0xBF, 0x9F, 0x5F, 0x4E, 0x20, 0x1F, 0x00, 0x00
};
const PROGMEM byte Cooler[] ={
0xFF, 0x05, 0xC7, 0xE1, 0xC1, 0xC1, 0x81, 0xFD, 0x79, 0x81, 0xC1, 0xC1, 0xE1, 0xC7, 0x05, 0xFF,
0xFF, 0xA0, 0xE0, 0x80, 0xB9, 0xBD, 0x9E, 0x84, 0x84, 0x9E, 0xBD, 0xB9, 0x80, 0xE0, 0xA0, 0xFF
};

#define PIN_ENCODER_CLK 6
#define PIN_ENCODER_DT 7
#define PIN_ENCODER_SW 5
#define CS_DI 8
#define DC_DI 9
#define RST_DI 10

HCuOLED HCuOLED(SH1106, CS_DI, DC_DI, RST_DI); // Для дисплеев SH1106 (HCMODU0058 & HCMODU0059)
Encoder myEnc(PIN_ENCODER_DT, PIN_ENCODER_CLK);

int motorSpeed = 75;                   // Изначальная скорость двигателя
int accel = 1;
int i = 0;
long oldPosition = 0;

void setup() 
{
  HCuOLED.Reset(); // Сбросить отображение
// ============================== Не изменяемые символы ======================== 
// ========= Знак термометра =================
  HCuOLED.Cursor(5,5);
  HCuOLED.Bitmap(16, 3, Termometr);
// ========= Знак "*" - вентилятор   =================
  HCuOLED.Cursor(6,41);
  HCuOLED.Bitmap(16, 2, Cooler);
// ========= SET темп   =================
  HCuOLED.SetFont(Terminal_8pt);
  HCuOLED.Cursor(94,4);
  HCuOLED.Print("SET");
// ========= SET вентил   =================
  HCuOLED.Cursor(94,37);
  HCuOLED.Print("SET");
// ========= Рамка, линии   =================
  HCuOLED.Rect(0,0,127,63, OUTLINE); // Рамка вокруг экрана
  HCuOLED.Line(85, 0, 85, 63);  // Вертикальная линия
  HCuOLED.Line(0, 32, 127, 32); // Горизонтальная линия
//  HCuOLED.Line(85, 32, 127, 32); // Горизонтальная короткая линия
}

void loop() 
{
//=== ручка энкодера/регулироака
  long newPosition = myEnc.read() / accel;    
  if 
(newPosition > oldPosition) 
  
{      
    motorSpeed 
+= 5;                  // Прибавляем скорость 
    if ( motorSpeed > 255 )
    motorSpeed = 255;
  }
  else
  if 
(newPosition < oldPosition)
  {    
    motorSpeed 
-= 5;                  // Убавляем скорость
    if ( motorSpeed < 75 )
    motorSpeed = 75;
  } 
  if 
( newPosition != oldPosition)
  {
    i = (+ 1)%16;
    oldPosition = newPosition;
  } 
    HCuOLED
.SetFont(LCDLarge_24pt);
    HCuOLED.Erase(30,3,70,29);  // Очистить область, в которой будет отображаться температура
    HCuOLED.Cursor(30,3); // Установите текстовый курсор в это место
    HCuOLED.Print(motorSpeed);  // Запишите переменную в буфер отображения
   // HCuOLED.Refresh();  // Вывод буфера отображения на экран
    
    HCuOLED
.SetFont(LCDLarge_24pt);
    HCuOLED.Erase(30,35,70,59);  // Очистить область, в которой будет отображаться скорость вентилятора
    HCuOLED.Cursor(30,35); // Установите текстовый курсор в это место
    HCuOLED.Print(motorSpeed);  // Запишите переменную в буфер отображения
   // HCuOLED.Refresh();  // Вывод буфера отображения на экран
    
    HCuOLED
.SetFont(MedProp_11pt);
    HCuOLED.Erase(94,15,120,30);  // Очистить область, в которой будет отображаться SET температура
    HCuOLED.Cursor(94,15); // Установите текстовый курсор в это место
    HCuOLED.Print(motorSpeed);  // Запишите переменную в буфер отображения
   // HCuOLED.Refresh();  // Вывод буфера отображения на экран 

    HCuOLED.SetFont(MedProp_11pt);
    HCuOLED.Erase(94,47,120,60);  // Очистить область, в которой будет отображаться SET скорость вентилятора
    HCuOLED.Cursor(94,47); // Установите текстовый курсор в это место
    HCuOLED.Print(motorSpeed);  // Запишите переменную в буфер отображения
    HCuOLED.Refresh();  // Вывод буфера отображения на экран  
}
Теперь попробую без рамки вокруг экрана и маленько растянуть местоположение показаний фена.
i love you mxIni Mysql

Аватара
Автор темы
Дим M
Администратор
Администратор
Сообщения: 1123
Репутация: 70
С нами: 5 лет 1 месяц

Сообщение #6 Дим » 27 февраля 2018, 19:39

Убрал рамку и растянул местоположения показаний фена. Есть ещё задумки - добавить часы и выделять фон регулируемых настроек.
растянул местоположения показаний фена.jpg
растянул местоположения показаний фена
растянул местоположения показаний фена.jpg (58.84 КБ) 429 просмотров

Код

Код: Выделить всё

#include "HCuOLED.h"
#include <Encoder.h>

const PROGMEM byte Termometr[] ={
0x000x000x000x000x000xFC0x020xA90xFF0x020xFC0x000x000x000x000x00,
0x000x000x000x800x400x7F0x800xFE0xFF0x800x7F0x400x800x000x000x00,
0x000x000x1F0x200x4E0x5F0x9F0xBF0xBF0x9F0x5F0x4E0x200x1F0x000x00
};
const 
PROGMEM byte Cooler[] ={
0xFF0x050xC70xE10xC10xC10x810xFD0x790x810xC10xC10xE10xC70x050xFF,
0xFF0xA00xE00x800xB90xBD0x9E0x840x840x9E0xBD0xB90x800xE00xA00xFF
};

#define PIN_ENCODER_CLK 6
#define PIN_ENCODER_DT 7
#define PIN_ENCODER_SW 5
#define CS_DI 8
#define DC_DI 9
#define RST_DI 10

HCuOLED HCuOLED(SH1106CS_DIDC_DIRST_DI); // Для дисплеев SH1106 (HCMODU0058 & HCMODU0059)
Encoder myEnc(PIN_ENCODER_DTPIN_ENCODER_CLK);

int motorSpeed 75;                   // Изначальная скорость двигателя
int accel 1;
int i 0;
long oldPosition 0;

void setup() 
{
  
HCuOLED.Reset(); // Сбросить отображение
// ============================== Не изменяемые символы ======================== 
// ========= Знак термометра =================
  
HCuOLED.Cursor(0,1);
  
HCuOLED.Bitmap(163Termometr);
// ========= Знак "*" - вентилятор   =================
  
HCuOLED.Cursor(0,46);
  
HCuOLED.Bitmap(162Cooler);
// ========= SET темп   =================
  
HCuOLED.SetFont(Terminal_8pt);
  
HCuOLED.Cursor(94,2);
  
HCuOLED.Print("SET");
// ========= SET вентил   =================
  
HCuOLED.Cursor(94,41);
  
HCuOLED.Print("SET");
// ========= Рамка, линии   =================
//  HCuOLED.Rect(0,0,127,63, OUTLINE); // Рамка вокруг экрана
  
HCuOLED.Line(7007064);  // Вертикальная линия
//  HCuOLED.Line(0, 32, 128, 32); // Горизонтальная линия
  
HCuOLED.Line(703212732); // Горизонтальная короткая линия
}

void loop() 
{
//=== ручка энкодера/регулироака
  
long newPosition myEnc.read() / accel;    
  if (
newPosition oldPosition
  {      
    
motorSpeed += 5;                  // Прибавляем скорость 
    
if ( motorSpeed 255 )
    
motorSpeed 255;
  }
  else
  if (
newPosition oldPosition)
  {    
    
motorSpeed -= 5;                  // Убавляем скорость
    
if ( motorSpeed 75 )
    
motorSpeed 75;
  } 
  if ( 
newPosition != oldPosition)
  {
    
= (1)%16;
    
oldPosition newPosition;
  } 
    
HCuOLED.SetFont(LCDLarge_24pt);
    
HCuOLED.Erase(22,0,69,29);  // Очистить область, в которой будет отображаться температура
    
HCuOLED.Cursor(22,0); // Установите текстовый курсор в это место
    
HCuOLED.Print(motorSpeed);  // Запишите переменную в буфер отображения
   // HCuOLED.Refresh();  // Вывод буфера отображения на экран
    
    
HCuOLED.SetFont(LCDLarge_24pt);
    
HCuOLED.Erase(22,40,69,64);  // Очистить область, в которой будет отображаться скорость вентилятора
    
HCuOLED.Cursor(22,40); // Установите текстовый курсор в это место
    
HCuOLED.Print(motorSpeed);  // Запишите переменную в буфер отображения
   // HCuOLED.Refresh();  // Вывод буфера отображения на экран
    
    
HCuOLED.SetFont(MedProp_11pt);
    
HCuOLED.Erase(94,13,120,30);  // Очистить область, в которой будет отображаться SET температура
    
HCuOLED.Cursor(94,13); // Установите текстовый курсор в это место
    
HCuOLED.Print(motorSpeed);  // Запишите переменную в буфер отображения
   // HCuOLED.Refresh();  // Вывод буфера отображения на экран 

    
HCuOLED.SetFont(MedProp_11pt);
    
HCuOLED.Erase(94,52,120,64);  // Очистить область, в которой будет отображаться SET скорость вентилятора
    
HCuOLED.Cursor(94,52); // Установите текстовый курсор в это место
    
HCuOLED.Print(motorSpeed);  // Запишите переменную в буфер отображения
    
HCuOLED.Refresh();  // Вывод буфера отображения на экран  
i love you mxIni Mysql

Аватара
Автор темы
Дим M
Администратор
Администратор
Сообщения: 1123
Репутация: 70
С нами: 5 лет 1 месяц

Сообщение #7 Дим » 28 февраля 2018, 11:14

Что то мне опять не понравилось как работает энкодер, и стал искать другие варианты кода. Нашёл почти такой же как и был у меня, и решил попробовать его вновь с u8glib библиотекой. Но результат оказался прежним
Дим писал(а):Начав работать с библиотекой u8glib,для дисплея, обнаружил следующую проблему. Энкодер не захотел корректно работать, при повороте ручки показания в основном не хотели убавляться. Иногда убавлялись но всё равно это было хаотично.

Немного помучившись, в голову пришла мысль - поменять выходы на энкодере. Были 6 и 7, сделал 3 и 7

Код: Выделить всё

#define pin_CLK 3 // Энкодер пин A
#define pin_DT  7 // Энкодер пин B   

И всё стало работать нормально. Так что теперь опять перехожу на работу с библиотекой u8glib, так как она мне больше понравилась, чем HCuOLED. Благо время у меня предостаточно, ручку фена только вчера отправили и будет идти 30 - 60 дней.
i love you mxIni Mysql

Аватара
Автор темы
Дим M
Администратор
Администратор
Сообщения: 1123
Репутация: 70
С нами: 5 лет 1 месяц

Сообщение #8 Дим » 28 февраля 2018, 20:55

Решил проверить как будет работать с вентилятором. Огорчило - начались очередные глюки. В конце концов решил попробовать подключить дисплей к аналоговым выходам. Как ни странно - получилось.

Код: Выделить всё

U8GLIB_SSD1306_128X64 u8g(A4, A3, A0, A1, A2); // наш дисплей  ||  

Регулировка и показания стали работать корректно, очень редко скакали цифры, но это я списал на плохой контакт проводов с макеткой. Но вдруг опять началась котовасия - скачки показаний и оборотов двигателя вентилятора. Всевозможные изменения выходов, результатов не дали. И тут мне на глаза попала ручка для вала энкодера. Установив её всё встало на свои места. Видимо как то влияло что я вращал ручку "голыми руками". Надеюсь мои мучения окончились, и буду пробовать подключать диммер и "рисовать" дизайн дисплея. Оставлю здесь код, дабы не затерялся.
КОД

Код: Выделить всё

#include <Encoder.h>
#include "U8glib.h"

#define PIN_ENCODER_CLK 8
#define PIN_ENCODER_DT 9
#define PIN_ENCODER_SW 10
U8GLIB_SSD1306_128X64 u8g(A4, A3, A0, A1, A2); // наш дисплей  ||
Encoder myEnc(PIN_ENCODER_DT, PIN_ENCODER_CLK);


int motorPin = 11;
int motorSpeed = 75;                   // Изначальная скорость двигателя
int accel = 1;
int i = 0;

long oldPosition = 0;

void draw(void) {
  u8g.setFont(u8g_font_fub25);
  u8g.setPrintPos(0, 30);
  u8g.print(motorSpeed);
}

void setup() {
  TCCR2B = TCCR2B & 0b11111000 | 7;
Serial.begin(9600);
pinMode(motorPin, OUTPUT);
}
void loop(){
  analogWrite(motorPin, motorSpeed);  // Устанавливаем первоначальную скорость
//=== ручка энкодера/регулироака
  long newPosition = myEnc.read() >> 1;
 // long newPosition = myEnc.read() / accel;    
  if (newPosition > oldPosition) 
  
{      
  
//  analogWrite(motorPin, newPosition);
    motorSpeed += 5;                  // Прибавляем скорость
    if ( motorSpeed > 255 )
    motorSpeed = 255;
  }
  else
  if 
(newPosition < oldPosition)
  {
 //   analogWrite(motorPin, newPosition);        
    motorSpeed -= 5;                  // Убавляем скорость
    if ( motorSpeed < 75 )
    motorSpeed = 75;
  } 
  if 
( newPosition != oldPosition)
  {
    i = (+ 1)%16;
    oldPosition = newPosition;
    analogWrite( motorPin, motorSpeed );
  } 

  u8g
.firstPage();  
  do 
{
    draw();
  } while( u8g.nextPage() );
}
i love you mxIni Mysql

Аватара
Автор темы
Дим M
Администратор
Администратор
Сообщения: 1123
Репутация: 70
С нами: 5 лет 1 месяц

Сообщение #9 Дим » 2 марта 2018, 0:44

Сейчас разбираюсь с кириллицей в U8g2 библиотеке. Что то долго не хотело работать, сейчас вроде нормально отображается, но не все шрифты попробовал.

Код: Выделить всё

#include <Arduino.h>
#include <U8g2lib.h>

U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ A4, /* data=*/ A3, /* cs=*/ A0, /* dc=*/ A1, /* reset=*/ A2); 

void setup
(void) {
  u8g2.begin();
  u8g2.enableUTF8Print();    // /включить поддержку UTF8 для функции печати Arduino print()
}

void loop(void) {
  u8g2.setFont(u8g2_font_cu12_t_cyrillic);  
  u8g2
.firstPage();
  do {
    u8g2.setCursor(0, 40);
    u8g2.print("Привет мир");
  } while ( u8g2.nextPage() );
}
i love you mxIni Mysql

Аватара
Автор темы
Дим M
Администратор
Администратор
Сообщения: 1123
Репутация: 70
С нами: 5 лет 1 месяц

Сообщение #10 Дим » 2 марта 2018, 20:32

Так как U8g2lib плохо работает с кириллицей, пока попробую ещё раз с u8glib библиотекой. Код U8g2lib, оставлю тут.
Код

Код: Выделить всё

#include <CyberLib.h> //Библиотека от Cyber-Place.ru
#include <U8g2lib.h>
#include <Encoder.h>
#define PIN_ENCODER_CLK 8
#define PIN_ENCODER_DT 9
#define PIN_ENCODER_SW 7
Encoder myEnc(PIN_ENCODER_DT, PIN_ENCODER_CLK);
U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ A4, /* data=*/ A3, /* cs=*/ A0, /* dc=*/ A1, /* reset=*/ A2); 

int motorPin 
= 3;
int motorSpeed = 75;                   // Изначальная скорость двигателя
int fanPower = 155;                    // Изначальная мощность фена
int selectMode = 0;
int accel = 1;
int i = 0;
volatile uint8_t tic, Dimmer1;
long oldPosition = 0;
char ch_ar[5];

void setup(void) {
  u8g2.begin();
  TCCR2B = TCCR2B & 0b11111000 | 7;
  pinMode(motorPin, OUTPUT);
  D4_Out;  //Настраиваем порты на выход
  D4_Low;  //установить на выходах низкий уровень сигнала
  D2_In; //настраиваем порт на вход для отслеживания прохождения сигнала через ноль
  attachInterrupt(0, detect_up, LOW); // настроить срабатывание прерывания interrupt0 на pin 2 на низкий уровень
  StartTimer1(halfcycle, 40); //время для одного разряда ШИМ
  StopTimer1(); //остановить таймер
}
//********************обработчик и прерываний******************** ***********
void halfcycle() //прерывания таймера
{
  tic++; //счетчик
  if(Dimmer1 < tic ) D4_High; //управляем выходом
}

void detect_up() // обработка внешнего прерывания. Сработает по переднему фронту
{
  tic=0; //обнулить счетчик
  ResumeTimer1(); //запустить таймер
  attachInterrupt(0, detect_down, HIGH); //перепрограммировать прерывание на другой обработчик
}

void detect_down() // обработка внешнего прерывания. Сработает по заднему фронту
{
  StopTimer1(); //остановить таймер
  D4_Low; //логический ноль на выходы
  tic=0; //обнулить счетчик
  attachInterrupt(0, detect_up, LOW); //перепрограммировать прерывание на другой обработчик
}
//**************************************** *********************************
void loop(void) {
// =================================== Кнопка энкодера   =====================   
  analogWrite(motorPin, motorSpeed);  // Устанавливаем первоначальную скорость
//=== ручка энкодера/регулироака
  long newPosition = myEnc.read() / accel;    
  if 
(newPosition > oldPosition) 
  
{ 
    if 
(selectMode == 0)  
    
{  
      motorSpeed 
+= 5;                  // Прибавляем скорость
      if ( motorSpeed > 255 )
      motorSpeed = 255;
    }
    else
    
{
      fanPower -= 5;                   // Прибавляем мощность фена
      if ( fanPower < 0)
      fanPower = 0;
    }
  }
  else
  if 
(newPosition < oldPosition)
  {
    if (selectMode == 0)  
    
{       
      motorSpeed 
-= 5;                  // Убавляем скорость
      if ( motorSpeed < 75 )
      motorSpeed = 75;
    }
    else
    
{
      fanPower += 5;                   // Убавляем мощность фена
      if ( fanPower > 255)
      fanPower = 255;
    }
  } 
  if 
( newPosition != oldPosition)
  {
    i = (+ 1)%16;
    oldPosition = newPosition;
    analogWrite( motorPin, motorSpeed );
    Dimmer1= fanPower;
//    Serial.println(motorSpeed);
  } 
  
// Данные фена на дисплей-------------------------------------------------------------------------------------------------------------------------
  u8g2.clearBuffer();          // очистить внутреннюю память
    // рисуем линии и пишем 2 строки---------------
//  u8g2.drawFrame(2,1,126,63);// Рамка вокруг экрана
  u8g2.drawLine(76, 1, 76, 64);//вертикальная по середине
//  u8g2.drawLine(1, 40, 76, 40);//горизонтальная в левой части
  u8g2.drawLine(76, 32, 128, 32);
 // u8g2.setFont(u8g2_font_ncenR12_tf);
     u8g2.setFont(u8g2_font_cu12_tr);
  u8g2.drawStr(82,13,"temp");  // установленная температура
  u8g2.drawStr(82,46,"fan");  // установленные обороты
 // u8g2.setFont(u8g2_font_helvR24_tf); // выберите подходящий шрифт tf
  u8g2.setFont(u8g2_font_fur25_tf); // выберите подходящий шрифт
  sprintf(ch_ar, "%d°", motorSpeed);
  u8g2.drawStr(5,29,ch_ar); //установленная температура фена 
  u8g2.sendBuffer();          // переносить внутреннюю память на дисплей
}
i love you mxIni Mysql


  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Прочая электроника»