Jump to content

Ушик

Members
  • Content Count

    30
  • Joined

  • Last visited

Community Reputation

1 Обычный

About Ушик

  • Rank
    Новенький

Электроника

  • Стаж в электронике
    Не связан с электроникой

Recent Profile Visitors

270 profile views
  1. Это потрясающе А какова (примерно) масса деревянных коромысел? Сколько граммов тащит этот агрегат? И еще, если позволите: что за Дедовская пыхтелка? Можно ли где-то ознакомиться с этим интересным девайсом? Спасибо.
  2. После многих бессонных дней оно таки заработало. Температура с Вашей, Yuriy.pv, подсказкой давно уже пофикшена, а вот двигатель лентопротяжки - буквально пол часа как заработал нормально. Условно нормально, т.к. 30 минут надругательств - это не тест. Что сделано: 1. Перетащил на библиотеку GyverStepper. В целом это без разницы, просто я пошел не самым логичным путем 2. Забросил проект на пару дней. 3. Перетащил с места на место строчки кода в процедуре loop (). 4. Причесал код, убрал закомментированные куски. 5. Выбросил все старые файлы из папки с проектом и перекомпилил заново в стопицотый раз. Что именно дало толчок к работе - не знаю. Но случилось чудо и картинка поплыла, как Солнце среди звезд, как жирный конь в компоте, как главком на красной площади, как деньги из бюджета - продолжать можно долго Еще раз спасибо за внимание, за помощь и поддержку. Вот текущий код: /* * Станок по протяжке ленты из ПЭТ бутылок в пруток. * Версия 0.1 от 03.08.2021 */ #include "Wire.h" #include "LiquidCrystal_I2C.h" #include "GyverButton.h" #include <GyverStepper.h> #define PID_INTEGER #include "GyverPID.h" #include <EEPROM.h> //----------------------------------------------------------------------------------------------------------------------- #define ver "0.1" #define btn_dec_pin 11 #define btn_ok_pin 10 #define btn_inc_pin 9 #define btn_inc_step 20 #define btn_dec_step 20 // PWM пины: 3, 5, 6, 9, 10, 11 #define heater_pin 5 // Контакт D5 #define tsens_pin 21 // Контакт A7 #define fan_pin 6 // Контакт D6 #define thermistor_r 100000 // Номинальное сопротивление термистора при 25 градусах 100К #define t_nominal 25 // Температура, при которой меряется номинальное сопротивление термистора #define thermo_b 3950 // Какой-то бетта коэффициент термистора (обычно 3000-4000). ХЗ что это #define thermo_r 11880 // Постоянный резистор второго плеча термистора, 11.88К #define num_pas 10 // Количество измерений температуры для усреднения #define temp_addr 0 // Адрес в EEPROM для хранения температуры нагревателя #define speed_addr 2 // Адрес в EEPROM для хранения скорости протяжки // ПИД регулятор #define dt 500 // Частота регулировки ПИД 0.5 секунды #define PID_kp 5.2 #define PID_ki 0.5 #define PID_kd 0.5 // Мотор протяжки #define motor_max_speed 1000 // Максимальное число шагов в секунду #define motor_steps 200 // Количество шагов мотора на оборот (для Nema17 200) #define motor_acceleration 300 #define motor_step_pin 15 // Контакт А1 #define motor_dir_pin 14 // Контакт А0 #define motor_en_pin 16 // Контакт А2 //======================================================================================================================= LiquidCrystal_I2C lcd(0x27, 16, 2); GButton btn_dec(btn_dec_pin); GButton btn_inc(btn_inc_pin); GButton btn_ok(btn_ok_pin); GyverPID regulator(0.1, 0.05, 0.01, 100); // коэф. П, коэф. И, коэф. Д, период дискретизации dt (мс) GStepper<STEPPER2WIRE> motor(motor_steps, motor_step_pin, motor_dir_pin, motor_en_pin); // драйвер step-dir + пин enable //======================================================================================================================= String menu_item [] = {"Temp ","Speed ","Motor ", "Heat ", "Fan ", "Save ", "Load "}; int menu_pos = 0; int heater_current_temp = 0; int heater_new_temp = 0; int motor_speed = 0; float error, error0, pid, pwr, integ; uint16_t Kp, Ki, Kd; bool heater_logo = false; static bool motor_enable = false; //----------------------------------------------------------------------------------------------------------------------- void Logo (void); void Btn_dec (int); void Btn_inc (int); void Btn_OK (); void Show (); void Save (); void Load (); int GetTemp (); void PID_heater (); void Motor_step (); void Ticks (); //======================================================================================================================= void Logo (void) { String logo_str = "Extruder ver.0.1"; int pos = 0; for (pos==0; pos<logo_str.length (); pos++) { lcd.setCursor (pos,0); lcd.print (logo_str[pos]); delay (100); } delay (1000); lcd.clear (); } //----------------------------------------------------------------------------------------------------------------------- void Btn_dec (int clicks){ // 0 1 2 3 4 5 6 //"Temp ","Speed ","Motor ", "Heat ", "Fan ", "Save ", "Load " // Одиночные нажатия if (clicks==1) { switch (menu_pos) { case 0: if (heater_new_temp>0) {heater_new_temp--;}; break; case 1: {motor_speed=motor_speed-5; motor.setSpeed(motor_speed);}; break; case 2: motor_enable = false; break; case 3: break; case 4: break; case 5: Save (); break; case 6: Load (); break; } }; // Долгое удержание if (clicks==2) { switch (menu_pos) { case 0: if (heater_new_temp>btn_dec_step) {heater_new_temp=heater_new_temp-btn_dec_step;}; break; case 1: {motor_speed=motor_speed-20; motor.setSpeed(motor_speed);}; break; } }; } //----------------------------------------------------------------------------------------------------------------------- void Btn_inc (int clicks){ // 0 1 2 3 4 5 6 //"Temp ","Speed ","Motor ", "Heat ", "Fan ", "Save ", "Load " // Одиночные нажатия if (clicks==1) { switch (menu_pos) { case 0: heater_new_temp++; break; case 1: if (motor_speed<motor_max_speed) {motor_speed=motor_speed+5; motor.setSpeed(motor_speed);}; break; case 2: motor_enable = true; break; case 3: break; case 4: break; case 5: Save (); break; case 6: Load (); break; } }; // Долгое удержание if (clicks==2) { switch (menu_pos) { case 0: heater_new_temp=heater_new_temp+btn_inc_step; break; case 1: {motor_speed=motor_speed+20; motor.setSpeed(motor_speed);}; break; }; }; } //----------------------------------------------------------------------------------------------------------------------- void Btn_OK (){ // 0 1 2 3 4 5 6 //"Temp ","Speed ","Motor ", "Heat ", "Fan ", "Save ", "Load " switch (menu_pos) { case 0: regulator.setpoint = heater_new_temp; break; case 1: break; case 2: break; case 3: break; case 4: break; case 5: break; case 6: break; } menu_pos++; if (menu_pos==7) {menu_pos=0;}; } //----------------------------------------------------------------------------------------------------------------------- void Show (void) { lcd.setCursor (0,0); lcd.print (menu_item[menu_pos]); lcd.setCursor (6,0); lcd.print ("T="); lcd.print (heater_new_temp); lcd.print("/"); lcd.print(heater_current_temp); lcd.print(" "); lcd.setCursor (6,1); lcd.print ("S="); lcd.print (motor_speed); lcd.print(" "); lcd.setCursor (14,1); if (heater_logo==true) {lcd.print('h');} else {lcd.print(' ');}; lcd.setCursor (13,1); if (motor_enable==true) {lcd.print('m');} else {lcd.print(' ');}; } //----------------------------------------------------------------------------------------------------------------------- void Save (void) { eeprom_update_word (temp_addr, heater_new_temp); eeprom_update_word (speed_addr, motor_speed); menu_pos = 0; } //----------------------------------------------------------------------------------------------------------------------- void Load (void) { heater_new_temp = eeprom_read_word (temp_addr); motor_speed = eeprom_read_word (speed_addr); menu_pos = 0; //Проверка на -1 (после обновления прошивки из ЕЕПРОМ читается -1) if (motor_speed==-1) motor_speed = 0; if (heater_new_temp==-1) heater_new_temp = 0; } //----------------------------------------------------------------------------------------------------------------------- int GetTemp(void) { //Функция измерения температуры int16_t At = 0; for (uint8_t i = 0; i < 10; i++) At += analogRead(tsens_pin); //Усредняем At /= 10; //10 последовательных измерений float Rt = 1023.0 / At - 1; Rt = thermo_r / Rt; float T; T = Rt / thermistor_r; T = log (T); T /= thermo_b; T += 1 / (t_nominal + 273.15); T = 1 / T; T -= 273.15; int xx; xx = T; return xx; } //----------------------------------------------------------------------------------------------------------------------- void PID_heater (void) { regulator.input = heater_current_temp; // сообщаем регулятору текущую температуру pwr = regulator.getResultTimer(); analogWrite(heater_pin, pwr); // отправляем на мосфет if (pwr>0) {heater_logo = true;} else {heater_logo = false;}; } //----------------------------------------------------------------------------------------------------------------------- void Ticks (void) { btn_dec.tick(); btn_inc.tick(); btn_ok.tick(); if (motor_enable==true) {motor.tick();}; } //----------------------------------------------------------------------------------------------------------------------- void PreSave (void) { motor_speed = 500; heater_new_temp = 50; Save (); lcd.clear (); lcd.print ("EEPROM saved"); lcd.setCursor (0,1); lcd.print ("T=50, S=500"); delay (1000); } //----------------------------------------------------------------------------------------------------------------------- void PreLoad (void) { Load (); lcd.clear (); lcd.print ("EEPROM loaded"); lcd.setCursor (0,1); lcd.print ("T="); lcd.print (heater_new_temp); lcd.print ("S=500"); lcd.print (motor_speed); delay (1000); } //----------------------------------------------------------------------------------------------------------------------- //======================================================================================================================= void setup() { // Инициализация портов { pinMode (heater_pin, OUTPUT); pinMode (fan_pin, OUTPUT); digitalWrite (heater_pin, LOW); digitalWrite (fan_pin, LOW); } // Инициализация дисплея { lcd.init(); lcd.backlight(); lcd.clear (); } Load (); // Инициализация ПИД регулятора { regulator.setDirection(NORMAL); // направление регулирования (NORMAL/REVERSE). ПО УМОЛЧАНИЮ СТОИТ NORMAL regulator.setLimits(0, 255); // пределы (ставим для 8 битного ШИМ). ПО УМОЛЧАНИЮ СТОЯТ 0 И 255 regulator.setpoint = heater_new_temp; // сообщаем регулятору температуру, которую он должен поддерживать regulator.Kp = PID_kp; regulator.Ki +=PID_ki; regulator.Kd = PID_kd; } // Инициализация двигателя протяжки { motor.invertEn(false); motor.setRunMode(KEEP_SPEED); motor.setMaxSpeed(motor_max_speed); motor.setAcceleration(motor_acceleration); motor.setSpeed(motor_speed); } // Прочее { Logo (); // Загрузка сохраненных в ЕЕПРОМ значений, если это необходимо if (digitalRead (btn_dec_pin)==0&&digitalRead (btn_inc_pin)==0) {PreSave (); Logo();}; if (digitalRead (btn_ok_pin)==0&&digitalRead (btn_inc_pin)==0) {PreLoad (); Logo();}; } } //======================================================================================================================= void loop() { heater_current_temp = GetTemp (); PID_heater (); Ticks (); Show (); if (btn_dec.isClick()) {Btn_dec(1);}; if (btn_inc.isClick()) {Btn_inc(1);}; if (btn_ok.isClick()) {Btn_OK();}; if (btn_dec.isHolded()) {Btn_dec(2);}; if (btn_inc.isHolded()) {Btn_inc(2);}; } Странно, предыдущий ответ пропал, а потом снова появился - это ваще законно? Простите, у нас тут локальная котоклизьма была, света больше суток не видели - даже пиво пили темное! Пишу иногда, по настроению. Точнее, пописываю Так, фанфики на все, что глаза видят Вы правы, станочек задумывался как вытягиватель ПЭТ-филамента для принтера, но пока делал - пришло много новых хотелок. Уж как там с филаментом пойдет я не знаю, все-таки вонюч он сверхмерно. Это я уже из экспериментов с предыдущей итерацией станка уяснил, а то в инете на сей счет мнения диаметрально разнятся. Еще хочу корзины научиться плести из этого прутка, сплести полноценный грузовой прицеп для велика, подвязки для помидоров в теплицу, розги для соседских детей, леску для триммера, гамак... Боюсь, моя печень не одобрит такой размах хотелок
  3. Юрий, Вы таки тоже правы Дунька - это как магия: она не зло и не добро, она просто есть. Вопрос в том, как ее применять Для меня платформа ардуино - это кучка железа, имеющий какое-то подобие устаканенного набора функций (зачастую несовместимого само с с собой), кучка программных поддержек (работающих только в демках), крайне убогую оболочку (порой легче в блокноте работать) и т.д. и т.п. Хаять можно долго и со вкусом - это существенно повышает моё ЧСВ Однако есть же и плюсы: оно уже есть, можно спросить совета у уже нахававшихся, можно скачай и прошей без особых трепыханий и будет тебе метеостанция... Все это сливается в понятие "порог вхождения". Впрочем. Вы и сами все это прекрасно понимаете, не будем тут холиваром развлекаться Я не хочу разбираться в начинке библиотек, не хочу оптимизировать и выцарапывать ресурсы (знаете сказку об одном байте?) и все такое. Буду по существу лучше Почему на дуньке делаю? Потому, что я не настолько крут, чтобы написать поддержку экрана, подключенного по I2C Драйвер мотора уж подцепил бы, там действительно все неприлично просто. Да и с кнопками тоже доводилось дело иметь. На резонный вопрос "ну и?" превентивно отвечу: "ну, эта..." Так-то, если уж касаться этой темы о предпочтениях в программировании, то мне больше всех нравится FlowCode - визуальная среда, строишь алгоритм программы из школьных блок-схем, а на выходе кекс, асм и си. Все бы хорошо, да вот закрытая она, эта ФК, поддержки нормального железа нет, только свои модули продвигают, а под самодельщину поддержку писать - опять же, я не хочу этим заниматься. Впрочем, я увлекся, узвините. Функция Ticks() вызывается в бесконечном цикле loop() - это аналог идеологически истинного while (1) do {}; В результате программа крутится внутри этого лупа, выскакивая ненадолго на всякие там прерывания (если они есть) и прочие функции (в том числе и наш Ticks()). Все как всегда, те же фаберже, вид сбоку. Была мысль злобно плюнуть в код и настрочить, как Вы говорите, самому это управление драйвером. И даже не вижу сложностей особоых, по крайней мере сейчас не вижу . Возможно, этим все и закончится
  4. Спасибо, что проявляете интерес к моему скромному проекту С подозрениями все хорошо - их есть у меня Но увы, кроме подозрений еще нужны веские доказательства, псакинг тут не прокатит. Вот думаю, может еще параною подключить, для надежности? При RAM=61% и FLASH=93% без паранои никак Сегодня еще не занимался проектом, не успел. Постараюсь пару часиков поковыряться. Хочу другие библиотеки еще попробовать - порой такой финт прокатывает на ардуине. Хоть и не всегда, конечно. Самое удивительное, что копипаст кода в пустой скетч двигателем крутит (и кнопками кнопит), а в нужном проекте - нет. Есть мысль переписать все нафиг с чистого листа, но сомнения гложут. А что, прошу прощения, не так с функцией Ticks()? void Ticks (void) { btn_dec.tick(); btn_inc.tick(); btn_ok.tick(); if (motor_enable==true) {motor.runSpeed();}; } Для опроса кнопок там вызываются, собственно, опросы кнопок и затем, если мотору можно крутиться (значение параметра задается вручную) - делаем один шажок. Это если я правильно понял описание функций библиотеки. Вроде бы никакого криминала в ней нет, да и на изменение скорости она не влияет. Честно говоря, не вижу, на что в ней можно грозно посмотреть. Эта переменная (motor_enable) так же используется в функции Show() - выводит символ m, если мотору можно крутиьтся. Так вот там она вполне корректно отрабатывается, так что и переменная тоже меняется. Я так думаю. Сейчас, после переезда на гайверовскую библиотеку (нравятся они мне, как-то удобненько работают, а про внутренний мир этих библиотек я не в курсе ) управления мотором функция приобрела немного иной вид: void Ticks (void) { btn_dec.tick(); btn_inc.tick(); btn_ok.tick(); if (motor_enable==true) {motor.tick();}; } В общем, пойду ковыряться, авось это поможет Потом расскажу, что получится.
  5. Действительно, с температурой теперь все в норме, нагрев управляется вовремя, произвольно и как и задумано Теперь с двигателем воюю. Проверил сто раз весь код, переполз на библиотеку GyverStepper, вытаскивал в отдельный скетч относящиеся к делу куски - там работает. И запускается, и скорость меняется, и тормозится... А в вышеприведенном скетче - авотхрен, фигвам! Точнее, вообще не запускается, хотя кусочки код копипастю из работающего окна в неработающее. Есть подозрение, что ресурсов мало осталось ( 94%/62% RAM/FLASH), но как-то так себе предположение. В общем, ищу пока решение
  6. Эээ... Ну да, действительно Вот ведь, Семен Семеныч Наверное, с двигателем тоже самое происходит Спасибо, слона-то я и не заметил
  7. Здравствуйте, уважаемые. Прошу помощи в написании прошивки станочка для протяжки ПЭТ бутылок в пруток. Точнее, не всей прошивки,а кусочка кода. Написал я кое-как программу, уж как сумел, и она даже почти работает. Вот это "почти" и не дает закрыть проект Предполагаемый алгоритм работы таков: 1. Система запускается, все хорошо. 2. Из EEPROM читаются 2 переменных, температура нагревателя и скорость мотора. 3. Нагреватель (при необходимости) начинает греться. Температура нагрева контролируется ч помощью ПИД регулятора (засада №1). 4. Когда температура устаканится, либо, по мнению пользователя, уже и так сойдет - ручками запускаем мотор, протягивающий ленту через нагреватель. Скорость вращения мотора задается средствами библиотеки AccelStepper (засада №2). Двигатель протяжки можно остановить в любой момент через менюшку. 5. В любой момент можно поменять скорость движка и температуру нагревателя. Остальные задумки уже не влазят в процессор , да и не особо нужны. Но пункт 5 немножко как раз и не работает. Система при старте считывает ранее заданные значения температуры и скорости, применяет их, а на дальнейшие мои попытки изменить их гордо корчит рожу. И, соотетственно, не меняет. Вот и хочу попросить совета, что я делаю не так. Самое противное, что примеры к библиотекам работают исправно, а в составе моего проекта - авотхрен. Проект строится на Atmega168P (Nano v2), мотор Nema17 с драйвером A4988. Из управления - 3 дискретных кнопки и экранчик 2*16 строчек. Прошу помощи Вот скетч (надеюсь, получится правильно вставить ) , схему подключений тоже нарисую, если нужно будет. Хотя там все задействованные лапы в дефайнах видны . #include "Wire.h" #include "LiquidCrystal_I2C.h" #include "GyverButton.h" #include <GyverTimers.h> #include <EEPROM.h> #define PID_INTEGER #include "GyverPID.h" //#include <GyverStepper.h> #include <AccelStepper.h> //----------------------------------------------------------------------------------------------------------------------- #define btn_dec_pin 11 #define btn_ok_pin 10 #define btn_inc_pin 9 #define btn_inc_step 20 #define btn_dec_step 20 // PWM пины: 3, 5, 6, 9, 10, 11 #define heater_pin 5 // Контакт D5 #define tsens_pin 21 // Контакт A7 #define fan_pin 6 // Контакт D6 #define thermistor_r 100000 // Номинальное сопротивление термистора при 25 градусах 100К #define t_nominal 25 // Температура, при которой меряется номинальное сопротивление термистора #define thermo_b 3950 // Какой-то бетта коэффициент термистора (обычно 3000-4000). ХЗ что это #define thermo_r 11880 // Постоянный резистор второго плеча термистора, 11.88К #define num_pas 10 // Количество измерений температуры для усреднения #define temp_addr 0 // Адрес в EEPROM для хранения температуры нагревателя #define speed_addr 2 // Адрес в EEPROM для хранения скорости протяжки // ПИД регулятор #define dt 500 // Частота регулировки ПИД 0.5 секунды #define PID_kp 5.2 #define PID_ki 0.5 #define PID_kd 0.5 // Мотор протяжки #define motor_steps 200 // Количество шагов мотора на оборот (для Nema17 200) #define motor_step_pin 15 // Контакт А1 #define motor_dir_pin 14 // Контакт А0 #define motor_en_pin 16 // Контакт А2 #define motor_max_speed 1000 // Максимальное число шагов в секунду //======================================================================================================================= LiquidCrystal_I2C lcd(0x27, 16, 2); GButton btn_dec(btn_dec_pin); GButton btn_inc(btn_inc_pin); GButton btn_ok(btn_ok_pin); //GyverPID regulator(1, 0, 0, 500); // коэф. П, коэф. И, коэф. Д, период дискретизации dt (мс) GyverPID regulator(0.1, 0.05, 0.01, 100); // коэф. П, коэф. И, коэф. Д, период дискретизации dt (мс) //GyverPID regulator(0.1, 0.05, 0.01); // коэф. П, коэф. И, коэф. Д // Определение тип интерфейса двигателя #define motorInterfaceType 1 AccelStepper motor(motorInterfaceType, motor_step_pin, motor_dir_pin); //======================================================================================================================= String menu_item [] = {"Temp ","Speed ","Motor ", "Heat ", "Fan ", "Save ", "Load "}; int menu_pos = 0; int heater_current_temp = 0; int heater_new_temp = 0; int motor_speed = 0; float error, error0, pid, pwr, integ; uint16_t Kp, Ki, Kd; bool heater_logo = false; static bool motor_enable = false; //----------------------------------------------------------------------------------------------------------------------- void Logo (void); void Btn_dec (int); void Btn_inc (int); void Btn_OK (); void Show (); void Save (); void Load (); int GetTemp (); void PID_heater (); void Motor_step (); void Ticks (); //======================================================================================================================= //----------------------------------------------------------------------------------------------------------------------- // Прерывание А таймера 1 ISR(TIMER1_A) { // прерывание таймера btn_dec.tick(); btn_inc.tick(); btn_ok.tick(); } //----------------------------------------------------------------------------------------------------------------------- void Logo (void) { String logo_str = "Extruder ver.0.0"; int pos = 0; for (pos==0; pos<logo_str.length (); pos++) { lcd.setCursor (pos,0); lcd.print (logo_str[pos]); delay (100); } delay (1000); lcd.clear (); } //----------------------------------------------------------------------------------------------------------------------- void Btn_dec (int clicks) { // 0 1 2 3 4 5 6 //"Temp ","Speed ","Motor ", "Heat ", "Fan ", "Save ", "Load " // Одиночные нажатия if (clicks==1) { switch (menu_pos) { case 0: if (heater_new_temp>0) {heater_new_temp--;}; break; case 1: {motor_speed=motor_speed-1;}; break; case 2: motor_enable = false; digitalWrite (motor_en_pin, HIGH); break; case 3: break; case 4: break; case 5: Save (); break; case 6: Load (); break; } }; // Долгое удержание if (clicks==2) { switch (menu_pos) { case 0: if (heater_new_temp>btn_dec_step) {heater_new_temp=heater_new_temp-btn_dec_step;}; break; case 1: {motor_speed=motor_speed-btn_dec_step;}; break; } }; } //----------------------------------------------------------------------------------------------------------------------- void Btn_inc (int clicks) { // 0 1 2 3 4 5 6 //"Temp ","Speed ","Motor ", "Heat ", "Fan ", "Save ", "Load " // Одиночные нажатия if (clicks==1) { switch (menu_pos) { case 0: heater_new_temp++; break; case 1: if (motor_speed<motor_max_speed) {motor_speed=motor_speed+1;}; break; case 2: motor_enable = true; digitalWrite (motor_en_pin, LOW); break; case 3: break; case 4: break; case 5: Save (); break; case 6: Load (); break; } }; // Долгое удержание if (clicks==2) { switch (menu_pos) { case 0: heater_new_temp=heater_new_temp+btn_inc_step; break; case 1: if (motor_speed<motor_max_speed-btn_inc_step) {motor_speed=motor_speed+btn_inc_step;}; break; }; }; } //----------------------------------------------------------------------------------------------------------------------- void Btn_OK () { // 0 1 2 3 4 5 6 //"Temp ","Speed ","Motor ", "Heat ", "Fan ", "Save ", "Load " switch (menu_pos) { case 0: break; case 1: motor.stop (); delay (20); motor.setSpeed(motor_speed); break; case 2: break; case 3: break; case 4: break; case 5: break; case 6: break; } menu_pos++; if (menu_pos==7) {menu_pos=0;}; } //----------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------- void Show (void) { lcd.setCursor (0,0); lcd.print (menu_item[menu_pos]); lcd.setCursor (6,0); lcd.print ("T="); lcd.print (heater_new_temp); lcd.print("/"); lcd.print(heater_current_temp); lcd.print(" "); lcd.setCursor (6,1); lcd.print ("S="); lcd.print (motor_speed); lcd.print(" "); lcd.setCursor (14,1); if (heater_logo==true) {lcd.print('h');} else {lcd.print(' ');}; lcd.setCursor (13,1); if (motor_enable==true) {lcd.print('m');} else {lcd.print(' ');}; //lcd.setCursor (0,1); lcd.print(regulator.getResultTimer()); lcd.print(" "); } //----------------------------------------------------------------------------------------------------------------------- void Save (void) { eeprom_update_word (temp_addr, heater_new_temp); eeprom_update_word (speed_addr, motor_speed); menu_pos = 0; } //----------------------------------------------------------------------------------------------------------------------- void Load (void) { heater_new_temp = eeprom_read_word (temp_addr); motor_speed = eeprom_read_word (speed_addr); menu_pos = 0; } //----------------------------------------------------------------------------------------------------------------------- int GetTemp(void) //Функция измерения температуры { int16_t At = 0; for (uint8_t i = 0; i < 10; i++) At += analogRead(tsens_pin); //Усредняем At /= 10; //10 последовательных измерений float Rt = 1023.0 / At - 1; Rt = thermo_r / Rt; float T; T = Rt / thermistor_r; T = log (T); T /= thermo_b; T += 1 / (t_nominal + 273.15); T = 1 / T; T -= 273.15; int xx; xx = T; return xx; } //----------------------------------------------------------------------------------------------------------------------- void PID_heater (void) { //heater_current_temp = GetTemp (); regulator.input = heater_current_temp; // сообщаем регулятору текущую температуру pwr = regulator.getResultTimer(); analogWrite(heater_pin, pwr); // отправляем на мосфет if (pwr>0) {heater_logo = true;} else {heater_logo = false;}; } //----------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------- void Ticks (void) { btn_dec.tick(); btn_inc.tick(); btn_ok.tick(); if (motor_enable==true) {motor.runSpeed();}; } //----------------------------------------------------------------------------------------------------------------------- void PreSave (void) { motor_speed = 500; heater_new_temp = 50; Save (); lcd.clear (); lcd.print ("EEPROM saved"); lcd.setCursor (0,1); lcd.print ("T=50, S=500"); delay (1000); } //----------------------------------------------------------------------------------------------------------------------- void PreLoad (void) { Load (); lcd.clear (); lcd.print ("EEPROM loaded"); lcd.setCursor (0,1); lcd.print ("T="); lcd.print (heater_new_temp); lcd.print ("S=500"); lcd.print (motor_speed); delay (1000); } //----------------------------------------------------------------------------------------------------------------------- //======================================================================================================================= void setup() { // Инициализация портов { pinMode (motor_en_pin, OUTPUT); pinMode (motor_dir_pin, OUTPUT); pinMode (motor_step_pin, OUTPUT); pinMode (heater_pin, OUTPUT); pinMode (fan_pin, OUTPUT); digitalWrite (motor_en_pin, HIGH); digitalWrite (motor_dir_pin, HIGH); digitalWrite (motor_step_pin, HIGH); digitalWrite (heater_pin, LOW); digitalWrite (fan_pin, LOW); } // Инициализация дисплея { lcd.init(); lcd.backlight(); lcd.clear (); } Load (); // Инициализация таймера { //Timer1.setFrequency(1000); // 1KHz //Timer1.enableISR(); // Запускаем прерывание (по умолч. канал А) } // Инициализация ПИД регулятора { regulator.setDirection(NORMAL); // направление регулирования (NORMAL/REVERSE). ПО УМОЛЧАНИЮ СТОИТ NORMAL regulator.setLimits(0, 255); // пределы (ставим для 8 битного ШИМ). ПО УМОЛЧАНИЮ СТОЯТ 0 И 255 regulator.setpoint = heater_new_temp; // сообщаем регулятору температуру, которую он должен поддерживать // в процессе работы можно менять коэффициенты //regulator.Kp = 5.2; //regulator.Ki += 0.5; //regulator.Kd = 0; regulator.Kp = PID_kp; regulator.Ki +=PID_ki; regulator.Kd = PID_kd; } // Инициализация двигателя протяжки { // Устанавливаем максимальную скорость, коэффициент ускорения, начальную скорость motor.setMaxSpeed(motor_max_speed); motor_speed = -1000; motor.setSpeed(motor_speed); } // Прочее { Logo (); // Загрузка сохраненных в ЕЕПРОМ значений, если это необходимо if (digitalRead (btn_dec_pin)==0&&digitalRead (btn_inc_pin)==0) {PreSave (); Logo();}; if (digitalRead (btn_ok_pin)==0&&digitalRead (btn_inc_pin)==0) {PreLoad (); Logo();}; } } //----------------------------------------------------------------------------------------------------------------------- //======================================================================================================================= void loop() { Ticks (); heater_current_temp = GetTemp (); if (btn_dec.isClick()) {Btn_dec(1);}; if (btn_inc.isClick()) {Btn_inc(1);}; if (btn_ok.isClick()) {Btn_OK();}; if (btn_dec.isHolded()) {Btn_dec(2);}; if (btn_inc.isHolded()) {Btn_inc(2);}; Show (); PID_heater (); }
  8. Думаете, ТС уже собрал чего-то там и даже попробовал сунуть это в розетку? Мой последний гаусс, кстати, тоже был состряпан по схема ТСа. И даже умудрился прострелить полиэтиленовый пакет
  9. Ключ можно взять от паровоза - он понадежнее будет. Кстати да, необходимость собирать для школы что-то, что имеет в себе напряжение выше полудохлой батарейки - это как-то не современно. Это ведь может быть опасно - втыкатьв розетку фиг пойми чего.
  10. ААА! Отпусти меня, КР580ВМ80! Уйди, КР1818ВГ93! Опять приходили К155ЛА3, звали с собой! Сестра, дайте брому! И при луне нет мне покоя, плохая должность и все такое... Ну теперь-то уж точно придут добрые модераторы и всем станет тихо, хорошо и я забудусь спокойным сном
  11. У Вас в качестве снаряда иголка дана по заданию ил Вы сами так решили? Если сами, то выберите что-то потолще, т.к. величина магнитного сцепления зависит от толщины снаряда. Иголками, увы, не стреляют, зато стреляют гвоздями почему-то.
  12. Если сократить многабукоф, то нелья - у резистора сопротивление не зависит от температуры (в идеале), а у термозависимых приборов на этой зависимости как раз вся работа построена.
  13. Модератор! Потрите эти два последних поста, пожалуйста! Я только завязал с хроническим плюшкинизмом, выбросил весь старый хлам, а тут они опять в соблазн вводят!
  14. В настоящий момент на NodeMCU планируется свесить весь функционал узлов. Еще раз уточню, что узлы планируется не очень обременять интеллектом - так, на уровне простого термостата с каналом связи с Центром. Ну, может быть, два термостата в одном флаконе, если позволит количество ножек модуля. Как вариант так же рассматриваю связку какой-либо МК+NodeMCU, где нода - это просто довесок для связи. Правда, в таком случае лучше взять что-то поскромнее и подешевле, наверное. Пока читаю азы типа мигания светодиодом по сети, смотрю, что вообще эта фигнюшка умеет. В целом, штучка любопытная, закажу парочку, будем посмотреть
×
×
  • Create New...