Выплескивание эмоций

Тема в разделе "Флудилка", создана пользователем alp69, 15 окт 2016.

  1. akl

    akl Гик

    о блин, вроде симуляция атмега8 и 168 есть. 328 нету
     
  2. rkit

    rkit Гуру

    Интегрирована с фирменными программаторами от атмела. Дудку не умеет, но можно самому заливать собранный файл.
     
  3. Airbus

    Airbus Оракул

    Вроде шил когдато.Надо проверить.Но у меня Студия 4
     
  4. akl

    akl Гик

    чет библиотека серво слишком запутанная.
     
  5. akl

    akl Гик

    есть такая хорошая приблуда для студии - atmel data visualizer. я так понял она с древними версиями (4.19 и т.п.) не работает. печально
     
  6. akl

    akl Гик

    кто-нибудь понимает логику библиотеки servo хоть в общих чертах?:confused:
     
  7. Airbus

    Airbus Оракул

    В общих это как драйвер.Или подпрограмма на Асме.Управляет конкретным устройством на уровне дрыгоножества при поступлении макрокоманд из основного цыкла
     
  8. akl

    akl Гик

    это уж слишком в общих чертах.
    я так понял вот основная суть:
    Код (C++):
    static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t *TCNTn, volatile uint16_t* OCRnA)
    {
      if( Channel[timer] < 0 )
        *TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
      else{
        if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive == true )
          digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,LOW); // pulse this channel low if activated
      }

      Channel[timer]++;    // increment to the next channel
      if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
        *OCRnA = *TCNTn + SERVO(timer,Channel[timer]).ticks;
        if(SERVO(timer,Channel[timer]).Pin.isActive == true)     // check if activated
          digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high
      }
      else {
        // finished all channels so wait for the refresh period to expire before starting over
        if( ((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL) )  // allow a few ticks to ensure the next OCR1A not missed
          *OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
        else
          *OCRnA = *TCNTn + 4;  // at least REFRESH_INTERVAL has elapsed
        Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
      }
    }
    приходит от счетчика прерывание по совпадению

    если перебор всех сервов закончился ( Channel[timer]<0), то счетчик обнуляется
    иначе если перебор не закончился, то если эта серва не последняя в списке и если ее пин активен (хз что значит "пин активен", может проверка подключена ли серва), то в пин записывается ноль.

    затем номер обрабатываемой сервы меняется на следующий.
    если эта следующая серва не последняя и че-то там не превышено количество сервов на таймер,
    пишем в регистр для сравнивания текущее зачение счетчика плюс сколько надо натикать для этой сервы, в пин, проверенный на активность, пишем 1, и уходим нафиг ждать пока натикает и сработает прерывание

    иначе же если эта следующая серва последняя (или предыдущая была последняя хз) или че-то там закончилось по количеству сервов на таймер, то если счетчик еще не натикал на рефреш_интервал (20к микросекунд) и в ближайшие 4 тика не натикает, то в регистре сравнения оставляем этот рефреш_интервал, иначе в регистр сравнения пишем текущее значение счетчика +4 (непонятно вообще что это за люфт +4, может чтобы не пропустить прерывание)
    ну и так как эта серва была последняя, то Channel[timer] = -1, чтобы в следующий раз перебор начался с нуля.


    то есть я не понимаю как это работает. на каждую из серв должно поступать 1 на определенное время раз в 20000 микросекунд. Походу этот алгоритм делает это. но как?

    когда приходит прерывание, он ставит 1 на первую серву, засекает ее время и идет ждать следующего прерывания. следующее прерывание приходит когда истечет время этой сервы, тогда он ставит на нее 0, на следующую 1 и идет ждать время для следующей, и так далее пока сервы не кончатся. когда все сервы кончились, он проверяет прошло ли 20000 микросекунд, если надо ждет пока пойдет, а дальше всё повторяется.
    Так это работает? но тогда получается что при количестве сервов больше 8ми интервал в 20000 может быть превышен? хотя может это и нормально, т.к. в библиотеке написано что это "minumim time to refresh servos in microseconds". Но ведь тогда частота будет плавать? или сервам пох на это, главное чтобы время импульса соблюдалось? Частота вообще будет плавать постоянно, в зависимости от положения предыдущих серв на следующие будет приходить сигнал в разное время.

    Короче - правильно ли я понял алгоритм? из-за всех этих обобщений, указателей и массивов там полнейшая каша
     
    Последнее редактирование: 3 окт 2017
  9. akl

    akl Гик

    установил симулятор VMLAB и вроде даже разобрался как в нем делать графики поведения ног. думаю сойдет. Был соблазн замахнуться на протеус конечно, но пока боязно.
     
  10. akl

    akl Гик

    вопрос такой назрел - в АврСтудии когда в режиме входа например
    DDRС=0 включаю подтяжку
    PORTС |= (1<<2)
    в регистре PINC,2 не появляется единичка.
    Где-то читал что это баг студии, но не помню где и правда ли это
    собственно - в реальности появится же единичка в PIN при включении подтяжки (и исчезнет когда нога замкнется за землю)? или как?
     
  11. Airbus

    Airbus Оракул

    DDRC=0 это портС на вход а вообще команда бессмысленная но они по умолчанию все на вход поэтому это можно не писать.Вторая команда это и есть подключить подтяжку в Вашем случае на ПортС пин2.Там и не будет ничего потому что это вход если не подавать внешний сигнал извне.Вот если DDRC=1 (порт как выход) и вторую косанду то на пине 2 ПортаС будет 1.Так что все логично.
     
  12. akl

    akl Гик

    так а резистор на питание (хоть и встроенный) - это че, не сигнал?

    что-то я вообще запутался. если я допустим хочу подключить кнопку, включаю подтяжку
    (PORTС |= (1<<2))
    а потом буду считывать нажата ли кнопка вот так
    PINC & (1 << 2)
    то оно будет возвращать 1 или нет? как тогда кнопки считывать если не из PIN-регистра?

    не может быть такого. наверно это баг. да, видимо просто авр-студия не отдупляет насчет подтяжки


    да, так и есть

     
    Последнее редактирование: 12 окт 2017
  13. Limoney

    Limoney Гик

    Подтяжка - это подключение встроенного резистора через VCC на пин, то есть на пине будет VCC.
    Настройка пина производится двумя регистрами, регистр направления DDx вход или выход, и регистр
    порта PORTx. Пин порта может быть настроен, как выход логический нуль, выход логическая единица, или вход с подтягивающем сопротивлением или высокоомный вход.
     
  14. akl

    akl Гик

    только вот в симуляторе авр-студии придется еще вручную тыкать в регистр PIN, т.к. иначе там 1 не появится хоть заподключайся подтяжками

    хотя это неудобство совершенно ничтожное по сравнению с плюсами наличия этого симулятора-дебаггера как такового. особенно после ардуино, где вообще непонятно что происходит.
     
    Последнее редактирование: 12 окт 2017
  15. Limoney

    Limoney Гик

    Да, для каждого пина нужно устанавливать PINx
     
  16. Airbus

    Airbus Оракул

    Ну да вручную тыкать по любому иначе как сымитировать приход 1?Напряжение на пине с подтяжкой 2.2 вольта это типа ноль а единица это 5 вольт.Здесь про подключение кнопок и светодиодов на выходе
     
    Последнее редактирование: 13 окт 2017
  17. davidgolikh

    davidgolikh Нуб

    Всем привет
    :)
     
  18. davidgolikh

    davidgolikh Нуб

    Как у вас дела у меня хорошо
     
  19. akl

    akl Гик

    доделал блок питания на чистомСи™
    Код (C++):
    #include <avr/io.h>
    #define F_CPU 8000000UL
    #include <util/delay.h>

    #define setH(port,bit)  do{port |= (1 << bit);}while(0)
    #define setL(port,bit)  do{port &= ~(1 << bit);}while(0)
    #define readP(reg,bit)    (reg & (1 << bit))

    uint16_t tok;
    uint16_t tok1;
    uint16_t tok2;
    uint16_t tok3;
    uint16_t tok4;
    uint8_t tokmod;
    uint8_t tokmodd;
    uint16_t tok0;
    uint8_t tokd;
    uint8_t button;
    uint8_t caltok;
    uint8_t calbut;

    typedef struct pin_t
    {
        volatile uint8_t *port;
        uint8_t bit;
    }Pin;

    Pin Led0 = {&PORTD, 1<<5};
    Pin Led1 = {&PORTD, 1<<6};
    Pin Led2 = {&PORTD, 1<<7};
    Pin Led3 = {&PORTB, 1<<0};
    Pin Led4 = {&PORTB, 1<<1};
    Pin Led5 = {&PORTB, 1<<2};

    Pin* LedArray[] = {
    &Led0,
    &Led1,
    &Led2,
    &Led3,
    &Led4,
    &Led5
    };
    #define allleds 6


    void WriteLed_on(uint8_t num)
    {
      Pin* pin = LedArray[num];
      *pin->port |= pin->bit;
    }

    void WriteLed_off(uint8_t num)
    {
      Pin* pin = LedArray[num];
      *pin->port &= ~pin->bit;
    }

    void WriteLed(uint8_t num, uint8_t val)
    {
      Pin* pin = LedArray[num];
      if (val==0){*pin->port &= ~pin->bit;}
      else {*pin->port |= pin->bit;}
    }

    void SetLeds(uint8_t n){
       uint8_t i;
       for(i=0; i<allleds; i++){
       if(i<n){WriteLed_on(i);}
       else{WriteLed_off(i);}}
    }

    static inline uint16_t AdcRead(uint8_t analog_pin){  //ADC
        ADMUX = 0b01000000 | analog_pin; //VCC
        ADCSRA = 0b11000110; // СК/64 (125KHZ)
        while ((ADCSRA & (1 << ADIF)) == 0);
        uint16_t adcw;
        adcw= ADC;
        ADCSRA |= (1 << ADIF);
        return adcw;
    }

    void EepromWrite(uint16_t addr, uint8_t dat){
       while(EECR & (1<<EEWE));
       EEAR = addr;
       EEDR = dat;
       EECR |= (1<<EEMWE);
       EECR |= (1<<EEWE);
    }

    uint8_t EepromRead(uint8_t addr){
       while(EECR & (1<<EEWE));
       EEAR = addr;
       EECR |= (1<<EERE);
       return EEDR;
    }

    void calibrovka(){
       uint8_t tokk;
       tokk = tok-350;
       EepromWrite(110, 123);
       WriteLed_off(0);
       WriteLed_off(1);
       WriteLed_off(2);
       WriteLed_off(3);
       WriteLed_off(4);
       _delay_ms(200);
       EepromWrite(111, tokk);
       WriteLed_on(0);
       _delay_ms(200);
       WriteLed_off(0);
       WriteLed_on(1);
       _delay_ms(200);
       WriteLed_off(1);
       WriteLed_on(2);
       _delay_ms(200);
       WriteLed_off(2);
       WriteLed_on(3);
       _delay_ms(200);
       WriteLed_off(3);
       WriteLed_on(4);
       _delay_ms(200);
       WriteLed_off(4);
       tok0 = 350+tokk;
    }


    int main(void) {

       DDRD=0b11100000;
       DDRB=0b00000111;

       PORTC |= (1<<2);

       PORTD=0b11100000;
       PORTB=0b00000111;
       _delay_ms(500);
       PORTD=0b00000000;
       PORTB=0b00000000;

       if(EepromRead(110)==123) {
       caltok = EepromRead(111);}
         else{caltok = 162;}

       tokd = 2;
       tok0 = 350+caltok;


    while (1==1) {

       tok1 = AdcRead(1);
       tok2 = AdcRead(1);
       tok3 = AdcRead(1);
       tok4 = AdcRead(1);
       tok = (tok1+tok2+tok3+tok4)/4;

       uint8_t j;
       tokmodd=tokmod;
       for(j=allleds; j>0; j--){
         if(tok > (tok0+tokd*(j-1))){
         tokmod=j;
         break;}
         else{tokmod=j-1;}}

       if(tokmodd!=tokmod){
         SetLeds(tokmod);}

       button = readP(PINC,2);
       if(button && !calbut) {
         calbut=1;
         _delay_ms(2000);
         button = readP(PINC,2);
         if(button) {
         calibrovka();
         }}
       if(!button && calbut) {calbut=0;}

       _delay_ms(200);

    }return 0;}
     

    [​IMG]

    правда этот датчик тока весьма малочувствительный - 180мВ/1ампер. А максимальный ток (прежде чем начнет проседать) 300мА. вот и получается, что вся эта штука чтобы адекватно показывать уровень тока (зелеными лампочками) должна регистрировать изменение хотя бы в 0,01вольт, что уже на пределе возможностей АЦП атмеги. Но в принципе работает, если сильно не перемещать в пространстве - какие-то наводки таки влияют, хотя на выходе датчика поставил довольно большой конденсатор. Возможно если засунуть в экранированный корпус будет нормально. А может это и не наводки, а какие-то магнитные явления.

    Обмотка 2А 6,3В через удвоитель (с диодами шотки), потом стабилизатор на 9В. Думал хоть 500мА будет максимальный ток, но не получилось.
     
    BAR__MEN нравится это.
  20. BAR__MEN

    BAR__MEN Гуру

     
    akl нравится это.