Телеметрия (часть 1)

Dikoy
dmk:

причем количество вложенных прерываний ограничивается только размером стека.

Об этом я и написал, вы опять не хотите вникать в суть, видя лишь верх.
Если вы будете писать код, который не успевает обрабатывать прерывания, очередь прерываний запросто переполнит стек. Что есть путь в никуда, умышленное снижение надёжности своей программы.
Не говоря про то, что стек у АВР, понятие весьма условное 😉
Это не PDP-6, та позволяла вообще на одних прерываниях жить…
Инструмент мощьный, но пользоваться надо осторожно. Я от него отказался и пока не встречал задачи, где без вложенных прерываний ну никак не обойтись, хотя пишу в основном шельф-менеджеры.

>>А вот STATUS регистр нужно сохранить в ручную, но это нужно делать вне зависимости от вложенности.
???
Если когда и сохраняют статус, то при ручном отключении прерываний внутри большого и важного прерывания. Но я это видел крайне редко в чужих кодах… И то если есть опасность включения настроек компилятора, разрешающий вложенность. Так сказать, для страховки (у нас тут основной критерий к коду - возможность повторного использования, реюзибл), на случай переноса куска кода в другую программу или компилятор. Если настройки нет и cli включается, компилер это заоптимизует и уберёт сам.

dmk
Dikoy:

Об этом я и написал …

Ну допустим не об этом Вы писали а о адресе возврата из прерывания, который вдруг куда-то исчезает. Возможно Вы не смогли правильно выразить свою мысль. Допускаю. Но к сожалению, создается впечатление, что это Вы в суть не вникли, но обязательно хотите оставить за собой последнее слово. Надеюсь, что это впечатление ложное.
Вложенностью прерываний можно и нужно пользоваться. А для того чтобы стек не переполнялся, действительно нужно уметь писать грамотный код (как Вы правильно заметили ранее).

Dikoy:

>>А вот STATUS регистр нужно сохранить в ручную, но это нужно делать вне зависимости от вложенности.

А здесь я допустил неточность, признаю. Это нужно делать в С программах только для прерываний, реализованных на ассемблере или с атрибутом naked. Но это было просто к слову.
А по существу, я вообще-то ответил smalltim-у, и поскольку комментировать или задавать вопросы он не стал, значит информация его либо удовлетворила, либо была излишней. Тем не менее, если интересно (smalltim-у), могу предложить свой код проекта OSD (тоже по мотивам Томаса Шерера двухлетней давности) на ATMega 168 , написанный на AVR GCC, с вложенным прерыванием строчного синхро. С его помощью я пытался реализовать графический и текстовый режимы в одном экране, вобщем довольно успешно. Хотя, по себе знаю, хуже нет чем ковыряться в чужом коде.

maloii
dmk:

Тем не менее, если интересно (smalltim-у), могу предложить свой код проекта OSD (тоже по мотивам Томаса Шерера двухлетней давности) на ATMega 168 , написанный на AVR GCC, с вложенным прерыванием строчного синхро. С его помощью я пытался реализовать графический и текстовый режимы в одном экране, вобщем довольно успешно. Хотя, по себе знаю, хуже нет чем ковыряться в чужом коде.

Не знаю как Тимофею но мне было б очень интересно посмотреть 😒 .

dmk

Да ради бога. Только e-mail в личку бросьте.

Dikoy
dmk:

Ну допустим не об этом Вы писали а о адресе возврата из прерывания, который вдруг куда-то исчезает. Возможно Вы не смогли правильно выразить свою мысль. Допускаю. Но к сожалению, создается впечатление, что это Вы в суть не вникли, но обязательно хотите оставить за собой последнее слово. Надеюсь, что это впечатление ложное.
Вложенностью прерываний можно и нужно пользоваться. А для того чтобы стек не переполнялся, действительно нужно уметь писать грамотный код (как Вы правильно заметили ранее).

Я писал о возможности потери вектора возврата при уровни вложенности более 1. Поясню.
Стек может переполниться запросто, причём даже не самими векторами возврата. Любая функция, особенно, если вызывается редко и из прерывания, да написана не тобой, может резко возжелать стек. А там уже данные основного кода. И вот тут очередному прерыванию понадобится сохранить вектор. А некуда! И всё - ниточка прервалась и получаем “адресе возврата из прерывания, который вдруг куда-то исчезает”.
Понятно, что если функции не хватит стека, это само по себе нехорошо. Но проц может и не зависнуть от этого. А вот от потерявшегося прерывания зависнет 100%. Или уйдёт на нулевой адрес (рестарт). Причём переменные в памяти и регистры сохранят свои значения и если код писался без лишней инициализации (есть такие экономщики, ставящие на дефолтные значения по ДШ) армагидец обеспечен.

А вы можете выложить видео с последнего полёта куда-нибудь, где его можно скачать? На том сайте дают только смотреть…

dmk
Dikoy:

Я писал о возможности потери вектора возврата при уровни вложенности более 1.

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

lodeworx

Вот, “босяцкий” индуктивный рпм сенсор, средствами меги, может работать БЕЗ ПРЕРЫВАНИЙ!

