Телеметрия (часть 1)
причем количество вложенных прерываний ограничивается только размером стека.
Об этом я и написал, вы опять не хотите вникать в суть, видя лишь верх.
Если вы будете писать код, который не успевает обрабатывать прерывания, очередь прерываний запросто переполнит стек. Что есть путь в никуда, умышленное снижение надёжности своей программы.
Не говоря про то, что стек у АВР, понятие весьма условное 😉
Это не PDP-6, та позволяла вообще на одних прерываниях жить…
Инструмент мощьный, но пользоваться надо осторожно. Я от него отказался и пока не встречал задачи, где без вложенных прерываний ну никак не обойтись, хотя пишу в основном шельф-менеджеры.
>>А вот STATUS регистр нужно сохранить в ручную, но это нужно делать вне зависимости от вложенности.
???
Если когда и сохраняют статус, то при ручном отключении прерываний внутри большого и важного прерывания. Но я это видел крайне редко в чужих кодах… И то если есть опасность включения настроек компилятора, разрешающий вложенность. Так сказать, для страховки (у нас тут основной критерий к коду - возможность повторного использования, реюзибл), на случай переноса куска кода в другую программу или компилятор. Если настройки нет и cli включается, компилер это заоптимизует и уберёт сам.
Об этом я и написал …
Ну допустим не об этом Вы писали а о адресе возврата из прерывания, который вдруг куда-то исчезает. Возможно Вы не смогли правильно выразить свою мысль. Допускаю. Но к сожалению, создается впечатление, что это Вы в суть не вникли, но обязательно хотите оставить за собой последнее слово. Надеюсь, что это впечатление ложное.
Вложенностью прерываний можно и нужно пользоваться. А для того чтобы стек не переполнялся, действительно нужно уметь писать грамотный код (как Вы правильно заметили ранее).
>>А вот STATUS регистр нужно сохранить в ручную, но это нужно делать вне зависимости от вложенности.
А здесь я допустил неточность, признаю. Это нужно делать в С программах только для прерываний, реализованных на ассемблере или с атрибутом naked. Но это было просто к слову.
А по существу, я вообще-то ответил smalltim-у, и поскольку комментировать или задавать вопросы он не стал, значит информация его либо удовлетворила, либо была излишней. Тем не менее, если интересно (smalltim-у), могу предложить свой код проекта OSD (тоже по мотивам Томаса Шерера двухлетней давности) на ATMega 168 , написанный на AVR GCC, с вложенным прерыванием строчного синхро. С его помощью я пытался реализовать графический и текстовый режимы в одном экране, вобщем довольно успешно. Хотя, по себе знаю, хуже нет чем ковыряться в чужом коде.
Тем не менее, если интересно (smalltim-у), могу предложить свой код проекта OSD (тоже по мотивам Томаса Шерера двухлетней давности) на ATMega 168 , написанный на AVR GCC, с вложенным прерыванием строчного синхро. С его помощью я пытался реализовать графический и текстовый режимы в одном экране, вобщем довольно успешно. Хотя, по себе знаю, хуже нет чем ковыряться в чужом коде.
Не знаю как Тимофею но мне было б очень интересно посмотреть 😒 .
Да ради бога. Только e-mail в личку бросьте.
Ну допустим не об этом Вы писали а о адресе возврата из прерывания, который вдруг куда-то исчезает. Возможно Вы не смогли правильно выразить свою мысль. Допускаю. Но к сожалению, создается впечатление, что это Вы в суть не вникли, но обязательно хотите оставить за собой последнее слово. Надеюсь, что это впечатление ложное.
Вложенностью прерываний можно и нужно пользоваться. А для того чтобы стек не переполнялся, действительно нужно уметь писать грамотный код (как Вы правильно заметили ранее).
Я писал о возможности потери вектора возврата при уровни вложенности более 1. Поясню.
Стек может переполниться запросто, причём даже не самими векторами возврата. Любая функция, особенно, если вызывается редко и из прерывания, да написана не тобой, может резко возжелать стек. А там уже данные основного кода. И вот тут очередному прерыванию понадобится сохранить вектор. А некуда! И всё - ниточка прервалась и получаем “адресе возврата из прерывания, который вдруг куда-то исчезает”.
Понятно, что если функции не хватит стека, это само по себе нехорошо. Но проц может и не зависнуть от этого. А вот от потерявшегося прерывания зависнет 100%. Или уйдёт на нулевой адрес (рестарт). Причём переменные в памяти и регистры сохранят свои значения и если код писался без лишней инициализации (есть такие экономщики, ставящие на дефолтные значения по ДШ) армагидец обеспечен.
А вы можете выложить видео с последнего полёта куда-нибудь, где его можно скачать? На том сайте дают только смотреть…
Я писал о возможности потери вектора возврата при уровни вложенности более 1.
Вы, извините, говорите о тривиальных вещах, которые сами собой разумеются. И писали Вы не о возможности потери вектора, а невозможности использования вложенности без какого-то дополнительного кода, который нужно городить.
Надеюсь, что в Ваших программах Вы следите за вложенностью функций (а не только прерываний), потому что при таком подходе и они для Вас также будут представлять угрозу переполнения стека, так как тоже сохраняют в нем адрес возврата.
Вот, “босяцкий” индуктивный рпм сенсор, средствами меги, может работать БЕЗ ПРЕРЫВАНИЙ!
(Катушка- половина рас…еного РЭС-22)
[codebox]
int FeatureCalcRpm;
ADMUX |=_BV(REFS0) |_BV(REFS1); //2.56v at AREF pin
ADCSRA |=_BV(ADEN); //Включаем шнягу…
ACSR |=_BV(ACIC); //Компаратор- как источник сигнала ICP, по отрицательному фронту…
TCCR1B |=_BV(CS11); //|_BV(ICNC1); //Timer1_Freq=XTAL/8 минимальная частота измерения~30.5hz макс.~1mhz
или частота проверки бита захвата. У меня проверка в конце “тела” строчного прерывания 15625херц
if (bit_is_set(TIFR,ICF1)) {
TIFR|=_BV(ICF1); //сброс
TCCR1B = 0x00; //стоп
TCNT1=0x00; //сброс
FeatureCalcRpm=ICR1; //сохраняем
TCCR1B |=_BV(CS11);//|_BV(ICNC1); //старт
}
RotationzPerMinute=(XTAL/8/FeatureCalcRpm)*60; //>>1, если 2 магнита
[/codebox]
Резистором “чувствительность” можно менять область применения 😁
(без него-“измеритель шума”)
А вы можете выложить видео с последнего полёта куда-нибудь, где его можно скачать? На том сайте дают только смотреть…
Если Вы имеете в виду видео последнего полета с улетом 😁 ,то на страничке где вы смотрите, снизу в правом углу есть ссылка на скачать в исходном качестве, но эта ссылка видна только для зарегистрированных.
Вы, извините, говорите о тривиальных вещах,
Вы, извините, уточните сначала, что есть стек в АВР и где находится, а потом мы обсудим дополнительный код.
Если Вы имеете в виду видео последнего полета с улетом 😁 ,то на страничке где вы смотрите, снизу в правом углу есть ссылка на скачать в исходном качестве, но эта ссылка видна только для зарегистрированных.
ИК! 500 метров! 😃 Жёстко… 😵
ИК! 500 метров! 😃 Жёстко… 😵
Дык 😁
Добрый день !
Собрал телеметрию, пока без датчиков давления. Есть проблемка. При выводе на телевизор буквы скачут на полэкрана, при этом сами символы какие-то деформированные. Но если закрыть объектив видеокамеры, всё встаёт на свои места. Вчём дело и куда копать ?
Есть подозрение на диод D1. Поставил что было, точнее уже перепробовал штук 5-6, выпаянных из разных плат, результат одинаковый.
Доброе время суток.
technolog
У Вас наверно камера NTSC используйте PAL камеру, у меня точно такой случай был с моей NTSC камерой
С уважением Эльмир
Добрый день !
Собрал телеметрию, пока без датчиков давления. Есть проблемка. При выводе на телевизор буквы скачут на полэкрана, при этом сами символы какие-то деформированные. Но если закрыть объектив видеокамеры, всё встаёт на свои места. Вчём дело и куда копать ?
Есть подозрение на диод D1. Поставил что было, точнее уже перепробовал штук 5-6, выпаянных из разных плат, результат одинаковый.
Похоже, LM1881 с Вашей камерой ошибочно принимает перепады яркости изображения за строчные синхроимпульсы. Попробуйте увеличить R12 (идет через C12 к ноге номер 2 LM1881) с 510 Ом до 1К.
Раз уж я вылез в тему,
запощу содержимое одного из заголовочных файлов программы автопилота,
при внимательном прочтении становится понятно, что и как и с чем едят.
Пока времени мало, так что продвигаюсь медленно.
#incl*ude "types.h"
typedef struct
{
u16 ssize; // size of this struct in bytes;
u8 ps_needs_reinit; // reititialization takes place once per power/reset cycle
u8 pwm_needs_calibration; // calibration takes place on usb command or after hwb press
u8 pyro_needs_calibration; // calibration takes place after hwb press
u8 compass_needs_calibration; // calibration takes place on usb command or after hwb press
u8 board_state; // autopilot board state
// 0 - idle in flight (just logging data to memory in flight)
// 1 - idle with USB connected (just communicationg to USB)
// 2 - stabilization active (logging + stabilization)
// 3 - autopilot active (logging + autopilot)
// 4 - calibration active (activates on hwb press or on USB command)
// 5 - menu is active (activates on hwb press when tb is present and USB is not connected)
u8 tb_connected; // telemetry board connection detection takes place on power/reset
// 0 - telemetry board is not connected,
// 1 - telemetry board is connected
u8 usb_connected; // usb connection detection takes place on USB interrupt activation
// 0 - autopilot board is not connected to USB
// 1 - autopilot board is connected to USB
u8 spi_state; // 0 - reads data from tb (when idle/stabilization/autopilot states are active and tb sends data)
// 1 - writes data (menu) to tb (when USB is NOT connected and idle mode is active)
// 2 - flashes tb (when USB is connected and flash command is sent)
// 3 - writes data to memory (when idle/stabilization/autopilot states are active, or when tb program is being stored to memory)
// 4 - reads data from memory (when USB is connected and log is being downloaded)
u16 mem_write_bytenumber; // counters: byte within page, page number
u16 mem_write_pagenumber;
u16 mem_read_bytenumber;
u16 mem_read_pagenumber;
u8 mem_state; // memory state
// 0 - memory is idle
// 1 - memory is being written
// 2 - memory is being read
u8 eeprom_state; // eeprom state
// 0 - eeprom is idle
// 1 - eeprom is being written
// 2 - eeprom is being read
u32 log_samplecount; // number of last log sample written to memory
u16 log_samplesize; // size of log sample in bytes
u16 out_pwm_curwidth[4]; // (scales to min..max range)
u16 in_pwm_curwidth[4]; // (scales to min..max range)
u8 gps_connected; // 0 - GPS module is not connected;
// 1 - GPS module is connected;
u8 gps_initialized; // 0 - start position is not stored;
// 1 - start position is stored;
u8 gps_datavalid; // 0 - current GPS data is not valid
// 1 - current GPS data is valid
u8 gps_fixmode; // 0 - "N/A"
// 1 - "2D"
// 2 - "3D"
u8 gps_numsatellites; // 0 - "N/A"
// 1 - "2D"
// 2 - "3D"
u8 gps_latlon_string[32];
u8 gps_numvalidstrings; // number of valid srings received from GPS, need at least 20 with "2D" or "3D" fixmode to store start position
u8 gps_incoming_string[85]; // string that is being filled with NMEA info over USART
u8 gps_current_string[85]; // complete string that is being parsed
u32 gps_startlat; // start position by GPS, in 0.001s of minutes
u32 gps_startlon; // start position by GPS, in 0.001s of minutes
u32 gps_startalt; // start altitude by GPS, in meters
u8 gps_EW; // char "E"/"W" that defines current hemisphere
u8 gps_NS; // char "N"/"S" that defines current hemisphere
u32 gps_curlat; // current position by GPS, in 0.001s of minutes
u32 gps_curlon; // current position by GPS, in 0.001s of minutes
u16 gps_curalt; // current altitude by GPS, in meters
u16 gps_curdist; // current distance to base by GPS, in meters
u16 gps_curspeed; // current ground speed by GPS, in kph
u16 gps_curazimuth; // current ground speed azimuth by GPS, in degrees
u16 baro_curalt; // current altitude by baro, in meters
u16 baro_curspeed; // current airspeed by baro, in kph
s16 pyro_x_diff; // output difference on x axis pyrometers
s16 pyro_y_diff; // output difference on y axis pyrometers
s16 pyro_z_diff; // output difference on z axis pyrometers
s16 pyro_maxdiff; // maximum difference on any axis
// used for normalization/angle calculation when pyros at Z axis are not available
s8 pyro_roll; // roll angle calculated by pyro output
s8 pyro_pitch; // pitch angle calculated by pyro output
u8 compass_sr_state; // compass set/reset state
// 0 - set
// 1 - reset
s16 compass_x; // magnet field projection at compass x axis
s16 compass_y; // magnet field projection at compass y axis
s16 compass_z; // magnet field projection at compass z axis
u16 compass_heading; // heading calculated by compass output;
u16 adc_rawdata[8]; // raw data from ADC after taking sum of 64 samples per channel
u16 cps; // main program cycles per second
u16 currentcycle; // current main program cycle number (within a second)
u16 second; // second number
} ap_state_type; // TYPE FOR GLOBALLY VISIBLE VARIABLE THAT HOLDS AUTOPILOT STATE
typedef struct
{
u16 pwm_minwidth[4]; // PPM width (in timer clock cycles) for throttle, aileron, elevator and rudder channels.
u16 pwm_maxwidth[4]; // All the corrective actions depend on that calibration.
// These are not set by PC application.
u16 compass_c_ax; // compass calibration values. These are not set by PC application
u16 compass_c_bx;
u16 compass_c_ay;
u16 compass_c_by;
u16 compass_c_az;
u16 compass_c_bz;
u8 invert_channel[4]; // 0 - channel is not inverted
// 1 - channel is inverted
u8 vtailmix; // 0 - mix for ailerons/elevator is not used
// 1 - mix for ailerons/elevator is used (models having V-tail, ailevon etc);
u8 tilt_stab_smult; // multiplier characterizing sensitivity of feedback on tilt, while stabilization is active.
// 16 corresponds to normal (1) sensitivity.
// 16=full span of roll/pitch angles detected by autopilot board produces
// full span of output pwm width, thus, maximum roll corresponds to maximum aileron corrective action.
//
// output values beyond allowe ppm range are clamped.
//
// example:
// 32=1/2 of maximum roll corresponds to maximum corrective action
// example:
// 8=maximum roll corresponds to 1/2 of maximum corrective action
// This field MUST be set
u16 target_altitude; // altitude at which autopilod must bring the plane home (in meters). This field MUST be set
u16 min_altitude; // minimal and maximal allowed altitude values for autopilot, getting closer to these values
u16 max_altitude; // causes 100% of corrective action (elevator turn, throttle control)
u16 target_airspeed; // air speed at which autopilot must bring the plane home (in kph). 0=target airspped is not set
u16 min_airspeed; // minimal and maximal allowed airspeed values for autopilot, getting closer to these values
u16 max_airspeed; // causes 100% of corrective action (throttle control)
u8 target_throttle; // trottle at which the autopilot must bring the plane home (in percents). 0=target throttle is not set
u8 min_throttle; // minimal and maximal allowed throttle values for autopilot, getting closer to these values
u8 max_throttle; // causes 100% of corrective action (throttle control)
u16 target_distance; // distance (meters) to base at which autopilot thinks it brought the plane home and goes off.
// 0-autpilot does not go off automatically.
u8 max_roll; // maximum roll and pitch angles allowed for maneuvering while autopilot is active
u8 max_pitch; // these fields MUST be set
u8 ap_rollenable; // 0 - autopilot does not allow roll when active
// 1 - autopilot does allow roll when active (not applicable for models w/o ailerons)
u16 ap_alarm_on_voltage; // 0 - alarm on battery voltage disabled
// any other value - alarm when battery voltage gets lower than value
u16 ap_active_on_voltage; // 0 - autopilot goes active on battery voltage disabled
// any other value - autopilot goes active when battery voltage gets lower than value
u16 ap_alarm_on_mah; // 0 - alarm on mAh value disabled
// any other value - alarm when mAh gets higher than value
u16 ap_active_on_mah; // 0 - autopilot goes active on mAh value disabled
// any other value - autopilot goes active when mAh gets higher than value
u16 ap_alarm_on_dist; // 0 - alarm on distance disabled
// any other value - alarm when distance gets higher than value
u16 ap_active_on_dist; // 0 - autopilot goes active on distance disabled
// any other value - autopilot goes active when distance gets higher than value
u16 ap_alarm_on_alt; // 0 - alarm on altitude disabled
// any other value - alarm when altitude gets higher than value
u16 ap_active_on_alt; // 0 - autopilot goes active on altitude disabled
// any other value - autopilot goes active when altitude gets higher than value
u8 ap_alarm_on_signal; // 0 - alarm on RC signal loss disabled
// any other value - alarm when RC signal is lost for more than value seconds
u8 ap_active_on_signal; // 0 - autopilot goes active on RC signal loss disabled
// any other value - autopilot goes active RC signal is lost for more than value seconds
s8 compass_inclination; // magnet field inclination angle
// this field MUST be set
} autopilotboard_eeprom_constants_type; // TYPE FOR GLOBALLY VISIBLE VARIABLE THAT HOLDS EEPROM CONSTANTS
Прыжки надписей, в целом, поборол установкой телеметрии в то место, где она и должна находится - т.е. между камерой и видеопередатчиком. Первый раз для проверки работоспособности она была полключена между видеоприёмником и телевизором.
Однако появился вопрос другого плана. На цифрах и буквах появляются (и пропадают) лишние сегменты - это хорошо видно в прикреплённом видеофайле.
А может это так и должно быть?
to smalltim
изменение номинала резистора от 240 ом до 2 ком заметного эффекта не даёт, да и неактуально уже.
to drweb
камера чёрно-белая KPC-S190S (взял для экспериметов) какой там стандарт виеосигнала - хз.
PAL/SECAM/NTSC разве не станарты цветности?
Ух ты, какая интересная фигня. Это точно не мусор в памяти - сломавшись в одном месте, буквы не ломаются в другом. Похоже на то, что иногда нужная нога атмеги не переходит в 0, когда ее просят. Я никогда с таким не встречался, хотя через меня прошел уже не один десяток телеметрий.
Можно фото платы и системы в сборе?
Вот плата телеметрии почти собраная. В реальности она не такая страшная. Делал плёночным фоторезистом, шаблон перерисовал в layoute. Внёс небольшие изменения (кварц в другом корпусе, некоторые дорожки другой формы).
“Система” в сборе. Передатчик на модуле AWM630, на плате ещё бует усилитель и модем.
Хорошая платка получилась.
А что за диод? Больно жирный что-то. Нужен слаботочный, высокочастотный, с как можно меньшей емкостью перехода.
Да, и еще. Я понимаю, что вроде как бы всё равно, но я бы подключил плату телеметрии между камерой и передатчиком, а не отдельным видеокабелем к передатчику.
У NTSC поля следуют с частотой 60 Гц, в поле 525 строк. У PAL поля следуют с частотой 50 Гц, в поле 625 строк. На NTSC букофки пойдут в полный расколбас.
А что за диод? Больно жирный что-то. Нужен слаботочный, высокочастотный, с как можно меньшей емкостью перехода.
Диод noname. Сегодня куплю что-нибудь из этого:
1N4148
BAS16
BAV70
BAV99
PMLL4148
Все они “быстрые” 4-6 нс, ёмкость перехода окол 1,5pF.
kamera samoe qlavnoe tochno ne NTSC ?
u menya tam voobshe stoit diod kd510 sovetskiy nash rodnoy, rabotaet kak chiki chiki 😉