Проект требует реальной доводки до ума, даже если попытаться фрезеровать на нем фанерку скажем 4-5 мм конструкция начнет по швам сыпаться. Ось Z выглядит таким образом что ее делали на очень скорую руку.
Ну конструкция далеко по швам не сыплется, она крепче чем кажется на первый взгляд. Фрезеровал алюминий, делал узор на дубовой доске глубиной до 8 мм V-образной 30 градусной фрезой. Прекрасно фрезирует акрил, контуры плат. Единственное нехватает вертикальной жесткости по оси У... т.е. если кривой винт, стол подпрыгивает при повороте винта. Планирую заменить эти мебельные направляющие... И еще одно... грабли... В качестве стола не берите фанетру. Я пару недель назад поменял на 20 мм. МДФ от столешницы. Печатку могу выложить, но она на ОООЧЕНь скорую руку... но работает...
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
И вообще, я ж писал, разъем XD - резервный, на него, кажется, в этой версии прошивки ничего не идет. Потом планирую добавить управление реле всякими... но пока времени нету.
И вообще, я ж писал, разъем XD - резервный, на него, кажется, в этой версии прошивки ничего не идет. Потом планирую добавить управление реле всякими... но пока времени нету.
не подскажете какая мега подойдет? в магазине мег16 кучка небольшая mega16-16AU mega16-16PU mega16A-AU mega16A-PU mega16L-8PU спасибо пысы: развитие контроллера будет и как скоро?
не подскажете какая мега подойдет? в магазине мег16 кучка небольшая
Впринципи любая... mega16L-8PU будет работать с небольшим оверклокингом.
У меня вроди atmega16-16PU стоит, хотя хз, завтра буду дома, гляну...
ViP писал(а):
пысы: развитие контроллера будет и как скоро?
На счет развития - планирую, но как скоро, не знаю... пока дел много... А чего там вообще развивать? ну кроме реле управления шпинделем... Мож пожелания какие будут?
Freeman мне понравился ваш проект довольно простое и практичное решение. Давно уже обдумываю постройку чпу но все в поисках надежной и недорогой конструкции электроники , ваш проект то что надо дешево и практично... Но я не не понял как реализованы концевые выключатели нулевого положения осей х,у,z? Я думаю что кроме реле управления шпинделем, не помешало бы управление для пылесоса или какой нибудь небольшой вытяжки...
Когда-то для друга, который хотел начать программировать авр_ки, делал подобное. Упор делал не на оптимальность работы прошивки, а на максимальность понимания процессов, происходящих в контроллере на примере понятного ему (другу) задания. Но тем не менее, оно хоть и учебное, но работало. Сделано в ИАР_е под МЕГУ8 3 step-dir с режимом "сна" Поскольку у этого контроллера только 2 внешних прерывания, третьим выбран вход компаратора.
Код:
#include <inavr.h> #include <iom8.h>
/* Set BIT in ADDRESS */ #define setbit(ADDRESS,BIT) ((ADDRESS) |= (1<<(BIT)))
/* Clear BIT in ADDRESS */ #define clearbit(ADDRESS,BIT) ((ADDRESS) &= ~(1<<(BIT)))
/* Test BIT in ADDRESS */ #define testbit(ADDRESS,BIT) ((ADDRESS) & (1<<(BIT)))
PORTC = 0x00;//all pin=0 DDRC = 0x7F;//C0-C6 for output
PORTD = 0x00;//all output pinD=0, input pin D5 without pullup_s DDRD = 0x20;//D5-output, all other-input }
//TIMER0 initialize (On system clock=8MHZ, overflow interrupt every 32768us.) void timer0_init(void) { TCCR0 = 0x00; //stop TCCR0 = 0x05; //start timer prescale:1024 }
//Comparator initialize void comparator_init(void) { ACSR = ACSR & 0xF7; //ensure interrupt is off before changing ACSR = 0x4B; //Use Analog Comparator+Compare interrupt //fixed bandgap reference voltage replaces the positive input to the Analog Comparator. //Interrupt trigger level - Rising output edge //interrupt from 1 to 0 on pin D7 }
void sleep_motor1(void) //мотор 1 ложим в спящее состояние { clearbit(PORTD,5); // установили в 1 PORTB,5 договоримся, что лог 1 уменьшает питание этого двигателя до состояния удержания } void sleep_motor2(void) { clearbit(PORTB,7); } void sleep_motor3(void) { clearbit(PORTB,6); }
void wakeup_motor1(void)//мотор 1 выводим из спящего состояния { setbit(PORTD,5); //установили в 0 PORTB,5 договоримся, что лог 0 питание этого двигателя на всю катушку worktime1=0; //раз двигатель проснулся, то переменная, содержащая количество тактов таймера когда двигатель1 неактивен, =0 } //грубо говоря, считаем с нуля.
#pragma vector = TIMER0_OVF_vect __interrupt void timer0_ovf_handler(void) { //32786 us time left worktime1++; //таймер клацнул. увеличиваем переменные неактивности двигателей worktime2++; worktime3++; if (worktime1>=30){sleep_motor1();worktime1=0;}//30 клацаний это около 1 секунды if (worktime2>=30){sleep_motor2();worktime2=0;}//если двигатель неактивен более секунды, if (worktime3>=30){sleep_motor3();worktime3=0;}//то ему пора баеньки }//а чтобы не часто его укладывать(32786 us), счетчики обнулим. повторно уложим через 1 секунду.
//тутычки процедура вычисления статуса, если нужно вращать влево unsigned char workleft(unsigned char data) { unsigned char resultat=1;// промежуточная переменная switch (data)// смотрим, что нам принесло число, переданное в эту процедуру { case 1: {resultat=2;break;} //в зависимости от предыдущих состояний case 2: {resultat=3;break;} //присваиваем промежуточной переменной различные состояния case 3: {resultat=4;break;} case 4: {resultat=5;break;} case 5: {resultat=6;break;} case 6: {resultat=7;break;} case 7: {resultat=8;break;} case 8: {resultat=1;break;} default: break; // так нужно... } return resultat;// говорим то, что вернет нам эта процедура }
//а здеся процедура вычисления статуса, если нужно вращать вправо unsigned char workright(unsigned char data) { unsigned char resultat=1;// все, как и выше, только вправо switch (data) { case 1: {resultat=8;break;} case 2: {resultat=1;break;} case 3: {resultat=2;break;} case 4: {resultat=3;break;} case 5: {resultat=4;break;} case 6: {resultat=5;break;} case 7: {resultat=6;break;} case 8: {resultat=7;break;} default: break; } return resultat; }
// и вот, наконец само воздействие на состояния выходных линий void left_motor1(void) { unsigned char newstatus; // все, как и раньше. обьявляем промежуточную переменную newstatus=workleft(oldstatus_motor1); //выясняем, какой статус будет, если раньше у мотора был статус-oldstatus_motor1 clearbit(PORTB,0); //а вращать нужно влево. clearbit(PORTB,1); clearbit(PORTB,2); //наитупейшим образом обнуляем выходные линии clearbit(PORTB,3); if (newstatus==1) {setbit(PORTB,0);} if (newstatus==2) {setbit(PORTB,0);setbit(PORTB,1);} if (newstatus==3) {setbit(PORTB,1);} if (newstatus==4) {setbit(PORTB,1);setbit(PORTB,2);} if (newstatus==5) {setbit(PORTB,2);} if (newstatus==6) {setbit(PORTB,2);setbit(PORTB,3);} if (newstatus==7) {setbit(PORTB,3);} if (newstatus==8) {setbit(PORTB,3);setbit(PORTB,0);} oldstatus_motor1=newstatus; // и напоследок, ведь статус выходных линий уже поменяли, запоминаем новый статус, как старый. } // это пригодится при повторном вычислении этого статуса
void right_motor1(void) { unsigned char newstatus; newstatus=workright(oldstatus_motor1);// все, как и раньше. Только вправо. clearbit(PORTB,0); clearbit(PORTB,1); clearbit(PORTB,2); clearbit(PORTB,3); if (newstatus==1) {setbit(PORTB,0);} if (newstatus==2) {setbit(PORTB,0);setbit(PORTB,1);} if (newstatus==3) {setbit(PORTB,1);} if (newstatus==4) {setbit(PORTB,1);setbit(PORTB,2);} if (newstatus==5) {setbit(PORTB,2);} if (newstatus==6) {setbit(PORTB,2);setbit(PORTB,3);} if (newstatus==7) {setbit(PORTB,3);} if (newstatus==8) {setbit(PORTB,3);setbit(PORTB,0);} oldstatus_motor1=newstatus; }
void left_motor3(void) { unsigned char newstatus; newstatus=workleft(oldstatus_motor3); clearbit(PORTC,2); clearbit(PORTC,3); clearbit(PORTC,4); clearbit(PORTC,5); if (newstatus==1) {setbit(PORTC,2);} if (newstatus==2) {setbit(PORTC,2);setbit(PORTC,3);} if (newstatus==3) {setbit(PORTC,3);} if (newstatus==4) {setbit(PORTC,3);setbit(PORTC,4);} if (newstatus==5) {setbit(PORTC,4);} if (newstatus==6) {setbit(PORTC,4);setbit(PORTC,5);} if (newstatus==7) {setbit(PORTC,5);} if (newstatus==8) {setbit(PORTC,5);setbit(PORTC,2);} oldstatus_motor3=newstatus; }
void right_motor3(void) { unsigned char newstatus; newstatus=workright(oldstatus_motor3); clearbit(PORTC,2); clearbit(PORTC,3); clearbit(PORTC,4); clearbit(PORTC,5); if (newstatus==1) {setbit(PORTC,2);} if (newstatus==2) {setbit(PORTC,2);setbit(PORTC,3);} if (newstatus==3) {setbit(PORTC,3);} if (newstatus==4) {setbit(PORTC,3);setbit(PORTC,4);} if (newstatus==5) {setbit(PORTC,4);} if (newstatus==6) {setbit(PORTC,4);setbit(PORTC,5);} if (newstatus==7) {setbit(PORTC,5);} if (newstatus==8) {setbit(PORTC,5);setbit(PORTC,2);} oldstatus_motor3=newstatus; }
#pragma vector = ANA_COMP_vect// Сюда мы попадем, если вход AIN1 установится в 0 __interrupt void ana_comp_handler(void) { //analog comparator compare event wakeup_motor3(); // договорились, что рабочий фронт =0, значит двигатель просят подвинуться. Нужно просыпаться if (!testbit(PIND,1)>0) left_motor3();// а в зависимости, от того, в какую сторону просят крутиться, else right_motor3(); //вызываем и соответствующие подппрограмки }
void left_motor2(void)// все, как и раньше. Только для двигателя 2. { unsigned char newstatus; newstatus=workleft(oldstatus_motor2); clearbit(PORTB,4); clearbit(PORTB,5); clearbit(PORTC,0); clearbit(PORTC,1); if (newstatus==1) {setbit(PORTB,4);} if (newstatus==2) {setbit(PORTB,4);setbit(PORTB,5);} if (newstatus==3) {setbit(PORTB,5);} if (newstatus==4) {setbit(PORTB,5);setbit(PORTC,0);} if (newstatus==5) {setbit(PORTC,0);} if (newstatus==6) {setbit(PORTC,0);setbit(PORTC,1);} if (newstatus==7) {setbit(PORTC,1);} if (newstatus==8) {setbit(PORTC,1);setbit(PORTB,4);} oldstatus_motor2=newstatus; }
void right_motor2(void) { unsigned char newstatus; newstatus=workright(oldstatus_motor2); clearbit(PORTB,4); clearbit(PORTB,5); clearbit(PORTC,0); clearbit(PORTC,1); if (newstatus==1) {setbit(PORTB,4);} if (newstatus==2) {setbit(PORTB,4);setbit(PORTB,5);} if (newstatus==3) {setbit(PORTB,5);} if (newstatus==4) {setbit(PORTB,5);setbit(PORTC,0);} if (newstatus==5) {setbit(PORTC,0);} if (newstatus==6) {setbit(PORTC,0);setbit(PORTC,1);} if (newstatus==7) {setbit(PORTC,1);} if (newstatus==8) {setbit(PORTC,1);setbit(PORTB,4);} oldstatus_motor2=newstatus; }
#pragma vector = INT0_vect// Сюда мы попадем, если вход INT0 установится в 0 __interrupt void int0_handler(void) { //external interupt on INT0 wakeup_motor1();// все, как и для мотора3, только для первого if (!testbit(PIND,0)>0) left_motor1(); else right_motor1(); }
#pragma vector = INT1_vect// Сюда мы попадем, если вход INT1 установится в 0 __interrupt void int1_handler(void) { //external interupt on INT1 wakeup_motor2();// выше уже обьяснял. if (!testbit(PIND,4)>0) left_motor2(); else right_motor2(); }
void init_devices(void) { //stop errant interrupts until set up __disable_interrupt(); //disable all interrupts port_init();// вызываем процедуру инициализации портов timer0_init();// вызываем процедуру инициализации таймера comparator_init();// вызываем процедуру инициализации компаратора
MCUCR = 0x0A;// INT0- Falling edge, INT1- Falling edge (interrupt from 1 to 0) GICR = 0xC0;// Interrupt from INT0+INT1 TIMSK = 0x01; //timer interrupt sources __enable_interrupt(); //re-enable interrupts //all peripherals are now initialized }
main( void ) { worktime1=0; //обнуляем переменные, содержащие время неактивности двигателей worktime2=0; worktime3=0; oldstatus_motor1=1;// состояния портов двигателя 1.2.3.4 oldstatus_motor2=1;//примем по умолчанию 1 oldstatus_motor3=1; init_devices();// Думаю, это не вызывает затруднений для понимания....
__delay_cycles (300); // В соответствии со статусом 1 установим соответствующие линии портов clearbit(PORTB,2);//M1 clearbit(PORTB,3); clearbit(PORTB,1); setbit(PORTB,0);
Freeman не против, вот только эта ветка по конкретному устройству... так что если по вашей теме будет больше 1-2 сообщений, то стоит создать отдельную тему.
В свое время такой проектик не нашел и решил сделать свой. Кроме того он (для меня) избыточен. Кстати, вместо биполярников лучше ставить полевики...
А вот с джойстиком, идея интересная, надо бы где-то найти и поиграться...
убивец писал(а):
Но я не не понял как реализованы концевые выключатели нулевого положения осей х,у,z?
По схеме предусмотрена только кнопка Estop. Остальное - не разведено. Никто вам не мешает дополнить схему концевиками - благо входов в LPT хватает.
А на счет исходников - не выкладываю потому что разведется флуд по теме нерациональности и кривизны написания... Имею горький опыт... Сам я не считаю что прошивка плохо написана, просто, местами, не рационально... Но ведь программисты, они как из гитаристы из анекдотов:
"- Сколько нужно гитаристов, чтобы вкрутить лампочку? - 100! - Почему так много?! - Один будет вкручивать, а остальные 99 будут критиковать, и говорить, что они бы это сделали значительно лучше."
Сейчас этот форум просматривают: indman и гости: 44
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения