жена говорит, что ей нужна какая-то особая доска для кухни, в магазинах нет, придётся делать и, стоить это будет раз в пять больше, чем купить готовое )))
какие вектора? Что за бред?
Тут полное ЕЕ, он сначало на “перезагрузку” зачем-то уходил, потом решил на прерывание по смене состояния ходить “0х0А”, там каша масляная.
Вопрос решился в #4, но мы тут все наблюдаем поток сознания, сходил на канал Ютуб, посмотрел -
понятно, человек живет в им самим выдуманной реальности
Ну да))
Вот видишь тут ещё одному, все это покое не даёт, родственники штоли
Доброго дня, спасибо Вадиму, в данный момент мне этот код очень нужен, я пошел с другой стороны, взял плоттер Epson А1 формата, epson 7890, разобрал его, и сейчас уже собрал всю механику, стол, пришло время arduino, сейчас только начал вникать, хорошо, что есть от чего отталкиваться. Я правильно понимаю, что если этот скетч залить в arduino uno, подключить шаговик и энкодер, без кнопок и запустить, то при вращение энкодера шаговик должен работать? или нужно кнопками еще что-то включить? Но энкодер у меня соответственно будет Epson, с питанием от основной платы принтера, я так понимаю, нужно arduino подключить тоже от питания принтера, что бы у них общая земля была?
Да, все верно вы поняли, земля общая, а кнопки и джоййстик для удобства, энкодер все норм работает только закоменти строку плюс движения энкодера что бы принтер при прочистке не дергал напрасно шаговик, я уже попробовал в деле без чернил все работает, шаговик нужно ставить на 1/4 шага и далее подбирать милисекунды, я пока занят домашкой немного некогда показать все в деле и доделать станок как разгребу подробно дополню все.
У меня энкодер не принтовский так как припаевать провода к плате я не умею оставил паралельный и закрепил его с боку примерно такое фото.
Доброго дня всем форумчанам .
Продолжаю заниматься планшетным принтером .
за это время я проделал много опытов и не все получилось.
не получилось .
1.
сделать передачу от encoder к шаговому двигателю .чтобы оборот или шаг encoder соответствовал шагу stepper motor nema17 .
от этого все распечатки получаются с искажениями . на распечатках видно .
- не смог правильно задействовать кнопку pin концевика датчика начала и окончании бумаги .
в этом вопросе я изучал как ведет себя принтер и когда мне вручную нажимать и отпускать кнопку .
но для начала нужно доделать первый пункт дописать код .
Есть и хорошие новости .
код до настроек и для удобства использования принтера что я встроил работает без сбоев .
а это
два концевика Limit стола . джойстик для более точного подъезда стола . кнопка отправки на печать и обнуления encoder посредством reboot , и другого кода пропуска поиска бумаги и окончании печати и обнуления encoder . Работает.
Напомню .
схема состоит из платы mks DLC v2.0 контролер AVR 328 то есть
обычная arduino uno 328 . с нависными драйвером a4988
Encoder optical 600 PPR на оборот . на фото у принтера видно .
2 limit нормально закрытые .
arduino джойстик .
кнопки botton .
stepper motor nema 17.
и сам Принтер Hp Deskjet 2330
выбор пал на него так как это
Проект для меня. изучения работы этого станка и он пока прототип более глобального проекта .
Простой . проще только простой карандаш .
Дешевый брал на Авито 3 шт по 300 руб
Можно на нем использовать пигментные чернила .
Сам код почти не изменился
//Энкодер на пинах 2, 3. Используется внутренняя подтяжка.
volatile long int enc;
#include <avr/wdt.h> // Библиотека часть компилятора avr-gcc
#define ENABLE_PIN 8
#define limitPin 9
#define button1 6
#define button2 5
void setup(){
Serial.begin(115200);
pinMode(2,INPUT_PULLUP);
pinMode(3,INPUT_PULLUP);
pinMode(ENABLE_PIN , OUTPUT);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(9, INPUT_PULLUP);
pinMode(10, INPUT_PULLUP);
PCIFR=PCIF2; PCICR=1<<PCIE2; //разрешить прерывание
PCMSK2=1<<PCINT18 | 1<<PCINT19; //выбрать вход на котором сработает прерывание
}
uint32_t timer = 0;
void(* resetFunc) (void) = 0;
const int STEP_PIN = 4;
const int DIR_PIN = 7;
const int R360 = 200;
int T = 10;
int A = 0;
int ST = enc/3;
ISR(PCINT2_vect){
static char EncPrev=0; //предыдущее состояние энкодера
static char EncPrevPrev=0; //пред-предыдущее состояние энкодера
char EncCur = 0;
if(!(PIND & (1 << PD2))){EncCur = 1;} //опрос фазы 1 энкодера
if(!(PIND & (1 << PD3))){ EncCur |= 2;} //опрос фазы 2 энкодера
if(EncCur != EncPrev) //если состояние изменилось,
{ if(EncPrev == 3 && //если предыдущее состояние 3
EncCur != EncPrevPrev ) //и текущее и пред-предыдущее не равны,
{
if(EncCur == 2)
(enc++, digitalWrite(DIR_PIN, LOW), digitalWrite(ENABLE_PIN, LOW));
else
(enc-- , digitalWrite(ENABLE_PIN, HIGH));
if (enc < 0) {
enc = 0;}
}
if (enc > 1 & enc < 1000){
if (ST < 3) {
digitalWrite(STEP_PIN, HIGH);
// delayMicroseconds(1);
digitalWrite(STEP_PIN, LOW);}
}
Serial.println(enc);
EncPrevPrev = EncPrev; //сохранение пред-предыдущего состояния
EncPrev = EncCur; //сохранение предыдущего состояния
}
}
void Step() // функция вращеия мотора
{
digitalWrite(ENABLE_PIN, LOW);
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(T);
digitalWrite(STEP_PIN, LOW);
}
void reboot() { // функция сторожевого таймера
wdt_disable();
wdt_enable(WDTO_15MS);
while (1) {}
}
void loop() {
if (!digitalRead(5)) { // кнока ухода в нулевое положеия
digitalWrite(ENABLE_PIN, LOW);
digitalWrite(DIR_PIN, HIGH);
for (int i = 0; (!digitalRead(9)) < 1; i++) {
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(500);
digitalWrite(STEP_PIN, LOW);
}
}
if (!digitalRead(6)){ // снятия с удержаия мотора
digitalWrite(8, HIGH);
}
A = analogRead(A4); // pin joystick
if (A > 520) {
T = map(A, 520, 1123, 500, 0);
digitalWrite(7, 1);
Step();
}
if (A < 480) {
T = map(A, 480, 0, 500, 0); // 500, 0); шкала перерасчета
digitalWrite(7, 0);
Step();
}
if (A > 480 && A < 520) { // 480 < Serial.println(A); < 520
digitalWrite(7, 0);
digitalWrite(4, 0);
}
if (!digitalRead(10)) { //pin коцевика
digitalWrite(ENABLE_PIN, LOW);
digitalWrite(DIR_PIN, HIGH);
for (int i = 0; i < R360; i++) {
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(1000); // скорость отьеда от limit
digitalWrite(STEP_PIN, LOW);
}
}
if (!digitalRead(9)) { //pin коцевика
digitalWrite(ENABLE_PIN, LOW);
digitalWrite(DIR_PIN, LOW);
for (int i = 0; i < R360; i++) {
digitalWrite(STEP_PIN, HIGH);
delayMicroseconds(1000); // скорость отьеда от limit
digitalWrite(STEP_PIN, LOW);
}
{ delay(1000);
reboot(); // сброс таймера
}
}
}
несколько фото с искажениями .
с этого кода я убрал все лишнее что бы можно более нагляднее
видеть как встроить передачу . примерно такую
volatile long int enc; // глобальная куда будет скидываться пики от энкодера
int ST = enc/2.04; // свое значения .
ST переменная получаемого нужное количества шагов ШД по отношению к импульсам энкодера [ Мне подсказал человек у которого код но другой работает хорошо . а как в этом коде далее продолжить я не догоняю чтобы это связать с ШД ]
2.04 условная цифра . нужно подобрать .
//Энкодер на пинах 2, 3.
volatile long int enc;
#define ENABLE_PIN 8
void setup(){
Serial.begin(115200);
pinMode(2,INPUT_PULLUP);
pinMode(3,INPUT_PULLUP);
pinMode(ENABLE_PIN , OUTPUT);
PCIFR=PCIF2; PCICR=1<<PCIE2; //разрешить прерывание
PCMSK2=1<<PCINT18 | 1<<PCINT19; //выбрать вход на котором сработает прерывание
}
uint32_t timer = 0;
const int STEP_PIN = 4;
const int DIR_PIN = 7;
int ST = enc/3;
ISR(PCINT2_vect){
static char EncPrev=0; //предыдущее состояние энкодера
static char EncPrevPrev=0; //пред-предыдущее состояние энкодера
char EncCur = 0;
if(!(PIND & (1 << PD2))){EncCur = 1;} //опрос фазы 1 энкодера
if(!(PIND & (1 << PD3))){ EncCur |= 2;} //опрос фазы 2 энкодера
if(EncCur != EncPrev) //если состояние изменилось,
{ if(EncPrev == 3 && //если предыдущее состояние 3
EncCur != EncPrevPrev ) //и текущее и пред-предыдущее не равны,
{
if(EncCur == 2)
(enc++, digitalWrite(DIR_PIN, LOW), digitalWrite(ENABLE_PIN, LOW));
else
(enc-- , digitalWrite(ENABLE_PIN, HIGH));
if (enc < 0) {
enc = 0;}
}
if (enc > 300 & enc < 1000){
if (ST < 3) {
digitalWrite(STEP_PIN, HIGH);
// delayMicroseconds(1);
digitalWrite(STEP_PIN, LOW);}
}
Serial.println(enc);
EncPrevPrev = EncPrev; //сохранение пред-предыдущего состояния
EncPrev = EncCur; //сохранение предыдущего состояния
}
}
void loop() {
}
ПРОШУ ПОМОЩИ , ПОМОГИТЕ ДОПИСАТЬ ЭТОТ БЛОК КОДА
volatile long int enc; // глобальная куда будет скидываться количества шагов от энкодера
int ST = enc/2.04; // свое значения .
ST переменная получаемого нужное количества шагов ШД по отношению к импульсам энкодера
А далее связать с ШД :
ВРОДЕ ЭТОГО
if (enc > 300 & enc < 1000){ // в этих пределах ШД работает
if (ST < 3) { // это мой мудреж
digitalWrite(STEP_PIN, HIGH); // так я обычно шагаю
// delayMicroseconds(1);
digitalWrite(STEP_PIN, LOW);}
с этой у меня посчиталось но все тормазило но отпечаталось правильно
enc = pulseInLong(3, 0);
но как я это применил я забыл .
Каков физический смысл числа в ST?
ST переменная
есть энкодер 600 имп.
есть ШД . в зависимости от деления драйвера у него разное количество импульсов или STEP_PIN на оборот .
Например без деления 200 импульсов или шагов с делителем 1/8
это уже 200 на 8 = 1600 имп.
За 1 оборот энкодера 600 имп. принтер делает оборот вала или шагов по оси Y неизвестное число (у всех принтеров думаю по разному)
нам нужно подобрать такое число шагов ST (STEP_PIN) чтобы
при одном импульсе энкодера ST соответствовало какому то количества импульсов ШД . что бы это соответствовало правильному отпечатанному изображению .
Теперь математика .
считаем импульсы энкодера и записываем их в temp так как arduino в реальном времени говорят не справиться .
записываем:
volatile long int enc; // число импульсов считаное pinMode(3,INPUT_PULLUP); или кодом (enc) EncCur |= 2;
добавляем переменную (STEP)
int ST = (enc/3.75); //
3.75 это число подбирается вручную если лень метки энкодера и зубья шестеренок от принтера посчитать и потом метки поделить на зубья . ,
далее мне нужно как то переменную ST задействовать в шаге ШД.
допустим пишем :
enc = pulseInLong(3, 0);
int ST = enc/3.75;
if(STпредыдущее != STтекущее) //если состояние изменилось
{ if(STпредыдущее== 3 && //если предыдущее состояние 3
{ STтекущее != STпред-предыдущее ) //и текущее и пред-предыдущее не равны,
{ if(STтекущее == 2)
// тогда делаем шаг
digitalWrite(STEP_PIN, HIGH);
// delayMicroseconds(1);
digitalWrite(STEP_PIN, LOW);}
как то так
может все нужно проще организовать ?
Возможно, я чего-то не понимаю, но одному импульсу энкодера должно соответствовать целое число шагов ШД, иначе как не считай - ошибка неизбежна
а как в принтере механика импульсы энкодера делим на зубья .
и кодом можно
мы же получаем переменную ST, При которой
if(STPrev == 3 && //если предыдущее состояние ST 3
STCur != STPrevPrev ) //и текущее и пред-предыдущее не равны,
// тогда шагаем
if (ST > 30 & ST < 2000){ //
digitalWrite(STEP_PIN, HIGH);
// delayMicroseconds(1);
digitalWrite(STEP_PIN, LOW);}
пока отвечал , мысль пришла проверить а справиться ардуино в реальном времени ? и накидал код но его нужно доработать .
volatile long int enc;
#define ENABLE_PIN 8
void setup(){
Serial.begin(115200);
pinMode(2,INPUT_PULLUP);
pinMode(3,INPUT_PULLUP);
pinMode(ENABLE_PIN , OUTPUT);
PCIFR=PCIF2; PCICR=1<<PCIE2; //разрешить прерывание
PCMSK2=1<<PCINT18 | 1<<PCINT19; //выбрать вход на котором сработает прерывание
}
uint32_t timer = 0;
const int STEP_PIN = 4;
const int DIR_PIN = 7;
int ST = enc/3;
ISR(PCINT2_vect){
static char EncPrev=0; //предыдущее состояние энкодера
static char EncPrevPrev=0; //пред-предыдущее состояние энкодера
char EncCur = 0;
static char STPrev=0; //предыдущее состояние ST
static char STPrevPrev=0; //пред-предыдущее состояние ST
char STCur = 0
if(!(PIND & (1 << PD2))){EncCur = 1;} //опрос фазы 1 энкодера
if(!(PIND & (1 << PD3))){ EncCur |= 2;} //опрос фазы 2 энкодера
if(!(ST & (1 << STPrev))){STCur = 1;} //опрос предыдущее состояние ST
if(!(ST & (1 << STPrevPrev))){ STCur |= 2;} //опрос пред-предыдущее состояние ST
if(EncCur != EncPrev) //если состояние изменилось,
if(STCur != STPrev) //если состояние изменилось
{ if(EncPrev == 3 && //если предыдущее состояние 3
EncCur != EncPrevPrev ) //и текущее и пред-предыдущее не равны,
if(STPrev == 3 && //если предыдущее состояние ST 3
STCur != STPrevPrev ) //и текущее и пред-предыдущее не равны,
{
if(EncCur == 2)
if(STCur == 2)
(enc++, digitalWrite(DIR_PIN, LOW), digitalWrite(ENABLE_PIN, LOW));
(ST++, digitalWrite(DIR_PIN, LOW), digitalWrite(ENABLE_PIN, LOW));
else
(enc-- , digitalWrite(ENABLE_PIN, HIGH));
if (enc < 0) {
enc = 0;}
}
if (ST > 30 & ST < 2000){ //
digitalWrite(STEP_PIN, HIGH);
// delayMicroseconds(1);
digitalWrite(STEP_PIN, LOW);}
}
Serial.println(enc);
Serial.println(ST);
EncPrevPrev = EncPrev; //сохранение пред-предыдущего состояния
EncPrev = EncCur; //сохранение предыдущего состояния
}
}
void loop() {}
Что-бы говорить конкретно - нужна полная схема устройства.
Если число шагов на оборот двигателя кратно числу импульсов на оборот энкодера - то никаких дробей не будет
Для упрощения я с кода все выкинул , оставил энкодер и ШД .
и arduino AVR328
По коду видно
enc сидит
pinMode(2,INPUT_PULLUP);
pinMode(3,INPUT_PULLUP);
ШД. на
#define ENABLE_PIN 8
const int STEP_PIN = 4;
const int DIR_PIN = 7;
задача ;
enc ++ = ST ++ умножить на STEP_PIN //++ импульс
ST моя переменная
как велосипед
enc = пидали Бол. Звезда есть
определить заднее колесо малую звезду == ST
Накинуть цепь - запитать этот механизм в коде .
велосипед наверное все видели .
У велосипеда колесо можно остановить между зубьями. ШД только делает шаги. На 0.13 “шагнуть” не сможет))
Посмотрите функцию map()
да , я ее пробовал несколько дней назад , но до нее нужно еще что то сделать .
я не смог разобраться .
и для map
нужны переменные энкодера и ШД.
SP = map (enc++, 0, 200, 0, 600); //200ШД И 600 ENC
потом их правильно вписать .
у меня нет базовых знаний для понимания что за чем вписывать
Почитайте описание функции
Здесь написано, что :
переменной SP присваивается значение переменной enc, из диапазона значений 0…200, переведённое в диапазон значений 0…600. После этого, значение enc увеличивается на 1.
Напишите простой скетч, с выводом в сериал, и посмотрите, как работает.
Опять ничего непонятно.
Что должно происходить с двигателем, когда вычислено ST = 855 / 3.75?
посмотрел и не понял . толи 1 к 1 мне так не надо
а на мониторе по другому 1 к неизвестно чему мне почти так надо
5 часов пробовал так и не понял .
нужно печать запускать а у нас ночь . 4 часа
так вот написал . ничего уже не соображаю.
volatile long int enc , ST = enc/1.04;
#define ENABLE_PIN 8
const int STEP_PIN = 4;
const int DIR_PIN = 7;
int L = 0;
void setup(){
Serial.begin(115200);
pinMode(2,INPUT_PULLUP);
pinMode(3,INPUT_PULLUP);
pinMode(ENABLE_PIN , OUTPUT);
PCIFR=PCIF2; PCICR=1<<PCIE2; //разрешить прерывание
PCMSK2=1<<PCINT18 | 1<<PCINT19; //выбрать вход на котором сработает прерывание
}
ISR(PCINT2_vect){
static char EncPrev=0; //предыдущее состояние энкодера
static char EncPrevPrev=0; //пред-предыдущее состояние энкодера
char EncCur = 0;
if(!(PIND & (1 << PD2))){EncCur = 1;} //опрос фазы 1 энкодера
if(!(PIND & (1 << PD3))){ EncCur |= 2;} //опрос фазы 2 энкодера
if(EncCur != EncPrev) //если состояние изменилось,
{
if(EncPrev == 3 && //если предыдущее состояние 3
EncCur != EncPrevPrev ) //и текущее и пред-предыдущее не равны,
{
if(EncCur == 2) //если текущее состояние 2,
enc++; //шаг вверх
else //иначе
enc--; //шаг вниз
}
if (enc > 0 && enc < 2000){
enc = digitalRead(3);
enc = map (ST++, 0, 1600, 0, 600);
digitalWrite(DIR_PIN, LOW);
digitalWrite(ENABLE_PIN, LOW);
digitalWrite(STEP_PIN, HIGH);
// delayMicroseconds(1);
digitalWrite(STEP_PIN, LOW);
}
else
enc = digitalRead(2);
enc = map (ST--, 0, 1600, 0, 600);
digitalWrite(DIR_PIN, 1);
digitalWrite(ENABLE_PIN, LOW);
digitalWrite(STEP_PIN, HIGH);
// delayMicroseconds(1);
digitalWrite(STEP_PIN, LOW);
EncPrevPrev = EncPrev; //сохранение пред-предыдущего состояния
EncPrev = EncCur; //сохранение предыдущего состояния
}
Serial.print(" ST - ");
Serial.print(ST);
Serial.print(" enc - ");
Serial.print(enc);
}
void loop() {
}
вывод монитора
ST - -115 enc - -42 ST - -116 enc - -43 ST - -117 enc - -43 ST - -118 enc - -43 ST - -119 enc - -44 ST - -120 enc - -44 ST