Activity

Тестирование моторов+ESC на предрасположенность к потере синхронизации

Код для ардуино. Пояснения и результаты чуть позже.
Обсуждение: rcopen.com/forum/f123/topic380040

/*************************************************************************************
  Sergey dROb, Oct 2014, 

  This program will test ESC+motor (or servo), sending range of valid PPM signals to the output pin at "servoPin"
  Primarily, this is used to detect sync issues, happening when Motor is quickly accelerating from low to high speed.

  If LCD display is connected - it displays number of test and Start-End microseconds of PPM signal (you can then record, which scenario is problem for your motor)

  Connection: Plug the LCD Keypad to the Arduino. Output PPM will be on servoPin. Conect GND and servoPin to ESC.
  Discussion: 
**************************************************************************************/

#include <LiquidCrystal.h>
#include <Servo.h>

Servo myservo;  // create servo object to control a servo

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);           // select the pins used on the LCD panel

int servoPin = 22;

int lcd_key     = 0;
int adc_key_in  = 0;

#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5


void setup(){
  lcd.begin(16, 2);
  lcd.setCursor(0,0);
  lcd.print("Starting motor");

  lcd.setCursor(0,1);
  lcd.print("In 3 seconds..");
  myservo.attach(servoPin);

  myservo.writeMicroseconds(950);  // Init ESC

  delay(3000); // Waiting 3 seconds to avoid chopping of user hands

  myservo.writeMicroseconds(1250); // Start motor on low speed
}


void loop(){

  int test_no=1;
  int start_uS;
  int end_uS;
  int tact_delay=1000;

  lcd.clear();
  lcd.print("No: Start: End:");


  // Main cycle - start series of cycles, when motor jumps from set of speeds to higher set of speeds.
  for (start_uS=1100; start_uS<=1900; start_uS+=100){  // Start PPM from which motor will jump to End PPM
    servoOutput(start_uS);
    delay(tact_delay);
      for (end_uS=start_uS+100; end_uS<=1900; end_uS+=100){ // End PPM of the current cycle
        displayData(test_no, start_uS, end_uS);

        servoOutput(end_uS);
        tact_delay=end_uS - start_uS; if (tact_delay<400) tact_delay=400;// Intellectual delay. Pause will be bigger if motor have to change the speed a lot. But not less 0.4 sec
        delay(tact_delay);
        servoOutput(start_uS);
        delay(tact_delay);
        test_no++;
     }
  }

  lcd.setCursor(0,1);

  lcd_key = read_LCD_buttons();
  dispatch_keys(lcd_key);
}


void servoOutput(int uS){
  myservo.writeMicroseconds(uS);
}

void displayData(int test_no, int s_uS, int e_uS){
  lcd.setCursor(1,1);
  lcd.print(test_no);
  lcd.setCursor(5,1);
  lcd.print(s_uS);
  lcd.setCursor(11,1);
  lcd.print(e_uS);
  lcd.print("     ");
}

//////////////////////////////////////////////////////////////////////////////
// This is actually not really used. Added to be able to get Keypad presses //
//////////////////////////////////////////////////////////////////////////////

int read_LCD_buttons(){               // read the buttons
    adc_key_in = analogRead(0);       // read the value from the sensor

    if (adc_key_in > 1000) return btnNONE;

    if (adc_key_in < 50)   return btnRIGHT;
    if (adc_key_in < 250)  return btnUP;
    if (adc_key_in < 450)  return btnDOWN;
    if (adc_key_in < 650)  return btnLEFT;
    if (adc_key_in < 850)  return btnSELECT;

    return btnNONE;                // when all others fail, return this.
}




void dispatch_keys(int key){
     switch (key){

       case btnRIGHT:{
            break;
       }
       case btnLEFT:{
            break;
       }
       case btnUP:{
             lcd.print("UP    ");
             break;
       }
       case btnDOWN:{
             lcd.print("DOWN  ");
             break;
       }
       case btnSELECT:{
             lcd.print("SELECT");
             break;
             setup();
       }
       case btnNONE:{
             ("NONE  ");
             break;
       }
   }

}
Код для использования Акселерометра LIS302DLTR в MultiWii

Убил блин почти целый день, но сделал таки кусок кода для применения данного датчика:

// ************************************************************************
// LIS302DL I2C Accelerometer
// ************************************************************************
#if defined(LIS302DL)
#define LIS302  0x1D
#define LIS302_CTRL_XEN 0
#define LIS302_CTRL_YEN 1
#define LIS302_CTRL_ZEN 2
#define LIS302_CTRL_STM 3
#define LIS302_CTRL_STP 4
#define LIS302_CTRL_FS 5
#define LIS302_CTRL_PD 6
#define LIS302_CTRL_DR 7


void ACC_init(){
  i2c_writeReg(LIS302 ,0x20 , _BV(LIS302_CTRL_PD) | _BV(LIS302_CTRL_XEN) | _BV(LIS302_CTRL_YEN) | _BV(LIS302_CTRL_ZEN) );
  acc_1G = 56; // Странно что не 64, но практика показала, что именно 56
}

