Помогите допилить проект на Attiny13
- можно проще - на свои выходы приёмыша навесить потроха от серв например 9ти грамовых, вместо переменника подстроечник- выствить нейтраль и ВСЁ - у вас два рега для движков.
с тинькой смысла морочиться тут никакого, ИМХО 😃)
- можно проще - на свои выходы приёмыша навесить потроха от серв например 9ти грамовых, вместо переменника подстроечник- выствить нейтраль и ВСЁ - у вас два рега для движков.
с тинькой смысла морочиться тут никакого, ИМХО 😃)
Одна игрулька - две распотрашенных сервы, а десять игрулек?
Я не ищу решение для одной вещи, у меня их много. У нас неисправные (в основном электроника) игрушки продают на вес. Чтобы сделать то что стоит в серве, мне не надо ее потрошить, это я и сам могу быстро сделать, там ниче трудного нет.
а код ваш в тиньку загоняли - нормально рулит?
Надо же работает. Криво правда, ну у меня суровее. 32 мега с Jtag-ом. Забавно. 😃
P. S. Ну порты поменять. Вооружение вы всё-таки используете. Ну а встроенный РС блин всё портит, но работает.
до заливки в тело еще не дошло, сегодня буду доделывать. Код получается небольшой, я решил увеличить кол-во выборок до 128 на 1мс (128кГц), изменение в коде OCR0A = 0x4A
Движки пищат противно. Изменение окра не сильно помогло. Но всё-таки! 😃
Какая частота PWM лучше для коллекторных движков - 2кГц, 1кГц, 500Гц?
Оптимальная частота 3кГц, меньше влияние помех от двигателей на аппаратуру и сервоприводы…
У меня при 2кГц получается 64 шага, если увеличу до 4кГц, то - во первых будет всего 32 шага, во вторых надо будет массштабировать, код может вылезти за прерывание. Оставлю 2кГц, авось прокатит. Сегодня буду катать в железе.
Полученный код ниже. Чуть позже опишу FUSE, надо ногу RESET отдать под IO порт, разрешить Internal OSC 9.6mHz, еще можно разрешить WDT 1s
В приведенном коде порт PB5 соединен с RESET для отладки и прошивки, хотя функционал его работы полностью написан.
/*
* rx2b_asm.asm
*
* Created: 21.10.2013 19:40:25
* Author: tester500
*//*
* CPU use internal RC clock 9,6 MHz
*/.def temp=r16
.def depwm_a=r17
.def depwm_b=r18
.def pwm_t=r19
.def cr_a=r20
.def cr_b=r21
.def pin_i=r22
.def ch_a_in=r23
.def ch_b_in=r24
.equ cha_p_left=2 ; PB2
.equ cha_p_right=3 ; PB3
.equ chb_p_left=4 ; PB4
.equ chb_p_right=5 ; PB5.org 0x0000
;Interrupt Vectors
rjmp RESET ;RESET
reti ;INT0
reti ;PCINT0
reti ;TIM0_OVF
reti ;EE_RDY
reti ;ANA_COMP
rjmp Timer_INT ;TIM0_COMPA
reti ;TIM0_COMPB
reti ;WDT
reti ;ADC;INT0:
;PCINT0:
;TIM0_OVF:
;EE_RDY:
;ANA_COMP:
;TIM0_COMPA:
;TIM0_COMPB:
;WDT:
;ADC:RESET:
;init procedure
ldi temp,RAMEND ;Set Stack Pointer to RAMEND 0x9f
out SPL,temp;shutdown adc
clr temp ;0x0 -> ADCSRA
out ADCSRA,temp
inc temp ;0x1 -> PRR
out PRR,temp;PORTB variable initializations
;PORTB0 for 1: __PB0 as Input - Reserved for pin PB0
;PORTB1 for 1: __PB1 as Input - Reserved for pin PB1
;PORTB2 for 1: __PB2 as Output - Reserved for pin PB2
;PORTB3 for 1: __PB3 as Output - Reserved for pin PB3
;PORTB4 for 1: __PB4 as Output - Reserved for pin PB4
;PORTB5 for 1: __PB5 as Output - Reserved for pin PB5;PORTB5 NOT Connected to IO PORT! Connected to reset
;for debug and ISP. On code functions for PB5 full
;presentldi temp,0x1C ; for full need 0x3C (PB5 - out)
out PORTB,temp
out DDRB,tempclr temp
clr depwm_a ; temp timer chanel A
clr depwm_b ;temp timer chanel A
clr pwm_t ; software PWM
clr cr_a
clr cr_b
clr pin_i
clr ch_a_in
clr ch_b_in;TIMER_COUNTER_0 - -
;
;Waveform Generation Mode = Clear Timer on Compare Match TOP=OCRA
;Clock Select = clk (No prescaling)
;Output Compare Register A = 0x4A
;CPU clock = 9,6 MHz
ldi temp,0x04 ;(1<<OCIE0A)
out TIMSK0,temp
ldi temp,0x4A ;OCR0A = 0x4A 127kHz
out OCR0A,temp
ldi temp,0x02 ;(1<<WGM01)|(0<<WGM00)
out TCCR0A,temp
ldi temp,0x01 ;(0<<WGM02)|(0<<CS02)|(0<<CS01)|(1<<CS00)
out TCCR0B,temp
seimain_loop:
nop
rjmp main_loop;Timer0 Overflow procedure
Timer_INT:
in pin_i,PINB ;store PinB to R16;PWM procedure
start_pwm:
inc pwm_tcp pwm_t,cr_a
brne pwm_b_start
tst cr_a ; if cr_a eq (0x00 or 0xFF) goto test cr_b
breq pwm_b_start
cpi cr_a,0x40
breq pwm_b_start
cbi PORTB,cha_p_left ; pwm_t eq cr_a, need clear PIN out chanel
cbi PORTB,cha_p_right
pwm_b_start:
cp pwm_t,cr_b
brne pwm_ff
tst cr_a ; if cr_b eq (0x00 or 0xFF) goto pwm_ff
breq pwm_ff
cpi cr_a,0x40
breq pwm_ff
cbi PORTB,chb_p_left ; pwm_t eq cr_b, need clear PIN out chanel
cbi PORTB,chb_p_right
pwm_ff:
cpi pwm_t,0x40
brne pwm_end
; pwm_t=ff; load cr_a, cr_b; need set out_PIN if cr_a or cr_b eq (0x00 or 0xFF)
clr pwm_t
;cr_a chanel
cpi ch_a_in,0x83
brlo cr_a_full_left
cpi ch_a_in,0xBD
brlo cr_a_left
cpi ch_a_in,0xC5
brlo cr_a_stop
cpi ch_a_in,0xFE
brlo cr_a_right
cr_a_full_right:
; cr_a full right
ser cr_a
cbi PORTB,cha_p_left ; clear pin_left, set pin_right
sbi PORTB,cha_p_right
rjmp cr_b_pwm_set
cr_a_full_left:
; cr_a full left
ser cr_a
sbi PORTB,cha_p_left ; set pin_left, clear pin_right
cbi PORTB,chb_p_right
rjmp cr_b_pwm_set
cr_a_stop:
; stop cr_a
clr cr_a
cbi PORTB,cha_p_left ; clear pin_left,pin_right
cbi PORTB,chb_p_right
rjmp cr_b_pwm_set
cr_a_left:
; cr_a left
ldi cr_a, 0xC0
sub cr_a,ch_a_in
sbi PORTB,cha_p_left ; set pin_left, clear pin_right
cbi PORTB,cha_p_right
rjmp cr_b_pwm_set
cr_a_right:
; cr_a right
mov cr_a,ch_a_in
subi cr_a,0xC0
cbi PORTB,cha_p_left ; clear pin_left, set pin_right
sbi PORTB,cha_p_right
cr_b_pwm_set:
;cr_b chanel
cpi ch_b_in,0x83
brlo cr_b_full_left
cpi ch_b_in,0xBD
brlo cr_b_left
cpi ch_b_in,0xC5
brlo cr_b_stop
cpi ch_b_in,0xFE
brlo cr_b_right
cr_b_full_right:
; cr_b full right
ser cr_b
cbi PORTB,chb_p_left ; clear pin_left, set pin_right
sbi PORTB,chb_p_right
rjmp pwm_end
cr_b_full_left:
; cr_b full left
ser cr_b
sbi PORTB,chb_p_left ; set pin_left, clear pin_right
cbi PORTB,chb_p_right
rjmp pwm_end
cr_b_stop:
; stop cr_b
clr cr_b
cbi PORTB,chb_p_left ; clear pin_left,pin_right
cbi PORTB,chb_p_right
rjmp pwm_end
cr_b_left:
; cr_b left
ldi cr_b, 0xC0
sub cr_b,ch_b_in
sbi PORTB,chb_p_left ; set pin_left, clear pin_right
cbi PORTB,chb_p_right
rjmp pwm_end
cr_b_right:
; cr_b right
mov cr_b,ch_b_in
subi cr_b,0xC0
cbi PORTB,chb_p_left ; clear pin_left, set pin_right
sbi PORTB,chb_p_right
pwm_end:bst pin_i,0 ; Test Chanel A
brts Pin0_not_null ; jump if Pin0 =1
tst depwm_a
brne tim_cha_notnull ; jump if Pin_chA = 0 Timer_chA > 0Test_chB:
bst pin_i,1 ; Test Chanel B
brts Pin1_not_null ; jump if Pin1 =1
tst depwm_b
brne tim_chb_notnull ; jump if Timer Chanel B > 0
rjmp ret_inttim_cha_notnull:
mov ch_a_in,depwm_a
clr depwm_a
rjmp Test_chBtim_chb_notnull:
mov ch_b_in,depwm_b
clr depwm_b
rjmp ret_intPin0_not_null: ; inc Timer Chanel A
cpi depwm_a,0xFF
breq Test_chB
inc depwm_a
rjmp Test_chBPin1_not_null:
cpi depwm_b,0xFF
breq ret_int
inc depwm_b
rjmp ret_intret_int:
wdr
reti
Респект. Для лучшей повторяемости, предлагаю вложить скрин с фьюзами и прошивку.
У меня как раз есть кошки, для тренировки…
Чета оно мне не очень понравилось, в логике не хватает красоты и простоты. Делаю версию 2.
План:
Тактовая частота - внутренний источник 9.6 мГц
Таймер - в режиме “Fast PWM TOP=0xFF”; прерывание по переполнению для оцифровки двух входных каналов; прерывания OCRA OCRB для формирования управляющего сигнала на выходе.
Таймер настроен на частоту 37,5 кГц. Для каждого направления в канале использую 36 шагов. Для PWM на выходе эти 36 шагов буду массштабировать (умножать) на 7. Почему 36? Потому что 36*7=252, а таймер 8-битный, макс значение регистра сравнения 255. Выбрал что поближе.
На выходе буду использовать (в схематике) L9110, ибо оно меньше бакса на мотор получается, да и места берет меньше.
Добрый день пару дней назад меня тоже заинтересовала эта тема, я хочу сделать управление до шести составов на железной дороге.через мощный полевик планирую выдавать на рельса сигнал РРМ. в каждом локомотиве стоит приемник. Через колеса, диодный мост спрямляет переменный сигнал PPM и этим напряжением питает двигатели откликаясь на свой канал, у игроков пульт с одним резистором. Сейчас собираю материал, ваша статья самая интересная для меня но хотел бы вам показать еще эту статью nick_shl.at.tut.by/Work/Receiver.htm, В ней понравилась идея определения полярности сигнала и некоторый другие вещи инициализации сейчас не знаю правда на сколько это актуально потому как макет еще не делал но по описанию разумно. Программу постараюсь писать сам, не подглядывая к вам может потом найдем оптимальные коды и объединим результат. Давно ничего не писал правда, но дети хотят интересные игрушки буду вспоминать, начну в понедельник на работе дома не хватает времени. еще хочу учесть функцию тормоза при малых длительностях команды в пределах 1- 1,2мс, шунтировать двигатель через полевик.
По ссылке проект, в котором на входе PPM, на выходе несколько PWM каналов. У меня это часть в приемнике. Я делаю схемку, которая принимает два PWM канала, на которых обычно висят сервы, и управляю двумя коллекторными движками. Подобную схему я не видел в инете, либо один контроллер на один движок. Хотя даже в одной тиньке сил хватает на два движка. Основная проблема с входным сигналом, я не знаю как приходят PWM импульсы, предполагаю что сигналы друг с другом вообще никак не связанны (может там два разных приемника).
Насчет питания - можно проще сделать - на рельсы подавать постоянный ток, и туда-же через конденсатор подмешивать полезный сигнал, на приемной стороне через такой-же конденсатор снимать сигнал.
Как я вижу вашу задачу, на входе по таймеру записываю число первого времени в один регистр, затем число второго времени в другой регистр. затем обсчет величин. Я предлагаю дискретность сделать равной десяти. и вычитать из числа эквивалента 1 мс наше подсчитанное число если флаг 0 или или отрицания то переход к заданию нуля на выходе шим, если флага нет, то вычитаем из 1,1мс, и т.д. до 2мс, при этом в цикле вычитания можно присваивать множитель переменной для последующего умножения шим или сразу эквивалент скважности. затем также второй канал. у вас на всю математику остается 16мс. можно уложиться с головой.
Насчет питания постоянным током и подмешиванием через конденсатор сигнала, насколько я понимаю такая схема будет работать если амплитуда сигнала будет выше постоянной составляющей, иначе грубо говоря нужно будет просаживать постоянку на землю. а тут диодный мост, хотя может даже и одного диода хватит (отрицательной составляющей же нет как в синусоидальном сигнале), и вот уже постоянка. итого до диода сигнал после питание! лично мне нравиться, хотя готов рассмотреть и другие варианты.
Как я вижу вашу задачу, на входе по таймеру записываю число первого времени в один регистр, затем число второго времени в другой регистр. затем обсчет величин.
Допустим есть 8-битный регистр-счетчик времени и счет идет вверх по кругу (по достижению значения 255 он обнуляется и считает снова). Предположим у нас 10 шагов счетчика на максимальный сигнал на входе. В первый регистр заносим 254 (именно в этот момент сигнал на входе скакнул вверх), во второй регистр заносим 5. Как будет выглядеть обсчет величин? А если сигнал на входе отвис на два-три и т.д. периода регистра-счетчика?
Обычно делается не так. Берем регистр, при появлении сигнала на входе двигаем этот регистр вверх с проверкой граничных величин. Как тока сигнал на входе изменился, копируем полученное число в регистр переменную длительности сигнала на входе. Основной фокус проверка тех самых граничных величин.
Теперь о проблемах. В Attiny13 один 8-битный таймер и внутренний генератор частоты на 9.6 мГц. Для того чтобы получить на выходе не просто сигнал направления (для двигателя вперед-назад), а чтобы этот сигнал был ШИМом для движка, есть два способа - аппаратный ШИМ, и программный ШИМ. Программный шим я уже сделал, но у него очень низкая частота. Для увеличения частоты нужен аппартный ШИМ. Теперь математика - используем режим “Fast PWM TOP=0xFF” для таймера. У таймера три прерывания - два прерывания для ШИМ, и одно по переполнению. Прерывание по переполнению используем для обсчета входного сигнала. 9600000/256=37500. На входе сигнал 1 мсек =1кГц (вперед или назад) у нас 37,5 периодов таймера максимальное разрешение таймера. буду считать 36 влево или вправо, а 1 на границу нуля. Выходной сигнал от 0 до 255. 255/36 = семь с копейками. Значит полученное значение умножаем на 7 и в регистр сравнения таймера для формирования ШИМ. Остается снабдить эту конструкцию проверкой границ и определения рабочего выходного канала (вперед или назад).