Mieciu11 Opublikowano 15 Grudnia 2017 Opublikowano 15 Grudnia 2017 Witam, Ostatnio bardzo mocno zainteresował mnie temat budowy a właściwie złożenia jak najniższym kosztem aparatury, która z powodzeniem miałaby być używana w sterowaniu kołowymi modelami rc. Projekt będzie oparty na fabrycznym module nadawczym turnigy 9x, który od jakiegoś czasu leży u mnie bezczynnie. Głównym zadaniem jest wygenerowanie sygnału ppm wszystkich kanałów i sterowanie każdym z nich odpowiednim czasem trwania impulsu od 1 do 2milisekund(minimalne i maksymalne wychylenie serwa). Idealnie nadaje się do tego arduino w moim przypadku nano które na aliexpress można zdobyć za około 7zł. Najtrudniejszym jest napisanie programu, który to wszystko obsłuży, więc na razie wykorzystam kod który można znaleźć w sieci. Być może jak trochę przysiądę do programowania to uda się coś takiego napisać Niestety twórca nie przewidział w kodzie trymerów ani rewersów, więc pozostanie tylko zewnętrznie wpływać na działanie kanałów. Rewers można uzyskać np prostym przełącznikiem zmiany kierunku obrotów silnika, który będzie przełączał na potencjometrze 5v oraz GND. Nie mam jednak pomysłu jak rozwiązać problem trymowania. W kodzie autor przewidział sterowanie sześcioma kanałami. Potencjometry do nich będą podpięte do wejść arduino a0-a5, natomiast sygnał ppm wychodzi z pinu cyfrowego D13 wprost do modułu. Podłączenie tak jak na schemacie. Dziś pierwsze próby i wszystko ładnie działa. cdn. Wątek, z którego zaczerpnąłem kod: https://www.rcgroups.com/forums/showthread.php?2037080-DIY-Arduino-joystick-to-PPM Kod: #define NB_WAY 6 // number of ways #define LOW_LENGTH 300 // How long last (in µs) a low between 2 pulses #define MIN_PPM_PULSE 600 // minimum pulse length in µs #define PPM_PULSE_LENGTH 1200 // how much more µs will last the max pulse length #define PACKET_LENGTH 20000 // How long (µs) last a full trame // trame length is fixed ! Every trame will make PACKET_LENGTH µs ! // MUST NO BE MORE THAN 32ms !!! (timer's prescaler constraint) #define PPM_OUTPUT 13 // OUTPUT PIN int way_value[NB_WAY]; int way_pin[NB_WAY]; int way_min[NB_WAY]; int way_max[NB_WAY]; int i = 0; int p = 0; // temp var for duty cycle calculation int last_i_timer = 0; // last way's value sent through PPM signal unsigned long int trame_elapsed_time = 0; bool output_state = LOW; void setup() { // ppm output : pinMode(PPM_OUTPUT, OUTPUT); digitalWrite(PPM_OUTPUT, output_state); // inits arrays for(i=0;i<NB_WAY;i++) { way_pin = 14 + i; pinMode(way_pin, INPUT); way_value = analogRead(way_pin); way_min = way_value; way_max = way_value; } // init timer cli(); // desactivation interruptions TCCR1A = 0x00; // set timer1 registers to 0 TCCR1B = 0x00; TIMSK1 = 0x00; OCR1A = 65535;// set to the max // CTC mode: TCCR1B |= (1 << WGM12); // prescaler to 8, that allow (@16mhz) 32.8ms trame TCCR1B |= (0 << CS10); TCCR1B |= (1 << CS11); TCCR1B |= (0 << CS12); // timer activation TIMSK1 |= (1 << OCIE1A); sei(); for(i=0;i<NB_WAY;i++) { way_min = 512; way_max = 1023; } } ISR(TIMER1_COMPA_vect) { TIMSK1 &= (0 << OCIE1A); if(output_state) { // END OF A HIGH, we have to wait LOW_LENGTH ms before next pulse output_state = LOW; digitalWrite(PPM_OUTPUT, output_state); OCR1A = 2 * LOW_LENGTH; // set when next timer interruption will occur TIMSK1 |= (1 << OCIE1A); // restart timer trame_elapsed_time += LOW_LENGTH; } else { // END of a LOW_LENGTH, new pulse ! output_state = HIGH; digitalWrite(PPM_OUTPUT, output_state); if(last_i_timer >= NB_WAY) // last way, so wait until next packet { OCR1A = (2 * PACKET_LENGTH) - (trame_elapsed_time * 2);// set when next timer interruption will occur TIMSK1 |= (1 << OCIE1A); // restart timer last_i_timer = 0; trame_elapsed_time = 0; } else { OCR1A = 2 * way_value[last_i_timer];// set when next timer interruption will occur TIMSK1 |= (1 << OCIE1A); // restart timer last_i_timer ++; trame_elapsed_time += way_value[NB_WAY]; } } } void loop() { for(i=0;i<NB_WAY;i++) { // Read current value of way i : p = analogRead(way_pin); // auto calibration... if(p > way_max) way_max = p; if(p < way_min) way_min = p; // Arduino map function sucks way_value = MIN_PPM_PULSE + PPM_PULSE_LENGTH * (float)((float)(p - way_min) / (float)(way_max - way_min)); } }
Gość z.x Opublikowano 16 Grudnia 2017 Opublikowano 16 Grudnia 2017 To forum raczej dla modelarzy a nie elektroników i informatyków (ale nie kasują tzn że jest OK) Choć czasem coś sie tu pokazuje. Ja też coś buduję, ale jeszcze mi to zejdzie bo zmieniam architekturę z AVR na ARM. I mój projekt ma być dużo bardziej rozbudowany. Jeśli dam radę to z chęcią pomogę, ale od razu mówię że jak chcesz mieć konkret do czeka Cię dużo pracy i z kodem i z elektroniką. Na wstępie Ci mogę powiedzieć że twój kod będzie szalał Tzn, musisz mieć filtry RC do potencjometrów i w kodzie ustabilizować odczyt. bo na 100% wszystko będzie skakać To jest norma. Trymery, no cóż są dwa rozwiązania: 1. Używasz innych kanałów ADC do trymowania, ale wtedy masz dwa razy mniej kanałów, z 6 schodzisz na 3. Lepiej z 8 na 4. 2. Używasz mechanicznych trymerow, chyba najlepsze rozwiązanie. 3*) Na pewno bedziesz potrzebowal trymerow? Rewersy? Możesz użyć przełączników i podpiąć do innych pinów, w zależności od stanu, zmieniasz wartość na wyjściu PPM. Mnie się udało wysterować FRSY XJT, póki co tylko PPM, może uda się wskoczyć na PXX. Albo coś nowszego. Kolejna sprawa, nie używaj bibliotek arduino. Osobiście uważam że przy dużych projektach są mega nie optymalne. Oczywiście ostateczny wybór pozostawiam Tobie. Wydajność AVR. Uważaj na bolączki arch AVR. Dzielenie zajmuje kupę czasu. Póki co ten kod jest prosty, może nie odbije się bardzo na efekcie końcowym, ale musisz o tym wiedzieć. Pozdro i powodzenia!
Rekomendowane odpowiedzi