(Катушка- половина рас…еного РЭС-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]
Резистором “чувствительность” можно менять область применения 😁
(без него-“измеритель шума”)

maloii
Dikoy:

А вы можете выложить видео с последнего полёта куда-нибудь, где его можно скачать? На том сайте дают только смотреть…

Если Вы имеете в виду видео последнего полета с улетом 😁 ,то на страничке где вы смотрите, снизу в правом углу есть ссылка на скачать в исходном качестве, но эта ссылка видна только для зарегистрированных.

Dikoy
dmk:

Вы, извините, говорите о тривиальных вещах,

Вы, извините, уточните сначала, что есть стек в АВР и где находится, а потом мы обсудим дополнительный код.

maloii:

Если Вы имеете в виду видео последнего полета с улетом 😁 ,то на страничке где вы смотрите, снизу в правом углу есть ссылка на скачать в исходном качестве, но эта ссылка видна только для зарегистрированных.

ИК! 500 метров! 😃 Жёстко… 😵

maloii
Dikoy:

ИК! 500 метров! 😃 Жёстко… 😵

Дык 😁

9 days later
technolog

Добрый день !

Собрал телеметрию, пока без датчиков давления. Есть проблемка. При выводе на телевизор буквы скачут на полэкрана, при этом сами символы какие-то деформированные. Но если закрыть объектив видеокамеры, всё встаёт на свои места. Вчём дело и куда копать ?
Есть подозрение на диод D1. Поставил что было, точнее уже перепробовал штук 5-6, выпаянных из разных плат, результат одинаковый.

drweb

Доброе время суток.

technolog

У Вас наверно камера NTSC используйте PAL камеру, у меня точно такой случай был с моей NTSC камерой

С уважением Эльмир

smalltim
technolog:

Добрый день !

Собрал телеметрию, пока без датчиков давления. Есть проблемка. При выводе на телевизор буквы скачут на полэкрана, при этом сами символы какие-то деформированные. Но если закрыть объектив видеокамеры, всё встаёт на свои места. Вчём дело и куда копать ?
Есть подозрение на диод D1. Поставил что было, точнее уже перепробовал штук 5-6, выпаянных из разных плат, результат одинаковый.

Похоже, LM1881 с Вашей камерой ошибочно принимает перепады яркости изображения за строчные синхроимпульсы. Попробуйте увеличить R12 (идет через C12 к ноге номер 2 LM1881) с 510 Ом до 1К.

smalltim

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

#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
technolog

Прыжки надписей, в целом, поборол установкой телеметрии в то место, где она и должна находится - т.е. между камерой и видеопередатчиком. Первый раз для проверки работоспособности она была полключена между видеоприёмником и телевизором.

Однако появился вопрос другого плана. На цифрах и буквах появляются (и пропадают) лишние сегменты - это хорошо видно в прикреплённом видеофайле.
А может это так и должно быть?

to smalltim
изменение номинала резистора от 240 ом до 2 ком заметного эффекта не даёт, да и неактуально уже.

to drweb
камера чёрно-белая KPC-S190S (взял для экспериметов) какой там стандарт виеосигнала - хз.
PAL/SECAM/NTSC разве не станарты цветности?

DSCN4963.rar

smalltim

Ух ты, какая интересная фигня. Это точно не мусор в памяти - сломавшись в одном месте, буквы не ломаются в другом. Похоже на то, что иногда нужная нога атмеги не переходит в 0, когда ее просят. Я никогда с таким не встречался, хотя через меня прошел уже не один десяток телеметрий.
Можно фото платы и системы в сборе?

technolog

Вот плата телеметрии почти собраная. В реальности она не такая страшная. Делал плёночным фоторезистом, шаблон перерисовал в layoute. Внёс небольшие изменения (кварц в другом корпусе, некоторые дорожки другой формы).

“Система” в сборе. Передатчик на модуле AWM630, на плате ещё бует усилитель и модем.

Ну и приёмник:

smalltim

Хорошая платка получилась.
А что за диод? Больно жирный что-то. Нужен слаботочный, высокочастотный, с как можно меньшей емкостью перехода.

Да, и еще. Я понимаю, что вроде как бы всё равно, но я бы подключил плату телеметрии между камерой и передатчиком, а не отдельным видеокабелем к передатчику.

smalltim

У NTSC поля следуют с частотой 60 Гц, в поле 525 строк. У PAL поля следуют с частотой 50 Гц, в поле 625 строк. На NTSC букофки пойдут в полный расколбас.

technolog

А что за диод? Больно жирный что-то. Нужен слаботочный, высокочастотный, с как можно меньшей емкостью перехода.

Диод noname. Сегодня куплю что-нибудь из этого:
1N4148
BAS16
BAV70
BAV99
PMLL4148

Все они “быстрые” 4-6 нс, ёмкость перехода окол 1,5pF.

drweb

kamera samoe qlavnoe tochno ne NTSC ?

u menya tam voobshe stoit diod kd510 sovetskiy nash rodnoy, rabotaet kak chiki chiki 😉