В моём случае плата ComMotion motor driver for 4 motors столкнулся с проблемой - при настройке её в режим автономного управления каждым мотором без энкодера моторы М1 и М3 управляются нормально(с реверсом), а М2 и М4 при любом задании вращаются в одну сторону. Собственно это первый вопрос, хотя понимаю что это не от AMPERKA и ответа не смогу дождаться. Вопрос второй - при анализе кода (привожу фрагмент): Код (C++): if(command==3 && (packsize==7 || packsize==9)) //============================ Motor Control ======================================================================= { if((configuration==3 || configuration==19) && packsize==9) // Individual motor control { for(byte i=0;i<4;i++) { mspeed[i]=datapack[i*2+1]*256+datapack[i*2+2]; } } else // Omni or Mecanum Wheels { velocity=datapack[1]*256+datapack[2]; angle=datapack[3]*256+datapack[4]; rotation=datapack[5]*256+datapack[6]; if(velocity>255) velocity=255; if(velocity<-255) velocity=-255; while(angle>=360) { angle-=360; } while(angle<0) { angle+=360; } if(rotation>255) rotation=255; if(rotation<-255) rotation=-255; Trigonometry(); } command=255; return; } выявил что mspeed=datapack[i*2+1]*256+datapack[i*2+2]; по идее надо заменить на mspeed=(datapack[i*2+1] <<8)+datapack[i*2+2]; или даже mspeed=(datapack[i*2+1] <<8) | datapack[i*2+2]; я не могу ориентироваться на Атмегу, т.к. не знаю его специфики а занимаюсь только ARM. допускается ли делать сдвиг на 8 бит влево вместо умножения на 256 - это увеличит скорость обработки более чем в 8 раз (исходя из битового анализа). В ARM подобная операция выполняется за один машинный такт (регистр-регистр). Про Атмега сказать не могу - не разбирался - может умножение тоже есть с результатом в 16 бит из двух операнодв по 8 бит. Если это можно, то я изменю везде эти ненужные умножения на сдвиг - это нормально? Заранее спасибо!!!
Сдвиг - это нормально. Главное чтобы биты не выпали за размерность переменной и не встали на знаковое место, если переменная знаковая. Только нужно ли увеличивать скорость в 8 раз? Моторы штука инерционная.
Нет - имеется ввиду выполнение сдвига всётаки более чем в 8 раз быстрее выполняется, чем умножение на 256 - операция сдвиг-анализ бита-сложение и повтор, пока 8 бит не пройдёт. а размерность: mspeed=(datapack[i*2+1] <<8) | datapack[i*2+2]; решается так: mspeed=(signed short)(datapack[i*2+1] <<8) | (signed short)(datapack[i*2+2]); т.е. ткнуть компилятор носом. Спасибо! Буду пилить шилд!
В AVR нет операции сдвига на определённое число разрядов, а есть только операция сдвига на 1 разряд. И если надо сдвинуть на 8 разрядов, то такой сдвиг выполняется в цикле, что увеличивает время выполнения. В то же время операция умножения занимает 2 такта, не зависимо от операндов. Поэтому эту операцию применяют в место операции сдвига.
Спасибо: подсмотрел - есть : MUL MULS MULSU FMUL FMULS FMULSU и 16-битный результат в регистры R0,R1. Ещё раз спасибо, а то наварнакал бы!
Нечаянное продолжение - по работе приводов. В том устройстве, над которым ковыряюсь ошибка в прошивке - ComMotion_Shield_V2.0. Именно в том месте, где мне надо - режим автономного управления одним из 4 двигателей без применения энкодера. А именно моторы 1 и 2 всегда вращаются в одном направлении, когда 3 и 4 согласно заданию -255...255 - с реверсом. ну это только мои испытания: Код (C++): if(command<32) Commands(); // respond to command from I²C bus or Serial interface if(encoders) { Motors(); // if encoders are enabled then use then to control motor speeds } else // if encoders are disabled then feed speed values directly to PWM output { analogWrite(pwmapin,abs(mspeed[mcu*2])); // set motor A speed digitalWrite(dirapin,mspeed[mcu*2]>0); // set motor A direction analogWrite(pwmbpin,abs(mspeed[mcu*2+1])); // set motor B speed //digitalWrite(dirаpin,mspeed[mcu*2+1]>0); //до исправления digitalWrite(dirbpin,mspeed[mcu*2+1]>0); //после // set motor B direction } теперь нормально!