void ACC_getADC(){
  TWBR = ((F_CPU / 400000L) - 16) / 2; // change the I2C clock rate to 400kHz
  i2c_getSixRawADC(LIS302,0x28+0x80);

  ACC_ORIENTATION( int8_t(rawADC[1]),
                   int8_t(rawADC[3]),
                   int8_t(rawADC[5]));
  ACC_Common();
}
#endif
Супер-застёжка 3M Dual Lock

ПРЕДВАРИТЕЛЬНАЯ ВЕРСИЯ. ПРОСЬБА НЕ ПИНАТЬ


Давно уже открыл для себя эту штуковину, и вот решил обобщить свои знания по этой супер-липучке. А так же провел тест на силу удержания.

Результаты тестирования.
 Для тестирования были вырезаны два куска Dual Lock размерами 25x27мм. Хотел 25x25 но тогда резать пришлось бы прямо по одной из линий грибков, что некрасиво. Один кусок был прикреплён на груз, другой - к длинной алюминиевой к палке, за которую будем груз поднимать. В роли груза выступил набор инструментов весом 4600 грамм.

Результаты тестирования показали следующие значения “на отрыв”:

  1. 3150гр
  2. 3000гр
  3. 3500гр
  4. 4600гр
    5. >4600гр
    6. >4600гр

Первые три теста я пытался сопоставить два куска Dual Lock друг к другу рисунком, и как стало ясно - это самый неудачный случай.
Последующие три теста показали что если клеить куски под некоторым углом друг к другу - соединение получается самым надёжным. При этом, в последнем тесте, липучки были наклеены под углом ровно 45 градусов, а это значит, что мы потеряли около 30% пятна контакта. Тем не менее соединение выдержало более 4.5кг веса. Грубо, это означает силу удержания в 1кг на 1см.
Любопытно, что тест на сдвиг показал столь же надёжное удержание

При этом надо отметить, что при соединении - сила, с которой поверхности будут держаться, чувствуется сразу. Т.е. если соединить липучки удалось слишком легко, без громкого щелчка - в случае если нужна максимальная сила, соединение лучше сделать заново. Но если речь идет о камере массой в 50 грамм, которая крепится на таком кусочке скотча, то оторвётся она только при перегрузке в 100G, хотя сомневаюсь что детали наших самолётов выдержат хотя бы 20G 😃

Единственное, к чему липучка клеится с трудом и держится плохо - это один из типов термоусадочной трубки, такая толстостенная и жирная на ощупь. К обычной термоусадке REXANT клеится нормально.

При наклейке на пористые поверхности вроде EPP, Потолочке, или фанеры, поверхность предварительно грунтуется, например Супер-Клеем, эпоксидкой, или даже Моментом (случай с термоусадкой)

Инициализация GPS модуля с помощью Arduino

Спаял себе GPS модуль на базе EB-500, но он по умолчанию работает на скорости 9600 бод, а для CL-OSD нужно 4800. Думал, как проще модуль сконфигурировать - решил через Arduino, которая здорово мне уже помогла в reverse engineering USB-GPS’а (использовал ардуину в качестве пробника-приемника UART, при поиске ноги c нужными нам NMEA данными). Первая проба была в использовании Ардуины в виде транслятора команд из терминала в GPS модуль, но что-то у меня не заработало. То есть данные из модуля идут, а в модуль - не лезут.

void loop()
{
  if (mySerial.available())
    Serial.print((char)mySerial.read());
  if (Serial.available())
    mySerial.print((char)Serial.read());
}

В принципе при ближайшем рассмотрении становится понятно, почему не работает - пример выдран из примера по библиотеки NewSoftSerial, и обмен между портами происходит по одной букве. А GPS модуль требует чтобы отправлена была сразу команда, а здесь он видит непонятно что. Ради интереса надо поправить позже.

Я не стал настаивать, и сделал программку, которая автоматически отправляет команды из Ардуины в модуль. Код ниже, но было несколько моментов, из-за которых плевое дело растянулось на пару часов:

  1. Поскольку GPS питается от 3.3В, а Ардуина - 5В, на выход Ардуины - поставил стабилитрон на 3В.
  2. Похоже, GPS не хочет менять скорость на пониженную, без снижения количества / скорости выводимых параметров. Поэтому алгоритм такой - снижаем скорость обновления до 1Гц, и отключаем почти все выводимые параемтры (я оставил GGA). После этого отправляем команду на переключение на 4800
  3. Похоже, надо соблюдать какие-то тайминги, или ждать освобождения порта в GPS. Я этого не делал, а просто перезапускал программу несколько раз, дожидаясь когда мне повезёт. Обычно на 2-3 раз команда проходит
  4. Похоже, по ссылке, которую давал falke5 в теме по E-OSD, в одной из команд ошибка. Вот эта команда не хотела выполняться: $PMTK314,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0*29 - вероятно ошибка в контрольной сумме. Я применил вместо этого $PMTK314,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29 - отключает вообще всё, кроме GGA, но работает. После переключения на 4800 можно всё обратно включить.
