Немножко на мой взгляд улутшил код. Теперь при входе в режим КАЛИБРОВКИ, в зависимости от режима меню - мигает тот светодиод - который ми калибруем или оба.
До этого было не понятно в каком режиме мы находимся.
//********** (РЕЖИМ 1-ШАГ) Крутим с помощью сдвига --рабочая - крутит туда сюда без потери шагов - ускоряет - отключает катушки после бездействия
//PORTB - 8, 9, 10, 11 - Шаговик. && 12-кнопка Menu \ 13-Светодиод 1й штор.
//PORTD - 4, 5, 6, 7 - Шаговик. && 2-кнопка UP \ 3-кнопка DOWN
// А0-Светодиод 2й штор..
#include <CyberLib.h>
//Задаем ускорение
#define uskor 3
byte n1 = 1;// Сдвигаем 1 бит
byte n3 = 0x10;
byte f_tim = 0;
byte sped_Xt = uskor;//Начальная скорость
byte sped_X = 0; //Ускорение
byte sped_Zt = uskor;//Начальная скорость
byte sped_Z = 0; //Ускорение
bool f_run1X = 0;//Сброс после остановки 3 переменные.
bool f_run2X = 0;
unsigned long no_runX; //Переменная для прошедшего периода
bool f_run1Z = 0;//Сброс после остановки 3 переменные.
bool f_run2Z = 0;
unsigned long no_runZ; //Переменная для прошедшего периода
// Переменные для кн.Menu
bool kn_menu;
bool f_menu;
bool f_Mpush;
bool f_Md;
uint8_t Menu = 1;
uint8_t temp_Menu;
bool kalib;
unsigned long menu_dreb;
unsigned long menu_klik;
// Переменные для кн.Up
bool kn_Up;
bool f_Up;
bool state_Up;
bool _UP;
uint32_t Up_dreb;
// Переменные для кн.Down
bool kn_Down;
bool f_Down;
bool state_Down;
bool _Down;
uint32_t Down_dreb;
uint32_t sbros;
bool f_sbros;
uint32_t cur_time;
uint32_t blink_time;
bool f_blink;
int Shtora1 = 50;// количество шагов для полного закрытия шторы 1;
int Shtora2 = 34;// количество шагов для полного закрытия шторы 2
void setup() {
// DDRB пин, 8,9,10,11 - Шаговик, pin 12- вход, 13- Выход
DDRB = DDRB | B00101111;
// pin 8,9,10,11,13 - выход в 0 а входы pin 12, - 0
PORTB = B00000000;
// DDRD, подключенный к двигателю pin 4,5,6,7 как выход,pin2,3 Выход
DDRD = DDRD | B11110000;
// pin 4,5,6,7 - выход в 0 а входы pin 2,3 - 0
PORTD = B00000000;//;
D14_Out; // Led_2
D14_Low;
Serial.begin(9600);
// Инициализировать TIMER1
noInterrupts (); // отключить все прерывания
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 125; // сравнить регистр (скорость!!!(2ms=125 - если медленнее - УВЕЛИЧИВАЕМ)
TCCR1B |= (1 << WGM12); // Режим СТС
TCCR1B |= (1 << CS12); // 256 делитель
TIMSK1 |= (1 << OCIE1A ); // включить таймер сравнить прерываний
interrupts(); // включить все прерывания
}
ISR (TIMER1_COMPA_vect) // Функция прерывания таймера
{
// Serial.println(f_tim);
f_tim = B1111;
}
//Функция вращения dvigatel 1
void RunX (bool perem_X)
{
f_tim &= B1110;
if (perem_X) {
n1 = (n1 >> 1) | (n1 << 3); //Сдвигаем
--Shtora1;
}
else {
n1 = (n1 << 1) | (n1 >> 3); //Сдвигаем
++Shtora1;
}
n1 = 0x0F & n1; //Маскируем кнопки
PORTB = (PORTB & 0xF0) | n1; //Очищаем Младшие биты и пишем туда n1
}
//Функция dvigatel 3
void RunZ (bool perem_Z)
{
f_tim &= B1011;
if (perem_Z) {
n3 = (n3 >> 1) | (n3 << 3); //Сдвигаем
--Shtora2;
}
else {
n3 = (n3 << 1) | (n3 >> 3); //Сдвигаем
++Shtora2;
}
n3 = 0xF0 & n3;//Маскируем
PORTD = (PORTD & 0xF) | n3; //Очищаем старшие биты и пишем туда n3
//Serial.println(n3);
}
void loop() {
static bool tem_UP;
if (_UP != tem_UP) {
tem_UP = _UP;
Serial.print("UP- "); Serial.println(_UP);
}
static bool tem_Down;
if (_Down != tem_Down)
{
tem_Down = _Down;
Serial.print("Down- "); Serial.println(_Down);
}
cur_time = millis();
///////////////////Проверка кнопки МЕНЮ - АНТИДРЕБЕЗГ
if (D12_Read && !f_menu)
{
menu_dreb = cur_time;
f_menu = 1;
}
if (!D12_Read)
{
kn_menu = 0;
f_menu = 0;
}
if (f_menu && cur_time - menu_dreb >= 20)
{
kn_menu = 1;
if (!f_Mpush) {
menu_klik = cur_time;
f_Mpush = 1;
}
}
if (f_Mpush && !kn_menu && cur_time - menu_klik < 500) {
if (_UP || _Down) {
_UP = 0;
_Down = 0;
}
else Menu++; // Меняем
if (Menu > 3) Menu = 1;
f_Mpush = 0;
}
else if (f_Mpush && !kn_menu && cur_time - menu_klik > 500) {
kalib = !kalib; // Включаем калибровку
Serial.print("kalib- "); Serial.println(kalib);
f_Mpush = 0;
}
///////////////////////Проверка кнопки UP - АНТИДРЕБЕЗГ
if (D2_Read != f_Up) { //Если сигнал изменился
f_Up = !f_Up;
Up_dreb = cur_time;
}
if (kn_Up == D2_Read && cur_time - Up_dreb > 20) kn_Up = !D2_Read;
// Было нажатие
if (kn_Up && !state_Up) {
if (_UP || _Down) {
_UP = 0;
_Down = 0;
state_Up = 1;
}
else {
_UP = !_UP; // Меняем значение
state_Up = 1;
}
}
if (!kn_Up)state_Up = 0; // Отпустили
///////////////////////Проверка кнопки DOWN - АНТИДРЕБЕЗГ
if (D3_Read != f_Down) { //Если сигнал изменился
f_Down = !f_Down;
Down_dreb = cur_time;
}
if (kn_Down == D3_Read && cur_time - Down_dreb > 20) kn_Down = !D3_Read;
// Было нажатие
if (kn_Down && !state_Down) {
if (_UP || _Down) {
_UP = 0;
_Down = 0;
state_Down = 1;
}
else {
_Down = !_Down; // Меняем значение
state_Down = 1;
}
}
if (!kn_Down)state_Down = 0; // Отпустили
//////////////////////// С кнопками закончили продолжаем логику
if (!kalib)
{
if (Menu != temp_Menu) {
temp_Menu = Menu;
Serial.print("Menu- "); Serial.println(Menu);
switch (Menu) {
case 1: D13_High; D14_Low; break;
case 2: D13_Low; D14_High; break;
case 3: D13_High; D14_High; break;
}
}
}
else {
if (cur_time - blink_time >= 300)
{
blink_time = cur_time;
switch (Menu) {
case 1: D13_Inv; D14_Low; break;
case 2: D13_Low; D14_Inv; break;
case 3: D13_Inv; D14_Inv; break;
}
}
}
/////////////////////////// Запуск 1го двигателя если " perem_X != 0 "
//if (!kalib) {
if (_UP || _Down) {
if (Menu != 2) {
if (f_tim & (1 << 0)) {
if (!sped_X) {
if (!kalib)//Калибровка отк.
{
if (_UP && Shtora1 < 50) {//3592
RunX(0);
Serial.print("Shtora1- "); Serial.println(Shtora1);
}
if (_Down && Shtora1 > 0) {
RunX(1);
Serial.print("Shtora1- "); Serial.println(Shtora1);
}
}
else { //Калибровка вкл.
if (_UP) {
Shtora1 = 0;
RunX(0);
Serial.print("Shtora1- "); Serial.println(Shtora1);
}
if (_Down) {
Shtora1 = 1;
RunX(1);
Serial.print("Shtora1- "); Serial.println(Shtora1);
}
}
if (sped_Xt > 0) {
--sped_Xt;
sped_X = sped_Xt;
}
}
else {
--sped_X;
f_tim &= B1110;
}
}////
else {
f_run2X = 1;
no_runX = cur_time;
}
}
}
else {
sped_Xt = uskor;
sped_X = 0; // для пропуска 1го тика
}
//}
/////////////////Запуск 3го двигателя если " perem_Z != 0 "
//if (!kalib) {
if (_UP || _Down) {
if (Menu != 1) {
if (f_tim & (1 << 2)) {
if (!sped_Z) {
if (!kalib)//Калибровка отк.
{
if (_UP && Shtora2 < 34) {//3475
RunZ(0);
Serial.print("Shtora2- "); Serial.println(Shtora2);
}
if (_Down && Shtora2 > 0) {
RunZ(1);
Serial.print("Shtora2- "); Serial.println(Shtora2);
}
}
else {//Калибровка Вкл.
if (_UP) {
Shtora2 = 0;
RunZ(0);
Serial.print("Shtora2- "); Serial.println(Shtora2);
}
if (_Down) {
Shtora2 = 1;
RunZ(1);
Serial.print("Shtora2- "); Serial.println(Shtora2);
}
}
if (sped_Zt > 0) {
--sped_Zt;
sped_Z = sped_Zt;
}
}
else {
--sped_Z;
f_tim &= B1011;
}
}////
else {
f_run2Z = 1;
no_runZ = cur_time;
}
}
}
else {
sped_Zt = uskor;
sped_Z = 0; // для пропуска 1го тика
}
//Если достигли конца сбрасываем UP\Down
if (f_tim != 15)
{
sbros = cur_time;
f_sbros = 0;
}
if (!f_sbros && cur_time - sbros > 1500)
{
f_sbros = 1;
_UP = 0;
_Down = 0;
}
//Снимаем напряжение с катушек двигателя X
if (f_run2X && cur_time - no_runX >= 1000)// закончилось ли время
{
f_run2X = 0;
PORTB &= 0xF0;
}
//Снимаем напряжение с катушек двигателя Z
if (f_run2Z && cur_time - no_runZ >= 1000)// закончилось ли время
{
f_run2Z = 0;
PORTD &= 0xF;
}
}
Немножко на мой взгляд улутшил код. Теперь при входе в режим КАЛИБРОВКИ, в зависимости от режима меню - мигает тот светодиод - который ми калибруем или оба.
До этого было не понятно в каком режиме мы находимся.
А оба зачем? Две шторы одновременно смысла нет калибровать. У нас самое главное не работает.....моторы не крутятся и кренка сильно греется!!! В симуляторе светодиоды бегают прикольно, а реальная сборка работать не хочет. Первый скетч работает изумительно, для режима калибровки самое то....пока держишь кнопку - мотор крутится, отпустил - остановился. Вот этот скетч.
//********** (РЕЖИМ 1-ШАГ) Крутим с помощью сдвига --рабочая - крутит туда сюда без потери шагов - ускоряет - отключает катушки после бездействия
//PORTB - 8, 9, 10, 11 - Шаговик. && 12, 13 - Вход сигнал от 2х кнопок (влево - вправо)
//PORTD - 4, 5, 6, 7 - Шаговик. && 2, 3 - остаются для переферии
#define uskor 2 //Задаем ускорение
byte n1 = 1;// Сдвигаем 1 бит
byte n3 = 0x10;
byte f_tim = 0;
long int perem_X = 0;
long int perem_Z = 0;
byte sped_Xt = uskor;//Начальная скорость
byte sped_X = 0; //Ускорение
byte sped_Zt = uskor;//Начальная скорость
byte sped_Z = 0; //Ускорение
bool f_run1X = 0;//Сброс после остановки 3 переменные.
bool f_run2X = 0;
unsigned long no_runX; //Переменная для прошедшего периода
bool f_run1Z = 0;//Сброс после остановки 3 переменные.
bool f_run2Z = 0;
unsigned long no_runZ; //Переменная для прошедшего периода
void setup() {
// пин, 8, 9, 10, 11 - Шаговик, 2, 3- переферия
DDRB = 0xCF;
//Устанавлюем значение выходов в 0 а входы - подтягивающий резистор
PORTB = 0x30;
// PORTD, подключенный к двигателю 3 как выход, Две кнопки с подтяжкой pin2-3
DDRD = DDRD | B11110000;
//Устанавлюем значение выходов PORTD в 0
PORTD = PORTD | B00001100;//x0F;
// Serial.begin(9600);
// Инициализировать TIMER1
noInterrupts (); // отключить все прерывания
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 125; // сравнить регистр (скорость!!!(2ms=125 - если медлиннее - УВЕЛИЧУЕМ)
TCCR1B |= (1 << WGM12); // Режим СТС
TCCR1B |= (1 << CS12); // 256 делитель
TIMSK1 |= (1 << OCIE1A ); // включить таймер сравнить прерываний
interrupts(); // включить все прерывания
}
ISR (TIMER1_COMPA_vect) // Функция прерывания таймера
{
// Serial.println(f_tim);
f_tim = B1111;
}
//Функция вращения dvigatel 1
void RunX ()
{
f_tim &= B1110;
if (perem_X > 0) {
n1 = (n1 >> 1) | (n1 << 3); //Сдвигаем
--perem_X;
}
else {
n1 = (n1 << 1) | (n1 >> 3); //Сдвигаем
++perem_X;
}
n1 = 0x0F & n1; //Маскируем кнопки
PORTB = (PORTB & 0xF0) | n1; //Очищаем Младшие биты и пишем туда n1
}
//Функция dvigatel 3
void RunZ ()
{
f_tim &= B1011;
if (perem_Z > 0) {
n3 = (n3 >> 1) | (n3 << 3); //Сдвигаем
--perem_Z;
}
else {
n3 = (n3 << 1) | (n3 >> 3); //Сдвигаем
++perem_Z;
}
n3 = 0xF0 & n3;//Маскируем
PORTD = (PORTD & 0xF) | n3; //Очищаем старшие биты и пишем туда n3
//Serial.println(n3);
}
void loop() {
//Кнопки 1 и 2 служат для демонстрации работы. Считается замкнутой при подаче МИНУСА
if ((PIND & (1 << 3))) //проверяем кнопку 1 - нажали? Можно использовать if(!digitalRead(2))
{
//Задаем количество шагов для дв.- ВПРАВО "perem_X = Количеству шагов;"
perem_X = 10;
perem_Z = -10;
}
//else perem_X = 0; // ВНИМАНИЕ если задаём количество шагов - эту строчку удаляем!!!
if ((PIND & (1 << 2))) //проверяем кнопку 2 - нажали? Можно использовать if(!digitalRead(3))
{
//Задаем количество шагов для дв.- ВЛЕВО "perem_X = -Количеству шагов;"
perem_X = -10;
perem_Z = 10;
}
/////////////////////////// Запуск 1го двигателя если " perem_X != 0 "
if (perem_X != 0) {
f_run1X = 1;
f_run2X = 0;
if (f_tim & (1 << 0)) {
if (!sped_X) {
RunX();
if (sped_Xt > 0) {
--sped_Xt;
sped_X = sped_Xt;
}
}
else {
--sped_X;
f_tim &= B1110;
}
}
}
else {
sped_Xt = uskor;
sped_X = 0; // для пропуска 1го тика
}
/////////////////Запуск 3го двигателя если " perem_Z != 0 "
if (perem_Z != 0) {
f_run1Z = 1;
f_run2Z = 0;
if (f_tim & (1 << 2)) {
if (!sped_Z) {
RunZ();
if (sped_Zt > 0) {
--sped_Zt;
sped_Z = sped_Zt;
}
}
else {
--sped_Z;
f_tim &= B1011;
}
}
}
else {
sped_Zt = uskor;
sped_Z = 0; // для пропуска 1го тика
}
//Снимаеммаем напряжение с катушек двигателя X
if (f_run1X && perem_X == 0) //Служит для запуска отключения катушек
{
f_run1X = 0;
f_run2X = 1;
no_runX = millis();
}
if (f_run2X && millis() - no_runX >= 1000)// Проверяем закончилось ли время
{
f_run2X = 0;
//Снимаем напряжение с катушек
PORTB &= 0xF0;
}
//Снимаеммаем напряжение с катушек двигателя Z
if (f_run1Z && perem_Z == 0) //Служит для запуска отключения катушек
{
f_run1Z = 0;
f_run2Z = 1;
no_runZ = millis();
}
if (f_run2Z && millis() - no_runZ >= 1000)// Проверяем закончилось ли время
{
f_run2Z = 0;
//Снимаем напряжение с катушек
PORTD &= 0xF;
}
}
По-поводу калибровки я считаю, что правильней калибровать "0" вверху, т.е. начальное положение из которого штора разматывается и чтобы штора не замоталась в барабан.
Вот скетч провери его на живой ардуине, правда на однм двигателе, крутит отключает, ничего не греется. Проблему скорости давал Сериал, пришлось его удалить. В принцепе он нужен только для настройки. А так пока искал причину по скорости то таймер поменял и так помелочам. Ммаксимальную высоту будете ставить в самом начале _ там написано
//********** (РЕЖИМ 1-ШАГ) Крутим с помощью сдвига --рабочая - крутит туда сюда без потери шагов - ускоряет - отключает катушки после бездействия
//PORTB - 8, 9, 10, 11 - Шаговик. && 12-кнопка Menu \ 13-Светодиод 1й штор.
//PORTD - 4, 5, 6, 7 - Шаговик. && 2-кнопка UP \ 3-кнопка DOWN
// А0-Светодиод 2й штор..
#include <CyberLib.h>
#define uskor 5 //Задаем ускорение
//Здесь устанавливаем максимальное кол. шагов для штор
#define max_Sht1 5000
#define max_Sht2 5000
byte n1 = 1;// Сдвигаем 1 бит
byte n3 = 0x10;
bool f_timX = 0;
bool f_timZ = 0;
//long int perem_X = 0;
//long int perem_Z = 0;
byte sped_Xt = uskor;//Начальная скорость
byte sped_X = 0; //Ускорение
byte sped_Zt = uskor;//Начальная скорость
byte sped_Z = 0; //Ускорение
bool f_run1X = 0;//Сброс после остановки 2 переменные.
//bool f_run1X = 0;
unsigned long no_runX; //Переменная для прошедшего периода
bool f_run1Z = 0;//Сброс после остановки 2 переменные.
//bool f_run1Z = 0;
unsigned long no_runZ; //Переменная для прошедшего периода
// Переменные для кн.Menu
bool kn_menu;
bool f_menu;
bool f_Mpush;
bool f_Md;
uint8_t Menu = 1;
uint8_t temp_Menu;
bool kalib;
unsigned long menu_dreb;
unsigned long menu_klik;
// Переменные для кн.Up
bool kn_Up;
bool f_Up;
bool state_Up;
bool _UP;
uint32_t Up_dreb;
// Переменные для кн.Down
bool kn_Down;
bool f_Down;
bool state_Down;
bool _Down;
uint32_t Down_dreb;
//сбрасываем UP\Down
uint32_t sbros;
bool f_sbros;
uint32_t cur_time;//Миллис читаем один раз
uint32_t blink_time;//Мигаем в режиме калибровки
int Shtora1 = 50;// количество шагов для полного закрытия шторы 1;
int Shtora2 = 34;// количество шагов для полного закрытия шторы 2
void setup() {
// DDRB пин, 8,9,10,11 - Шаговик, pin 12- вход, 13- Выход
DDRB = DDRB | B00101111;
// pin 8,9,10,11,13 - выход в 0 а входы pin 12, - 0
PORTB = B00000000;
// DDRD, подключенный к двигателю pin 4,5,6,7 как выход,pin2,3 Выход
DDRD = DDRD | B11110000;
// pin 4,5,6,7 - выход в 0 а входы pin 2,3 - 0
PORTD = B00000000;//;
D14_Out; // Led_2
D14_Low;
//Serial.begin(9600);
// Инициализировать TIMER1
StartTimer1(Time_Closk, 2000);
}
void Time_Closk() // Функция прерывания таймера
{
f_timX = 1;
f_timZ = 1;
}
//Функция вращения dvigatel 1
void RunX (bool perem_X)
{
f_timX = 0;
if (perem_X) {
n1 = (n1 >> 1) | (n1 << 3); //Сдвигаем
--Shtora1;
}
else {
n1 = (n1 << 1) | (n1 >> 3); //Сдвигаем
++Shtora1;
}
n1 = 0x0F & n1; //Маскируем кнопки
PORTB = (PORTB & 0xF0) | n1; //Очищаем Младшие биты и пишем туда n1
}
//Функция dvigatel 3
void RunZ (bool perem_Z)
{
f_timZ = 0;
if (perem_Z) {
n3 = (n3 >> 1) | (n3 << 3); //Сдвигаем
--Shtora2;
}
else {
n3 = (n3 << 1) | (n3 >> 3); //Сдвигаем
++Shtora2;
}
n3 = 0xF0 & n3;//Маскируем
PORTD = (PORTD & 0xF) | n3; //Очищаем старшие биты и пишем туда n3
}
void loop() {
cur_time = millis();
///////////////////Проверка кнопки МЕНЮ - АНТИДРЕБЕЗГ
if (D12_Read && !f_menu)
{
menu_dreb = cur_time;
f_menu = 1;
}
if (!D12_Read)
{
kn_menu = 0;
f_menu = 0;
}
if (f_menu && cur_time - menu_dreb >= 20)
{
kn_menu = 1;
if (!f_Mpush) {
menu_klik = cur_time;
f_Mpush = 1;
}
}
if (f_Mpush && !kn_menu && cur_time - menu_klik < 500) {
if (_UP || _Down) {
_UP = 0;
_Down = 0;
}
else Menu++; // Меняем
if (Menu > 3) Menu = 1;
f_Mpush = 0;
}
else if (f_Mpush && !kn_menu && cur_time - menu_klik > 500) {
kalib = !kalib; // Включаем калибровку
f_Mpush = 0;
}
///////////////////////Проверка кнопки UP - АНТИДРЕБЕЗГ
if (D2_Read != f_Up) { //Если сигнал изменился
f_Up = !f_Up;
Up_dreb = cur_time;
}
if (kn_Up == D2_Read && cur_time - Up_dreb > 20) kn_Up = !D2_Read;
// Было нажатие
if (kn_Up && !state_Up) {
if (_UP || _Down) {
_UP = 0;
_Down = 0;
state_Up = 1;
}
else {
_UP = !_UP; // Меняем значение
state_Up = 1;
}
}
if (!kn_Up)state_Up = 0; // Отпустили
///////////////////////Проверка кнопки DOWN - АНТИДРЕБЕЗГ
if (D3_Read != f_Down) { //Если сигнал изменился
f_Down = !f_Down;
Down_dreb = cur_time;
}
if (kn_Down == D3_Read && cur_time - Down_dreb > 20) kn_Down = !D3_Read;
// Было нажатие
if (kn_Down && !state_Down) {
if (_UP || _Down) {
_UP = 0;
_Down = 0;
state_Down = 1;
}
else {
_Down = !_Down; // Меняем значение
state_Down = 1;
}
}
if (!kn_Down)state_Down = 0; // Отпустили
//////////////////////// С кнопками закончили продолжаем логику
if (!kalib)
{
if (Menu != temp_Menu) {
temp_Menu = Menu;
switch (Menu) {
case 1: D13_High; D14_Low; break;
case 2: D13_Low; D14_High; break;
case 3: D13_High; D14_High; break;
}
}
}
else {
if (cur_time - blink_time >= 300)
{
blink_time = cur_time;
switch (Menu) {
case 1: D13_Inv; D14_Low; break;
case 2: D13_Low; D14_Inv; break;
case 3: D13_Inv; D14_Inv; break;
}
}
}
/////////////////////////// Запуск 1го двигателя если " perem_X != 0 "
if (f_timX) {
if (_UP || _Down) {
if (Menu != 2) {
if (!sped_X) {
if (!kalib) { //Калибровка отк.
if (_UP && Shtora1 < max_Sht1) {//3592
RunX(0);
}
if (_Down && Shtora1 > 0) {
RunX(1);
}
}
else { //Калибровка вкл.
if (_UP) {
Shtora1 = 0;
RunX(0);
}
if (_Down) {
Shtora1 = 1;
RunX(1);
}
}
}
else if (sped_Xt > 0) {
--sped_Xt;
sped_X = sped_Xt;
f_timX = 0;
}
else {
--sped_X;
f_timX = 0;
}
}
}////
}
else {
f_run1X = 1;
no_runX = cur_time;
sbros = cur_time;
f_sbros = 1;
sped_Xt = uskor;
sped_X = 0; // для пропуска 1го тика
}
/////////////////Запуск 3го двигателя если " perem_Z != 0 "
//if (!kalib) {
if (f_timZ) {
if (_UP || _Down) {
if (Menu != 1) {
if (!sped_Z) {
if (!kalib)//Калибровка отк.
{
if (_UP && Shtora2 < max_Sht2) {//3475
RunZ(0);
}
if (_Down && Shtora2 > 0) {
RunZ(1);
}
}
else {//Калибровка Вкл.
if (_UP) {
Shtora2 = 0;
RunZ(0);
}
if (_Down) {
Shtora2 = 1;
RunZ(1);
}
}
}
else if (sped_Zt > 0) {
--sped_Zt;
sped_Z = sped_Zt;
f_timZ = 0;
}
}
else {
--sped_Z;
f_timZ = 0;
}
}////
}
else {
f_run1Z = 1;
no_runZ = cur_time;
sbros = cur_time;
f_sbros = 1;
sped_Zt = uskor;
sped_Z = 0; // для пропуска 1го тика
}
//Снимаем напряжение с катушек двигателя X
if (f_run1X && cur_time - no_runX >= 1000)// закончилось ли время
{
f_run1X = 0;
PORTB &= 0xF0;
}
//Снимаем напряжение с катушек двигателя Z
if (f_run1Z && cur_time - no_runZ >= 1000)// закончилось ли время
{
f_run1Z = 0;
PORTD &= 0xF;
}
}
Добрый вечер. Спасибо, сейчас буду проверять. Я тут немного со схемой повозился, 1 светодиод повесил на 14 пин, 2 светодиод на 15 пин, а на 16 пин прицепил пищалку(при навигации по меню удобно). Можно добавить в скетч?
void Beep() //короткий звук, переключение шторы
{
tone(ton,500,500);
delay(200);
noTone(ton);
}
void Beep_long() //длинный звук, вход и выход из режима калибровки "0"
{
tone(ton,200,1000);
delay(200);
noTone(ton);
}
Проверил скетч...
Со второй шторой всё получилось хорошо, методом тыка настроил высоту - 27500. Ездит хорошо. Полное закрытие или открытие занимает 55 секунд. Немножко не понял в режиме калибровки....как только в него входишь, штору сразу затягивает в барабан, кнопками UP и DOWN возвращаешь на нужное место. С моргающим светодиодом прикольно!
С первой шторой не получится настроить, потому что она должна работать в обратном порядке...моторы стоят не симметрично, здесь нужно инверсию делать.
Вот сделал инверсию попробуйте. Поповоду скорости в стр.72 - StartTimer1(Time_Closk, 2000); можете поиграться с числом, сейчас стоит 2 мс. на меньшем значении у меня стабильно не работает, а у Вас может и будет. По поводу калибровки: при первом входе он сам движется или после установки, при втором заходе тоже?
//********** (РЕЖИМ 1-ШАГ) Крутим с помощью сдвига --рабочая - крутит туда сюда без потери шагов - ускоряет - отключает катушки после бездействия
//PORTB - 8, 9, 10, 11 - Шаговик. && 12-кнопка Menu \ 13-Светодиод 1й штор.
//PORTD - 4, 5, 6, 7 - Шаговик. && 2-кнопка UP \ 3-кнопка DOWN
// А0-Светодиод 2й штор..
#include <CyberLib.h>
#define uskor 2 //Задаем ускорение
//Здесь устанавливаем максимальное кол. шагов для штор
#define max_Sht1 5000
#define max_Sht2 5000
byte n1 = 1;// Сдвигаем 1 бит
byte n3 = 0x10;
bool f_timX = 0;
bool f_timZ = 0;
byte sped_Xt = uskor;//Начальная скорость
byte sped_X = 0; //Ускорение
byte sped_Zt = uskor;//Начальная скорость
byte sped_Z = 0; //Ускорение
bool f_run1X = 0;//Сброс после остановки 2 переменные.
//bool f_run1X = 0;
unsigned long no_runX; //Переменная для прошедшего периода
bool f_run1Z = 0;//Сброс после остановки 2 переменные.
//bool f_run1Z = 0;
unsigned long no_runZ; //Переменная для прошедшего периода
// Переменные для кн.Menu
bool kn_menu;
bool f_menu;
bool f_Mpush;
bool f_Md;
uint8_t Menu = 1;
uint8_t temp_Menu;
bool kalib;
unsigned long menu_dreb;
unsigned long menu_klik;
// Переменные для кн.Up
bool kn_Up;
bool f_Up;
bool state_Up;
bool _UP;
uint32_t Up_dreb;
// Переменные для кн.Down
bool kn_Down;
bool f_Down;
bool state_Down;
bool _Down;
uint32_t Down_dreb;
//сбрасываем UP\Down
uint32_t sbros;
bool f_sbros;
uint32_t cur_time;//Миллис читаем один раз
uint32_t blink_time;//Мигаем в режиме калибровки
int Shtora1 = 50;// количество шагов для полного закрытия шторы 1;
int Shtora2 = 34;// количество шагов для полного закрытия шторы 2
void setup() {
// DDRB пин, 8,9,10,11 - Шаговик, pin 12- вход, 13- Выход
DDRB = DDRB | B00101111;
// pin 8,9,10,11,13 - выход в 0 а входы pin 12, - 0
PORTB = B00000000;
// DDRD, подключенный к двигателю pin 4,5,6,7 как выход,pin2,3 Выход
DDRD = DDRD | B11110000;
// pin 4,5,6,7 - выход в 0 а входы pin 2,3 - 0
PORTD = B00000000;//;
D14_Out; // Led_2
D14_Low;
//Serial.begin(9600);
// Инициализировать TIMER1
StartTimer1(Time_Closk, 2000);
}
void Time_Closk() // Функция прерывания таймера
{
f_timX = 1;
f_timZ = 1;
}
//Функция вращения dvigatel 1
void RunX (bool perem_X)
{
f_timX = 0;
if (perem_X) {
n1 = (n1 >> 1) | (n1 << 3); //Сдвигаем
--Shtora1;
}
else {
n1 = (n1 << 1) | (n1 >> 3); //Сдвигаем
++Shtora1;
}
n1 = 0x0F & n1; //Маскируем кнопки
PORTB = (PORTB & 0xF0) | n1; //Очищаем Младшие биты и пишем туда n1
}
//Функция dvigatel 3
void RunZ (bool perem_Z)
{
f_timZ = 0;
if (perem_Z) {
n3 = (n3 >> 1) | (n3 << 3); //Сдвигаем
--Shtora2;
}
else {
n3 = (n3 << 1) | (n3 >> 3); //Сдвигаем
++Shtora2;
}
n3 = 0xF0 & n3;//Маскируем
PORTD = (PORTD & 0xF) | n3; //Очищаем старшие биты и пишем туда n3
}
void loop() {
cur_time = millis();
///////////////////Проверка кнопки МЕНЮ - АНТИДРЕБЕЗГ
if (D12_Read && !f_menu)
{
menu_dreb = cur_time;
f_menu = 1;
}
if (!D12_Read)
{
kn_menu = 0;
f_menu = 0;
}
if (f_menu && cur_time - menu_dreb >= 20)
{
kn_menu = 1;
if (!f_Mpush) {
menu_klik = cur_time;
f_Mpush = 1;
}
}
if (f_Mpush && !kn_menu && cur_time - menu_klik < 500) {
if (_UP || _Down) {
_UP = 0;
_Down = 0;
}
else Menu++; // Меняем
if (Menu > 3) Menu = 1;
f_Mpush = 0;
}
else if (f_Mpush && !kn_menu && cur_time - menu_klik > 500) {
kalib = !kalib; // Включаем калибровку
f_Mpush = 0;
}
///////////////////////Проверка кнопки UP - АНТИДРЕБЕЗГ
if (D2_Read != f_Up) { //Если сигнал изменился
f_Up = !f_Up;
Up_dreb = cur_time;
}
if (kn_Up == D2_Read && cur_time - Up_dreb > 20) kn_Up = !D2_Read;
// Было нажатие
if (kn_Up && !state_Up) {
if (_UP || _Down) {
_UP = 0;
_Down = 0;
state_Up = 1;
}
else {
_UP = !_UP; // Меняем значение
state_Up = 1;
}
}
if (!kn_Up)state_Up = 0; // Отпустили
///////////////////////Проверка кнопки DOWN - АНТИДРЕБЕЗГ
if (D3_Read != f_Down) { //Если сигнал изменился
f_Down = !f_Down;
Down_dreb = cur_time;
}
if (kn_Down == D3_Read && cur_time - Down_dreb > 20) kn_Down = !D3_Read;
// Было нажатие
if (kn_Down && !state_Down) {
if (_UP || _Down) {
_UP = 0;
_Down = 0;
state_Down = 1;
}
else {
_Down = !_Down; // Меняем значение
state_Down = 1;
}
}
if (!kn_Down)state_Down = 0; // Отпустили
//////////////////////// С кнопками закончили продолжаем логику
if (!kalib)
{
if (Menu != temp_Menu) {
temp_Menu = Menu;
switch (Menu) {
case 1: D13_High; D14_Low; break;
case 2: D13_Low; D14_High; break;
case 3: D13_High; D14_High; break;
}
}
}
else {
if (cur_time - blink_time >= 300)
{
blink_time = cur_time;
switch (Menu) {
case 1: D13_Inv; D14_Low; break;
case 2: D13_Low; D14_Inv; break;
case 3: D13_Inv; D14_Inv; break;
}
}
}
/////////////////////////// Запуск 1го двигателя если " perem_X != 0 "
if (f_timX) {
if (_UP || _Down) {
if (Menu != 2) {
if (!sped_X) {
if (!kalib) { //Калибровка отк.
if (_UP && Shtora1 < max_Sht1) {//3592
RunX(0);
}
if (_Down && Shtora1 > 0) {
RunX(1);
}
}
else { //Калибровка вкл.
if (_UP) {
Shtora1 = 0;
RunX(0);
}
if (_Down) {
Shtora1 = 1;
RunX(1);
}
}
}
else if (sped_Xt > 0) {
--sped_Xt;
sped_X = sped_Xt;
f_timX = 0;
}
else {
--sped_X;
f_timX = 0;
}
}
}////
}
else {
f_run1X = 1;
no_runX = cur_time;
sbros = cur_time;
f_sbros = 1;
sped_Xt = uskor;
sped_X = 0; // для пропуска 1го тика
}
/////////////////Запуск 3го двигателя если " perem_Z != 0 "
//if (!kalib) {
if (f_timZ) {
if (_UP || _Down) {
if (Menu != 1) {
if (!sped_Z) {
if (!kalib)//Калибровка отк.
{
if (_Down && Shtora2 < max_Sht2) {//3475
RunZ(0);
}
if (_UP && Shtora2 > 0) {
RunZ(1);
}
}
else {//Калибровка Вкл.
if (_UP) {
Shtora2 = 0;
RunZ(0);
}
if (_Down) {
Shtora2 = 1;
RunZ(1);
}
}
}
else if (sped_Zt > 0) {
--sped_Zt;
sped_Z = sped_Zt;
f_timZ = 0;
}
}
else {
--sped_Z;
f_timZ = 0;
}
}////
}
else {
f_run1Z = 1;
no_runZ = cur_time;
sbros = cur_time;
f_sbros = 1;
sped_Zt = uskor;
sped_Z = 0; // для пропуска 1го тика
}
//Снимаем напряжение с катушек двигателя X
if (f_run1X && cur_time - no_runX >= 1000)// закончилось ли время
{
f_run1X = 0;
PORTB &= 0xF0;
}
//Снимаем напряжение с катушек двигателя Z
if (f_run1Z && cur_time - no_runZ >= 1000)// закончилось ли время
{
f_run1Z = 0;
PORTD &= 0xF;
}
}
Вот сделал инверсию попробуйте. Поповоду скорости в стр.72 - StartTimer1(Time_Closk, 2000); можете поиграться с числом, сейчас стоит 2 мс. на меньшем значении у меня стабильно не работает, а у Вас может и будет. По поводу калибровки: при первом входе он сам движется или после установки, при втором заходе тоже?
Скетч с инверсией проверил - с первой шторой: нажимаешь кнопку DOWN штора едет вверх, UP - вниз.
Со второй шторой тоже самое.
В режиме калибровки первая штора при нажатии DOWN едет вверх, UP-вниз. Вторая штора DOWN -вниз, UP-вверх.
Еще одна особенность появилась....кнопки UP и DOWN срабатывают со второго нажатия.
P/S похоже я Вас ввожу в заблуждение....первая штора пины:8 9 10 11, вторая штора пины:4 5 6 7
Т.е. получается, что до инверсии вторая штора работала правильно.
Проверил новый скетч.
В режиме калибровки всё отлично! шторы ездят правильно.
В рабочем режиме вторая штора работает, а с первой шторой происходит следущее:
1. При нажатии DOWN штора стоит.
2. При нажатии UP штора заматывается в барабан.
3. Если сначала в режиме калибровки штору опустить полностью и перейти в рабочий режим, то всё работает как надо.
P.S. Погонял шторы одновременно...когда подогнал высоту, все заработало как и хотелось.
Получается, что сначала нужно провести калибровку, а именно опустить шторы в режиме калибровки до нужного положения, выйти из режима калибровки и всё будет работать. Тогда имеет смысл запретить нажатие кнопок UP и DOWN если калибровка не была проведена, это будет один раз при первом запуске, потом когда положения штор и флаг калибровки(шторы уже калибровались) будут храниться в энергонезависимой памяти, разрешить нажатие кнопок.
34 стр. (kalib) присвойте 1, тоесть (bool kalib = 1;) тогда при запуске\перезапуске сразу будет включена калибровка и чтобы выйти изнеё нужно длинное нажатие
34 стр. (kalib) присвойте 1, тоесть (bool kalib = 1;) тогда при запуске\перезапуске сразу будет включена калибровка и чтобы выйти изнеё нужно длинное нажатие
Понял, а можете на 16 пин повесить пищалку? Я пробовал, но что-то не получается. Только для кнопки меню, на короткое нажатие - короткий сигнал, на длинное - длинный сигнал, ну и тон может отличаться.
Хотя если по мне так надобности в пищалке я не вижу потому что кнопка проверяется после отпукания - был клик или нажатие. Светодиоды прекрасно все показывают. При любом писке Вы все равно смотрите на диоды - а что же я включил.
Хотя если по мне так надобности в пищалке я не вижу потому что кнопка проверяется после отпукания - был клик или нажатие. Светодиоды прекрасно все показывают. При любом писке Вы все равно смотрите на диоды - а что же я включил.
Согласен, но всё же....привыкли уже.
Я так думаю ошибка как всегда в делеях?
Заработало!
Теперь осталось сохранять позиции штор в память. Такая реализация как у меня была подойдет?
Еще нужно как то высчитывать оставшееся количество шагов до нужной позиции и сохранять результат калибровки....после отключения/включения питания.
По поводу памяти я Вашу реализацию не разбирал но если работала то должна подойти. Алгоритм предлагаю такой:
1- При загрузке читаем с памяти и присваюем значение перемен. штора1 и штора2
2- После сброса напряжения на двигателе - проверяем изменилось ли значение если да переписуем
3- Не нужно вычислять никаких остатков, просто сохранять перем. штора1(2)
4- калибровку сохранять не нужно - 0 нам звестный также как максимум
Память имеет ограниченный ресурс перезаписи и на сколько Вам ее хватит, Это вопрос, как часто будете дергать штору?
Если что то в тойже CyberLib есть функция работы с помятью
Я по-поводу калибровки хочу спросить...когда мы даем питание на плату, как узнать, что калибровка уже проводилась и в ячейках записано значения положения штор? А если, к примеру, хранить в отдельной ячейке 1 - если калибровка проводилась и 0 - если не проводилась. И если 1, то считать значения из ячеек.
Вопрос: в каком месте скетча сделать запись того, что калибровка провелась?
Чтение и запись значений сделал вот так:
#include <EEPROM.h>
---------------------------------------------------------------------
// чтение
int EEPROM_int_read(int addr) {
byte raw[2];
for(byte i = 0; i < 2; i++) raw[i] = EEPROM.read(addr+i);
int &num = (int&)raw;
return num;
}
// запись
void EEPROM_int_write(int addr, int num) {
if (EEPROM_int_read(addr)!= num){//если сохраняемое отличается
byte raw[2];
(int&)raw = num;
for(byte i = 0; i < 2; i++) EEPROM.write(addr+i, raw[i]);
}
}
------------------------------------------------------------------------
void setup(){
if (EEPROM_int_read(4)!=1)
{
Shtora1=28900;
Shtora2=27500;
}
else
{
Shtora1 = EEPROM_int_read(0);
Shtora2 = EEPROM_int_read(2);
}
}
----------------------------------------------------------------------
void loop(){
//Снимаем напряжение с катушек двигателя X
if (f_run1X && cur_time - no_runX >= 1000)
{
f_run1X = 0;
PORTB &= 0xF0;
f_sbrosX = 1;
if (EEPROM_int_read(0)!=Shtora1)
{
EEPROM_int_write(0, Shtora1); // адрес 0 (+2 байта)
}
}
//Снимаем напряжение с катушек двигателя Z
if (f_run1Z && cur_time - no_runZ >= 1000)
{
f_run1Z = 0;
PORTD &= 0xF;
f_sbrosZ = 1;
if (EEPROM_int_read(2)!=Shtora2)
{
EEPROM_int_write(2, Shtora2); // адрес 0 (+2 байта)
}
}
}
Поповоду калибровки: Глобальная калибровка должна проводиться один раз после перезаписи Ардуино, Это Вы должны знать и без записи в память. Представим что вы провели калибровку и в памяти записали 1, после этого решили обновить программу а у Вас в памяти записано что калибровку проводить не надо, хотя по факту ее надо провести. Так что я не вижу как указать програме что она перепрошыта и нужно калибровать. А поточные - если будут пропуски двигателя и нужно будет подкоректировать штору то Вы будете сами видеть нужно или нет. А вот записать полжение шторы после ее движения - это можно. После перезапуска программа просто востановит положение штор.
#include <EEPROM.h>
---------------------------------------------------------------------
// чтение
int EEPROM_int_read(int addr) {
byte raw[2];
for(byte i = 0; i < 2; i++) raw[i] = EEPROM.read(addr+i);
int &num = (int&)raw;
return num;
}
// запись
void EEPROM_int_write(int addr, int num) {
if (EEPROM_int_read(addr)!= num){//если сохраняемое отличается
byte raw[2];
(int&)raw = num;
for(byte i = 0; i < 2; i++) EEPROM.write(addr+i, raw[i]);
}
}
------------------------------------------------------------------------
void setup(){
Shtora1 = EEPROM_int_read(0);
Shtora2 = EEPROM_int_read(2);
}
----------------------------------------------------------------------
void loop(){
//Снимаем напряжение с катушек двигателя X
if (f_run1X && cur_time - no_runX >= 1000)
{
f_run1X = 0;
PORTB &= 0xF0;
f_sbrosX = 1;
if (EEPROM_int_read(0)!=Shtora1)
{
EEPROM_int_write(0, Shtora1); // адрес 0 (+2 байта)
}
}
//Снимаем напряжение с катушек двигателя Z
if (f_run1Z && cur_time - no_runZ >= 1000)
{
f_run1Z = 0;
PORTD &= 0xF;
f_sbrosZ = 1;
if (EEPROM_int_read(2)!=Shtora2)
{
EEPROM_int_write(2, Shtora2); // адрес 0 (+2 байта)
}
}
}
А если для перевода в режим калибровке включить её с нажатыми кнопками или в сетапе считывать значение определённой ячейки. если там скажем 0xff или 0x00 то считаем что калибровки нет.
Я тоже об этом думал и не нашел решения, только появилось еще больше вопросов, поэтому согласен с Вами. Сейчас залью скетч и проверю. Можно Вас попросить, так сказать "на пальцах" объяснить мне, что означают все эти PORTB &= 0xF0, PORTD &= 0xF, n3 = 0xF0 & n3;//Маскируем PORTD = (PORTD & 0xF) | n3; //Очищаем старшие биты и пишем туда n3, DDRB = DDRB | B00101111;, PORTB = B00000000;, DDRD = DDRD | B11110000;,
PORTD = B00000000;//;
Если в остальном еще можно разобраться, то это для меня темный лес...
Похоже действительно, запись о калибровке не нужна. Сейчас проверил, ставил шторы в разных положениях и отключал питание, после включения все работает как надо, шторы в крайних положениях останавливаются.
А если для перевода в режим калибровке включить её с нажатыми кнопками или в сетапе считывать значение определённой ячейки. если там скажем 0xff или 0x00 то считаем что калибровки нет.
Установить или прочитать это не проблема, Проблема состоит в ее ипользовании - выше я описал.
ИМХО без наличия ООС точное определение положения шторы невозможно. Вот если бы концевики. или по току моторчика определять крайние положения... Но это так - мысли вслух...
Было бы интересно посмотреть видео с работой устройства когда будет всё готово.
ИМХО без наличия ООС точное определение положения шторы невозможно. Вот если бы концевики. или по току моторчика определять крайние положения... Но это так - мысли вслух...
Было бы интересно посмотреть видео с работой устройства когда будет всё готово.
Это еще до переделки, у меня моторы не хотели работать одновременно, а по-одному работали практически так же, только чуть медленнее. Сейчас вообще всё работает изумительно!
Может завтра пересниму....главное не забыть телефон горизонтально держать :)
Сначала хочу Вас поблагодарить! Без Вашей помощи был бы у меня коряво работающий скетч....а сейчас я просто ненарадуюсь :) Спасибо огромное!
Ну а теперь .....у меня в зале окно эркер....
Там установлены 3 шторки. Вас не затруднит переделать этот скетч под Мегу на 3 мотора?
Особенности: на 1 и 3 шторах моторы установлены так же как и в этом скетче, а у 2-ой шторы так же как у 3-ей.
Воистину человеческой наглости нет предела, но без Вашей помощи я еще полгода буду учиться моргать светодиодом, а шторы хочется закончить уже сейчас.
Ладно попробую, только Меги у меня нет испытувать будете Вы
Я завтра попробую переделать часть скетча по аналогии, я так понимаю нужно добавить все как для Z только с Y? Плюс меню увеличить на 1, добавить светодиод.....ну а моторы вращать уже мне не по силам. А еще нужно с пинами определиться...
Кстати, никогда не игрался с шаговыми двигателями, но почитав в интернете возникла следующая мысль - правильно ли я понял, что если взять два двигателя и подключить их парраллельно но с распиновкой у одного в порядке 1-2-3-4 а у другого 4-3-2-1 то мы получим одновременно работающие двигатели крутящиеся в противоположные стороны?
Если это так, то можно было бы взять 3 мосфета, и ими включать и выключать нужные двигатели, подключенные параллельно, а всё управление останется на 4х выводах. ведь ситуация при которой одна штора опускается, а другая поднимается - не предусмотрена ТЗ?
Кстати, никогда не игрался с шаговыми двигателями, но почитав в интернете возникла следующая мысль - правильно ли я понял, что если взять два двигателя и подключить их парраллельно но с распиновкой у одного в порядке 1-2-3-4 а у другого 4-3-2-1 то мы получим одновременно работающие двигатели крутящиеся в противоположные стороны?
Если это так, то можно было бы взять 3 мосфета, и ими включать и выключать нужные двигатели, подключенные параллельно, а всё управление останется на 4х выводах. ведь ситуация при которой одна штора опускается, а другая поднимается - не предусмотрена ТЗ?
На мой взгляд в этом есть зерно. Их не обезтельно включать навстречу, пусть крутят и паралельно.
Я завтра попробую переделать часть скетча по аналогии, я так понимаю нужно добавить все как для Z только с Y? Плюс меню увеличить на 1, добавить светодиод.....ну а моторы вращать уже мне не по силам. А еще нужно с пинами определиться...
Так пойдет? Я просто не знаю, может один порт управлять двумя моторами.
Я еще ничего не подключал, поэтому пока не критично.
И вот изменил скетч, поправьте если что не так. (что не смог сделать я отметил /////////////////////////)
//********** (РЕЖИМ 1-ШАГ) Крутим с помощью сдвига --рабочая - крутит туда сюда без потери шагов - ускоряет - отключает катушки после бездействия
//PORTB - 8, 9, 10, 11 - Шаговик. && 12-кнопка Menu \ 13-Светодиод 1й штор.
//PORTD - 4, 5, 6, 7 - Шаговик. && 2-кнопка UP \ 3-кнопка DOWN
// А0-Светодиод 2й штор..
#include <EEPROM.h>
#include <CyberLib.h>
#define uskor 3 //Задаем ускорение
//Здесь устанавливаем максимальное кол. шагов для штор
#define max_Sht1 28900
#define max_Sht2 30500
#define max_Sht3 28900
byte n1 = 1;// Сдвигаем 1 бит
byte n3 = 0x10;
bool f_timX = 0;
bool f_timY = 0;
bool f_timZ = 0;
byte sped_Xt = uskor;//Начальная скорость
byte sped_X = 0; //Ускорение
byte sped_Yt = uskor;//Начальная скорость
byte sped_Y = 0; //Ускорение
byte sped_Zt = uskor;//Начальная скорость
byte sped_Z = 0; //Ускорение
bool f_run1X = 0;//Сброс после остановки 2 переменные.
unsigned long no_runX; //Переменная для прошедшего периода
bool f_run1Y = 0;//Сброс после остановки 2 переменные.
unsigned long no_runY; //Переменная для прошедшего периода
bool f_run1Z = 0;//Сброс после остановки 2 переменные.
unsigned long no_runZ; //Переменная для прошедшего периода
// Переменные для кн.Menu
bool kn_menu;
bool f_menu;
bool f_Mpush;
bool f_Md;
uint8_t Menu = 1;
uint8_t temp_Menu;
bool kalib;
unsigned long menu_dreb;
unsigned long menu_klik;
// Переменные для кн.Up
bool kn_Up;
bool f_Up;
bool state_Up;
bool _UP;
uint32_t Up_dreb;
// Переменные для кн.Down
bool kn_Down;
bool f_Down;
bool state_Down;
bool _Down;
uint32_t Down_dreb;
//сбрасываем UP\Down
bool f_sbrosZ = 1;
bool f_sbrosY = 1;
bool f_sbrosX = 1;
uint32_t cur_time;//Миллис читаем один раз
uint32_t blink_time;//Мигаем в режиме калибровки
int Shtora1;
int Shtora2;
int Shtora3;
const int ton = 8;//пищалка
// чтение
int EEPROM_int_read(int addr) {
byte raw[2];
for(byte i = 0; i < 2; i++) raw[i] = EEPROM.read(addr+i);
int &num = (int&)raw;
return num;
}
// запись
void EEPROM_int_write(int addr, int num) {
if (EEPROM_int_read(addr)!= num){//если сохраняемое отличается
byte raw[2];
(int&)raw = num;
for(byte i = 0; i < 2; i++) EEPROM.write(addr+i, raw[i]);
}
}
void setup() {
// DDRB пин, 8,9,10,11 - Шаговик, pin 12- вход, 13- Выход
////////////////////////////////////////////////////////////////////// DDRB = DDRB | B00101111;
// pin 8,9,10,11,13 - выход в 0 а входы pin 12, - 0
////////////////////////////////////////////////////////////////////// PORTB = B00000000;
// DDRD, подключенный к двигателю pin 4,5,6,7 как выход,pin2,3 Выход
////////////////////////////////////////////////////////////////////// DDRD = DDRD | B11110000;
// pin 4,5,6,7 - выход в 0 а входы pin 2,3 - 0
////////////////////////////////////////////////////////////////////// PORTD = B00000000;//;
D2_In; //2-кнопка UP
D3_In; //3-кнопка DOWN
D4_In; //4-кнопка MENU
D5_Out; // Led_1
D5_Low;
D6_Out; // Led_2
D6_Low;
D7_Out; // Led_3
D7_Low;
pinMode(ton,OUTPUT);//пищалка
//Serial.begin(9600);
// Инициализировать TIMER1
StartTimer1(Time_Closk, 2200);
Shtora1 = EEPROM_int_read(0);
Shtora2 = EEPROM_int_read(2);
Shtora3 = EEPROM_int_read(4);
}
void Beep() //короткий звук, переключение шторы
{
tone(ton,500,500);
delay(200);
noTone(ton);
}
void Beep_long() //длинный звук, вход и выход из режима калибровки "0"
{
tone(ton,200,1000);
delay(200);
noTone(ton);
}
void Time_Closk() // Функция прерывания таймера
{
f_timX = 1;
f_timY = 1;
f_timZ = 1;
}
//Функция вращения dvigatel 1
void RunX (bool perem_X)
{
f_sbrosX = 0;
f_timX = 0;
if (perem_X) {
n1 = (n1 >> 1) | (n1 << 3); //Сдвигаем
--Shtora1;
}
else {
n1 = (n1 << 1) | (n1 >> 3); //Сдвигаем
++Shtora1;
}
///////////////////////////////////////////////////// n1 = 0x0F & n1; //Маскируем кнопки
///////////////////////////////////////////////////// PORTB = (PORTB & 0xF0) | n1; //Очищаем Младшие биты и пишем туда n1
}
//Функция dvigatel 2
void RunY (bool perem_Y)
{
f_sbrosY = 0;
f_timY = 0;
if (perem_Y) {
n3 = (n3 >> 1) | (n3 << 3); //Сдвигаем
--Shtora2;
}
else {
n3 = (n3 << 1) | (n3 >> 3); //Сдвигаем
++Shtora2;
}
/////////////////////////////////////////////////// n3 = 0xF0 & n3;//Маскируем
/////////////////////////////////////////////////// PORTD = (PORTD & 0xF) | n3; //Очищаем старшие биты и пишем туда n3
}
//Функция dvigatel 3
void RunZ (bool perem_Z)
{
f_sbrosZ = 0;
f_timZ = 0;
if (perem_Z) {
n3 = (n3 >> 1) | (n3 << 3); //Сдвигаем
--Shtora3;
}
else {
n3 = (n3 << 1) | (n3 >> 3); //Сдвигаем
++Shtora3;
}
////////////////////////////////////////////////// n3 = 0xF0 & n3;//Маскируем
////////////////////////////////////////////////// PORTD = (PORTD & 0xF) | n3; //Очищаем старшие биты и пишем туда n3
}
void loop() {
cur_time = millis();
///////////////////Проверка кнопки МЕНЮ - АНТИДРЕБЕЗГ
if (D4_Read && !f_menu)
{
menu_dreb = cur_time;
f_menu = 1;
}
if (!D4_Read)
{
kn_menu = 0;
f_menu = 0;
}
if (f_menu && cur_time - menu_dreb >= 20)
{
kn_menu = 1;
if (!f_Mpush) {
menu_klik = cur_time;
f_Mpush = 1;
}
}
//Был клик
if (f_Mpush && !kn_menu && cur_time - menu_klik < 1000) {
if (_UP || _Down) {
_UP = 0;
_Down = 0;
}
else Menu++, Beep(); // Меняем
if (Menu > 4) Menu = 1;
f_Mpush = 0;
}
//Было нажатие
else if (f_Mpush && !kn_menu && cur_time - menu_klik > 1000) {
Beep_long();
kalib = !kalib; // Включаем калибровку
f_Mpush = 0;
} ///////////////////////Проверка кнопки UP - АНТИДРЕБЕЗГ
if (D2_Read != f_Up) { //Если сигнал изменился
f_Up = !f_Up;
Up_dreb = cur_time;
}
if (kn_Up == D2_Read && cur_time - Up_dreb > 20) kn_Up = !D2_Read;
// Было нажатие
if (kn_Up && !state_Up) {
if (_UP || _Down) {
_UP = 0;
_Down = 0;
state_Up = 1;
}
else {
_UP = !_UP; // Меняем значение
state_Up = 1;
}
}
if (!kn_Up)state_Up = 0; // Отпустили
///////////////////////Проверка кнопки DOWN - АНТИДРЕБЕЗГ
if (D3_Read != f_Down) { //Если сигнал изменился
f_Down = !f_Down;
Down_dreb = cur_time;
}
if (kn_Down == D3_Read && cur_time - Down_dreb > 20) kn_Down = !D3_Read;
// Было нажатие
if (kn_Down && !state_Down) {
if (_UP || _Down) {
_UP = 0;
_Down = 0;
state_Down = 1;
}
else {
_Down = !_Down; // Меняем значение
state_Down = 1;
}
}
if (!kn_Down)state_Down = 0; // Отпустили
//////////////////////// С кнопками закончили продолжаем логику
if (!kalib)
{
if (Menu != temp_Menu) {
temp_Menu = Menu;
switch (Menu) {
case 1: D5_High; D6_Low; D7_Low; break;
case 2: D5_Low; D6_High; D7_Low; break;
case 3: D5_Low; D6_Low; D7_High; break;
case 4: D5_High; D6_High; D7_High; break;
}
}
}
else {
if (cur_time - blink_time >= 300)
{
blink_time = cur_time;
switch (Menu) {
case 1: D5_Inv; D6_Low; D7_Low; break;
case 2: D5_Low; D6_Inv; D7_Low; break;
case 3: D5_Low; D6_Low; D7_Inv break;
case 4: D5_Inv; D6_Inv; D7_Inv break;
}
}
}
/////////////////////////// Запуск 1го двигателя если " perem_X != 0 "
if (f_timX) {
if (_UP || _Down) {
if (Menu != 1) {
if (!sped_X) {
if (!kalib) { //Калибровка отк.
if (_Down && Shtora1 < max_Sht1) {
RunX(0);
}
if (_UP && Shtora1 > 0) {
RunX(1);
}
}
else { //Калибровка вкл.
if (_Down) {
Shtora1 = 0;
RunX(0);
}
if (_UP) {
Shtora1 = 1;
RunX(1);
}
}
//Три поверки для разгона
if (sped_Xt > 0) {
--sped_Xt;
sped_X = sped_Xt;
// f_timX = 0;
}
}
else {
--sped_X;
f_timX = 0;
}
}
}////
else {
sped_Xt = uskor;
sped_X = 0;
}
}
else { //Для снятия напряжения
f_run1X = 1;
no_runX = cur_time;
}
/////////////////Запуск 2го двигателя если " perem_Y != 0 "
if (f_timY) {
if (_UP || _Down) {
if (Menu != 2) {
if (!sped_Y) {
if (!kalib)//Калибровка отк.
{
if (_UP && Shtora2 < max_Sht2) {
RunY(0);
}
if (_Down && Shtora2 > 0) {
RunY(1);
}
}
else {//Калибровка Вкл.
if (_UP) {
Shtora2 = 0;
RunY(0);
}
if (_Down) {
Shtora2 = 1;
RunY(1);
}
}
//Три поверки для разгона
if (sped_Yt > 0) {
--sped_Yt;
sped_Y = sped_Yt;
f_timY = 0;
}
}
else {
--sped_Y;
f_timY = 0;
}
}
}////
else {
sped_Yt = uskor;
sped_Y = 0;
}
}
else { //Для снятия напряжения
f_run1Y = 1;
no_runY = cur_time;
}
/////////////////Запуск 3го двигателя если " perem_Z != 0 "
if (f_timZ) {
if (_UP || _Down) {
if (Menu != 3) {
if (!sped_Z) {
if (!kalib)//Калибровка отк.
{
if (_UP && Shtora3 < max_Sht3) {
RunZ(0);
}
if (_Down && Shtora3 > 0) {
RunZ(1);
}
}
else {//Калибровка Вкл.
if (_UP) {
Shtora3 = 0;
RunZ(0);
}
if (_Down) {
Shtora3 = 1;
RunZ(1);
}
}
//Три поверки для разгона
if (sped_Zt > 0) {
--sped_Zt;
sped_Z = sped_Zt;
f_timZ = 0;
}
}
else {
--sped_Z;
f_timZ = 0;
}
}
}////
else {
sped_Zt = uskor;
sped_Z = 0;
}
}
else { //Для снятия напряжения
f_run1Z = 1;
no_runZ = cur_time;
}
//Возврат по достижению конечной точки
if (f_sbrosZ && f_sbrosY && f_sbrosX) {
_UP = 0;
_Down = 0;
}
//Снимаем напряжение с катушек двигателя X
if (f_run1X && cur_time - no_runX >= 1000)
{
f_run1X = 0;
////////////////////////////////////////////////////////////// PORTB &= 0xF0;
f_sbrosX = 1;
if (EEPROM_int_read(0)!=Shtora1)
{
EEPROM_int_write(0, Shtora1); // адрес 0 (+2 байта)
}
}
//Снимаем напряжение с катушек двигателя Y
if (f_run1Y && cur_time - no_runY >= 1000)
{
f_run1Y = 0;
///////////////////////////////////////////////////////////// PORTD &= 0xF;
f_sbrosY = 1;
if (EEPROM_int_read(2)!=Shtora2)
{
EEPROM_int_write(2, Shtora2); // адрес 2 (+2 байта)
}
}
//Снимаем напряжение с катушек двигателя Z
if (f_run1Z && cur_time - no_runZ >= 1000)
{
f_run1Z = 0;
/////////////////////////////////////////////////////////// PORTD &= 0xF;
f_sbrosZ = 1;
if (EEPROM_int_read(4)!=Shtora3)
{
EEPROM_int_write(4, Shtora3); // адрес 4 (+2 байта)
}
}
}
Я просто не знаю, может один порт управлять двумя моторами.
а почему бы и нет? Он же через ULN работает.
Кстати, ИМХО, есть смысл провести эксперимент - подключить два мотора, как я писал выше. Что бы они от одного порта крутились в разные стороны. Тогда будет достаточно 10 лап на 3 кнопки, 3 мотора и 4 вывода управления
Кстати, ИМХО, есть смысл провести эксперимент - подключить два мотора, как я писал выше. Что бы они от одного порта крутились в разные стороны. Тогда будет достаточно 10 лап на 3 кнопки, 3 мотора и 4 вывода управления
Проверил Ваше предположение....верно, можно все три мотора подключить к четырем пинам по схеме 1-2-3-4, причем один мотор подключил 4-3-2-1....нажимаешь кнопку "вправо" крутятся два в право, а один влево и наоборот. Удерживая вращение, снимал перемычку на драйвере (как Вы и сказали типа мосфетом дал команду), нужный мотор останавливался, остальные крутятся.
Получается, что нужно дать команду на вращение и мосфетами выбирать нужный мотор или все сразу. А по мин или макс положению выключать.
Давайте пока попробуем на Мега, которой у меня нет и испытать не могу
Испытывал на столе, моторы разложил как они должны стоять на шторах. Сначала была небольшая путаница, моторы крутились не в те стороны какие нужно....подключал вот так:
//PORTA - к двигателю X (22,23,24,25,) - как выход
//PORTC - к двигателю Y,Z (37,36,35,34) (33,32,31,30) как выход
Потом переподключил вот так:
//PORTA - к двигателю X (25,24,23,22,) - как выход
//PORTC - к двигателю Y,Z (37,36,35,34) (30,31,32,33) как выход
Моторы стали крутиться в нужную сторону, но Y - это 3 мотор, а Z - 2 мотор.
В принципе можно "забить" на это, подключить как нужно, и пофиг как это в скетче называется. В комментарии написать, что Z - второй мотор (30,31,32,33), Y - третий мотор (37,36,35,34).
ИМХО надо или класс делать, или структуру. А их них массив - размерностью в количество двигателей.
тогда
switch (Menu) {
case 1:
if (_Down)Shtora1++;
if (_UP)Shtora1--;
break;
case 2:
if (_Down)Shtora2++;
if (_UP)Shtora2--;
break;
case 3:
if (_Down)Shtora3++;
if (_UP)Shtora3--;
break;
case 4:
if (_Down) {
if (_Mofs1)Shtora1++;
if (_Mofs2)Shtora2++;
if (_Mofs3)Shtora3++;
}
if (_UP) {
if (_Mofs1)Shtora1--;
if (_Mofs2)Shtora2--;
if (_Mofs3)Shtora3--;
}
break;
}
Будет выглядеть как
for( int i = 0; i < MotorCount; i++)
{
if( motorArr[i].State == HIGH )
{
motorArr[i].Shtora += direction; // direction 1 в одну сторону, -1 в другую.
}
}
А оба зачем? Две шторы одновременно смысла нет калибровать. У нас самое главное не работает.....моторы не крутятся и кренка сильно греется!!! В симуляторе светодиоды бегают прикольно, а реальная сборка работать не хочет. Первый скетч работает изумительно, для режима калибровки самое то....пока держишь кнопку - мотор крутится, отпустил - остановился. Вот этот скетч.
По-поводу калибровки я считаю, что правильней калибровать "0" вверху, т.е. начальное положение из которого штора разматывается и чтобы штора не замоталась в барабан.
Вот скетч провери его на живой ардуине, правда на однм двигателе, крутит отключает, ничего не греется. Проблему скорости давал Сериал, пришлось его удалить. В принцепе он нужен только для настройки. А так пока искал причину по скорости то таймер поменял и так помелочам. Ммаксимальную высоту будете ставить в самом начале _ там написано
Добрый вечер. Спасибо, сейчас буду проверять. Я тут немного со схемой повозился, 1 светодиод повесил на 14 пин, 2 светодиод на 15 пин, а на 16 пин прицепил пищалку(при навигации по меню удобно). Можно добавить в скетч?
Проверил скетч...
Со второй шторой всё получилось хорошо, методом тыка настроил высоту - 27500. Ездит хорошо. Полное закрытие или открытие занимает 55 секунд. Немножко не понял в режиме калибровки....как только в него входишь, штору сразу затягивает в барабан, кнопками UP и DOWN возвращаешь на нужное место. С моргающим светодиодом прикольно!
С первой шторой не получится настроить, потому что она должна работать в обратном порядке...моторы стоят не симметрично, здесь нужно инверсию делать.
Вот сделал инверсию попробуйте. Поповоду скорости в стр.72 - StartTimer1(Time_Closk, 2000); можете поиграться с числом, сейчас стоит 2 мс. на меньшем значении у меня стабильно не работает, а у Вас может и будет. По поводу калибровки: при первом входе он сам движется или после установки, при втором заходе тоже?
При первом входе точно движется, сейчас проверю еще пару раз.
Вот сделал инверсию попробуйте. Поповоду скорости в стр.72 - StartTimer1(Time_Closk, 2000); можете поиграться с числом, сейчас стоит 2 мс. на меньшем значении у меня стабильно не работает, а у Вас может и будет. По поводу калибровки: при первом входе он сам движется или после установки, при втором заходе тоже?
Скетч с инверсией проверил - с первой шторой: нажимаешь кнопку DOWN штора едет вверх, UP - вниз.
Со второй шторой тоже самое.
В режиме калибровки первая штора при нажатии DOWN едет вверх, UP-вниз. Вторая штора DOWN -вниз, UP-вверх.
Еще одна особенность появилась....кнопки UP и DOWN срабатывают со второго нажатия.
P/S похоже я Вас ввожу в заблуждение....первая штора пины:8 9 10 11, вторая штора пины:4 5 6 7
Т.е. получается, что до инверсии вторая штора работала правильно.
По поводу проблемы с калибровкой, у себя (на живой плате и в симуляторе) не заметил. Вот проверяйте с инверсией
Проверил новый скетч.
В режиме калибровки всё отлично! шторы ездят правильно.
В рабочем режиме вторая штора работает, а с первой шторой происходит следущее:
1. При нажатии DOWN штора стоит.
2. При нажатии UP штора заматывается в барабан.
3. Если сначала в режиме калибровки штору опустить полностью и перейти в рабочий режим, то всё работает как надо.
P.S. Погонял шторы одновременно...когда подогнал высоту, все заработало как и хотелось.
Получается, что сначала нужно провести калибровку, а именно опустить шторы в режиме калибровки до нужного положения, выйти из режима калибровки и всё будет работать. Тогда имеет смысл запретить нажатие кнопок UP и DOWN если калибровка не была проведена, это будет один раз при первом запуске, потом когда положения штор и флаг калибровки(шторы уже калибровались) будут храниться в энергонезависимой памяти, разрешить нажатие кнопок.
34 стр. (kalib) присвойте 1, тоесть (bool kalib = 1;) тогда при запуске\перезапуске сразу будет включена калибровка и чтобы выйти изнеё нужно длинное нажатие
34 стр. (kalib) присвойте 1, тоесть (bool kalib = 1;) тогда при запуске\перезапуске сразу будет включена калибровка и чтобы выйти изнеё нужно длинное нажатие
Понял, а можете на 16 пин повесить пищалку? Я пробовал, но что-то не получается. Только для кнопки меню, на короткое нажатие - короткий сигнал, на длинное - длинный сигнал, ну и тон может отличаться.
Канешно могу, но мы же с Вами договаривались вместе писать код. Общую логику я вывел а такие дополнения подключайтесь и Вы!
Канешно могу, но мы же с Вами договаривались вместе писать код. Общую логику я вывел а такие дополнения подключайтесь и Вы!
Я пробовал вот так:
И вот здесь указал функцию:
Но так работать не хочет....где я ошибаюсь?
Хотя если по мне так надобности в пищалке я не вижу потому что кнопка проверяется после отпукания - был клик или нажатие. Светодиоды прекрасно все показывают. При любом писке Вы все равно смотрите на диоды - а что же я включил.
Хотя если по мне так надобности в пищалке я не вижу потому что кнопка проверяется после отпукания - был клик или нажатие. Светодиоды прекрасно все показывают. При любом писке Вы все равно смотрите на диоды - а что же я включил.
Согласен, но всё же....привыкли уже.
Я так думаю ошибка как всегда в делеях?
Если пин ton Вы настроили как ВЫХОД, то почти угадали. А еще в библиотеке CyberLib есть встроеная функция beep, можно почитать и вызывать ее
Заработало!
Теперь осталось сохранять позиции штор в память. Такая реализация как у меня была подойдет?
Еще нужно как то высчитывать оставшееся количество шагов до нужной позиции и сохранять результат калибровки....после отключения/включения питания.
Я по-поводу калибровки хочу спросить...когда мы даем питание на плату, как узнать, что калибровка уже проводилась и в ячейках записано значения положения штор? А если, к примеру, хранить в отдельной ячейке 1 - если калибровка проводилась и 0 - если не проводилась. И если 1, то считать значения из ячеек.
Вопрос: в каком месте скетча сделать запись того, что калибровка провелась?
Чтение и запись значений сделал вот так:
Поповоду калибровки: Глобальная калибровка должна проводиться один раз после перезаписи Ардуино, Это Вы должны знать и без записи в память. Представим что вы провели калибровку и в памяти записали 1, после этого решили обновить программу а у Вас в памяти записано что калибровку проводить не надо, хотя по факту ее надо провести. Так что я не вижу как указать програме что она перепрошыта и нужно калибровать. А поточные - если будут пропуски двигателя и нужно будет подкоректировать штору то Вы будете сами видеть нужно или нет. А вот записать полжение шторы после ее движения - это можно. После перезапуска программа просто востановит положение штор.
А если для перевода в режим калибровке включить её с нажатыми кнопками или в сетапе считывать значение определённой ячейки. если там скажем 0xff или 0x00 то считаем что калибровки нет.
Я тоже об этом думал и не нашел решения, только появилось еще больше вопросов, поэтому согласен с Вами. Сейчас залью скетч и проверю. Можно Вас попросить, так сказать "на пальцах" объяснить мне, что означают все эти PORTB &= 0xF0, PORTD &= 0xF, n3 = 0xF0 & n3;//Маскируем PORTD = (PORTD & 0xF) | n3; //Очищаем старшие биты и пишем туда n3, DDRB = DDRB | B00101111;, PORTB = B00000000;, DDRD = DDRD | B11110000;,
Если в остальном еще можно разобраться, то это для меня темный лес...
Похоже действительно, запись о калибровке не нужна. Сейчас проверил, ставил шторы в разных положениях и отключал питание, после включения все работает как надо, шторы в крайних положениях останавливаются.
А если для перевода в режим калибровке включить её с нажатыми кнопками или в сетапе считывать значение определённой ячейки. если там скажем 0xff или 0x00 то считаем что калибровки нет.
Установить или прочитать это не проблема, Проблема состоит в ее ипользовании - выше я описал.
ИМХО без наличия ООС точное определение положения шторы невозможно. Вот если бы концевики. или по току моторчика определять крайние положения... Но это так - мысли вслух...
Было бы интересно посмотреть видео с работой устройства когда будет всё готово.
ИМХО без наличия ООС точное определение положения шторы невозможно. Вот если бы концевики. или по току моторчика определять крайние положения... Но это так - мысли вслух...
Было бы интересно посмотреть видео с работой устройства когда будет всё готово.
Видео есть в этой теме http://arduino.ru/forum/proekty/rulonnye-shtory-na-arduino
Это еще до переделки, у меня моторы не хотели работать одновременно, а по-одному работали практически так же, только чуть медленнее. Сейчас вообще всё работает изумительно!
Может завтра пересниму....главное не забыть телефон горизонтально держать :)
На пальцах не получится да и не все сразу как пример можете посмотреть
http://arduino.net.ua/Arduino_articles/Opisanie%20jazyka%20Arduino%20na%20russkom%20jazyke/Manipuljacii%20s%20portami/
http://cxem.net/arduino/arduino6.php
На пальцах не получится да и не все сразу как пример можете посмотреть
http://arduino.net.ua/Arduino_articles/Opisanie%20jazyka%20Arduino%20na%20russkom%20jazyke/Manipuljacii%20s%20portami/
http://cxem.net/arduino/arduino6.php
Спасибо. Я это уже читал, похоже пока не пощупаешь фиг научишься....
На пальцах не получится да и не все сразу как пример можете посмотреть
Я Вам еще не сильно надоел?
Посмотрел - с учтётом монументальности конструкции - склоняюсь ко мнению что дрейф будет минимальным и ООС можно принебречь.
PS. Очень понравилось качество изготовления.
Посмотрел - с учтётом монументальности конструкции - склоняюсь ко мнению что дрейф будет минимальным и ООС можно принебречь.
PS. Очень понравилось качество изготовления.
Спасибо! Старался, чтобы выглядело не очень колхозно....еще бы моторчики спрятать под колпачком, но для этого 3д принтер бы.....
Да тоже посмотрел - сделано акуратно!
Да тоже посмотрел - сделано акуратно!
Спасибо! Можно Вас еще подаставать?
Ну если смогу то помогу.
Ну если смогу то помогу.
Сначала хочу Вас поблагодарить! Без Вашей помощи был бы у меня коряво работающий скетч....а сейчас я просто ненарадуюсь :) Спасибо огромное!
Ну а теперь .....у меня в зале окно эркер....
Там установлены 3 шторки. Вас не затруднит переделать этот скетч под Мегу на 3 мотора?
Особенности: на 1 и 3 шторах моторы установлены так же как и в этом скетче, а у 2-ой шторы так же как у 3-ей.
Воистину человеческой наглости нет предела, но без Вашей помощи я еще полгода буду учиться моргать светодиодом, а шторы хочется закончить уже сейчас.
Ладно попробую, только Меги у меня нет испытувать будете Вы
Ладно попробую, только Меги у меня нет испытувать будете Вы
Я завтра попробую переделать часть скетча по аналогии, я так понимаю нужно добавить все как для Z только с Y? Плюс меню увеличить на 1, добавить светодиод.....ну а моторы вращать уже мне не по силам. А еще нужно с пинами определиться...
Кстати, никогда не игрался с шаговыми двигателями, но почитав в интернете возникла следующая мысль - правильно ли я понял, что если взять два двигателя и подключить их парраллельно но с распиновкой у одного в порядке 1-2-3-4 а у другого 4-3-2-1 то мы получим одновременно работающие двигатели крутящиеся в противоположные стороны?
Если это так, то можно было бы взять 3 мосфета, и ими включать и выключать нужные двигатели, подключенные параллельно, а всё управление останется на 4х выводах. ведь ситуация при которой одна штора опускается, а другая поднимается - не предусмотрена ТЗ?
Кстати, никогда не игрался с шаговыми двигателями, но почитав в интернете возникла следующая мысль - правильно ли я понял, что если взять два двигателя и подключить их парраллельно но с распиновкой у одного в порядке 1-2-3-4 а у другого 4-3-2-1 то мы получим одновременно работающие двигатели крутящиеся в противоположные стороны?
Если это так, то можно было бы взять 3 мосфета, и ими включать и выключать нужные двигатели, подключенные параллельно, а всё управление останется на 4х выводах. ведь ситуация при которой одна штора опускается, а другая поднимается - не предусмотрена ТЗ?
На мой взгляд в этом есть зерно. Их не обезтельно включать навстречу, пусть крутят и паралельно.
Я завтра попробую переделать часть скетча по аналогии, я так понимаю нужно добавить все как для Z только с Y? Плюс меню увеличить на 1, добавить светодиод.....ну а моторы вращать уже мне не по силам. А еще нужно с пинами определиться...
Кнопки: 2 - UP, 3 - DOWN, 4 - MENU
Светодиоды: 5 - Led1, 6 - Led2, 7 - Led3
Пищалка: 8 - Ton
Моторы: PORTA, PORTC, PORTL
Так пойдет? Я просто не знаю, может один порт управлять двумя моторами.
Я еще ничего не подключал, поэтому пока не критично.
И вот изменил скетч, поправьте если что не так. (что не смог сделать я отметил /////////////////////////)
Я просто не знаю, может один порт управлять двумя моторами.
а почему бы и нет? Он же через ULN работает.
Кстати, ИМХО, есть смысл провести эксперимент - подключить два мотора, как я писал выше. Что бы они от одного порта крутились в разные стороны. Тогда будет достаточно 10 лап на 3 кнопки, 3 мотора и 4 вывода управления
Кстати, ИМХО, есть смысл провести эксперимент - подключить два мотора, как я писал выше. Что бы они от одного порта крутились в разные стороны. Тогда будет достаточно 10 лап на 3 кнопки, 3 мотора и 4 вывода управления
Проверил Ваше предположение....верно, можно все три мотора подключить к четырем пинам по схеме 1-2-3-4, причем один мотор подключил 4-3-2-1....нажимаешь кнопку "вправо" крутятся два в право, а один влево и наоборот. Удерживая вращение, снимал перемычку на драйвере (как Вы и сказали типа мосфетом дал команду), нужный мотор останавливался, остальные крутятся.
Получается, что нужно дать команду на вращение и мосфетами выбирать нужный мотор или все сразу. А по мин или макс положению выключать.
Да. Мне кажется что так и код будет проще, и ардуинку подешевле можно использовать.
Да. Мне кажется что так и код будет проще, и ардуинку подешевле можно использовать.
Осталось придумать как считать шаги каждого мотора отдельно, шторы могут находиться в разных положениях, а двигаться нужно к примеру в мах.
Да. Мне кажется что так и код будет проще, и ардуинку подешевле можно использовать.
Осталось придумать как считать шаги каждого мотора отдельно, шторы могут находиться в разных положениях, а двигаться нужно к примеру в мах.
Давайте пока попробуем на Мега, которой у меня нет и испытать не могу
Давайте пока попробуем на Мега, которой у меня нет и испытать не могу
Испытывал на столе, моторы разложил как они должны стоять на шторах. Сначала была небольшая путаница, моторы крутились не в те стороны какие нужно....подключал вот так:
Да. Мне кажется что так и код будет проще, и ардуинку подешевле можно использовать.
Вот попробовал - Сказать что код по проще это врядли а на ардуинке да выигруем. Если интересно то вот
ИМХО надо или класс делать, или структуру. А их них массив - размерностью в количество двигателей.
тогда
Будет выглядеть как