#include <NewSoftSerial.h>

NewSoftSerial mySerial(2, 3); //GPS модуль на пинах 2 и 3

void setup()
{
  Serial.begin(9600); // Соединяемся с ПК
  Serial.println("Hit me!");

  // начинаем связь на скорости 9600
  mySerial.begin(9600);
  delay(1000);

  // Первым делом надо занизить все параметры - ставим 1гц обновление и выдачу только данных GGA
  mySerial.println("$PMTK300,1000,0,0,0,0*1C");   // скорость обновления 1гц
  Serial.println("Command sent: $PMTK300,1000,0,0,0,0*1C");
  while (mySerial.available()) Serial.print((char)mySerial.read()); // Смотрим результат
  delay(1000);

  mySerial.println("$PMTK314,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29"); // выдача только GGA
  Serial.println("Command sent: $PMTK314,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29");
  while (mySerial.available()) Serial.print((char)mySerial.read()); // Смотрим результат
  delay(1000);

  /*
  // Это инициализация выдачи GGA, GSA, RMC, VTG, ZDA - её запустим уже в следующий раз, когда модуль уже будет проинициализирован на 1Гц, GGA, и 4800baud
  mySerial.println("$PMTK314,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,5,0*2D"); // выдача только GGA
  Serial.println("Command sent: $PMTK314,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,5,0*2D");
  while (mySerial.available()) Serial.print((char)mySerial.read()); // Смотрим результат
  delay(1000);*/

  mySerial.println("$PMTK251,4800*14");  // Переключаем модуль на 4800
  Serial.println("Command sent: $PMTK251,4800*14");
  while (mySerial.available()) Serial.print((char)mySerial.read()); // Смотрим результат
  delay(1000);*/

  // Настройка закончена, теперь начинаем связь теперь на скорости 4800
  mySerial.begin(4800);
  delay(1000);

}

void loop() // Готово, теперь просто смотрим на входящие данные
{
  if (mySerial.available())
    Serial.print((char)mySerial.read());
  /*if (Serial.available())
    mySerial.print((char)Serial.read()); // Транслировать данные с порта компьютера на ардуину и на GPS (у меня вроде не работало) */
}

P.S. Возможно, если у кого-то возникнут проблемы с командой PMTK314, есть возможность включать/отключать выдаваемые опции по отдельности (я не пробовал):

GGA: Вкл => $PSRF103,00,00,01,01*25 , Выкл =>$PSRF103,00,00,00,01*24
GLL: Вкл => $PSRF103,01,00,01,01*24 , Выкл => $PSRF103,01,00,00,01*25
GSA: Вкл => $PSRF103,02,00,01,01*27 , Выкл => $PSRF103,02,00,00,01*26
GSV: Вкл => $PSRF103,03,00,01,01*26 , Выкл => $PSRF103,03,00,00,01*27
RMC: Вкл => $PSRF103,04,00,01,01*21 , Выкл => $PSRF103,04,00,00,01*20
VTG:Вкл => $PSRF103,05,00,01,01*20 , Выкл => $PSRF103,05,00,00,01*21

Простейший микрофонный усилитель на ОУ


Случайно завалялось пару часов свободного времени, и я решил потратить их с толком, а именно изготовить усилитель микрофона для FPV полётов, - надоело летать в тишине. На этом и остановился - нашел пару схем усилителей на Операционных Усилителях. Начал копаться в своем электронном “разборе”, и как назло - ни одного операционника 😦 Но, заглянув в закрома новых запчастей, - о чудо!, оказывается я когда-то купил два ОУ LM358, но при этом почему-то в корпусе SO8 (SMD) 😦 Была не была - конструируем свою первую схемку на SMD компонентах. Вооружившись феном - выпаял из старой магнитолы разом все чип-резисторы и конденсаторы. За основу взял вот эту схему. За 10 минут, в программе для разводки печатных плат Microsoft Paint развёл данную платку.

5 минут утюжком, 20 минут травления, час пайки - готово!! Долго меня смущала постоянная составляющая на выходе, но потом всё же рискнул подключить к усилку. (на выходе стоял развязывающий конденсатор, но при измерении вольтметром показывал медленно падающее постоянное напряжение) Всё прекрасно работает! Из минусов - обошёлся без регулировки обратной связи (усиления), но вроде громкость нормальная. А также, из-за того, что конденсатор С1 подбирал “на глазок” (так и не понял, как они маркируются), похоже подобрал очень маленькую ёмкость. Много высоких частот и мало низких. Но в целом доволен!!

P.S. Вместо подстроечного резистора у меня 1МОм, - думаю многовато. Лучше 200-500кОм.
P.P.S. рисунок печатной платы отзеркален, то есть уже готов к печати и переводу утюгом. Печатался прямо из Paint с масштабом 15%. Думаю лучше перепроверить при печати по размеру микросхемки