Files
RadioPhotonic-generator-docs/Задачи.md
2025-09-18 17:11:38 +03:00

266 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 1
NaN:
Всё взаимодействие через UART
вопрос в следующем после получения пакета с заданием 0х7777 он начинает работу по перестройке тока, параметры заданы в пакете. каждую секунду приходит еще пакет
`Sent: Request last data (TRANS_ENABLE).
`Received 30 bytes
формируется ответ и отправляются значения температур диодов
**вопрос где тут в коде формируется ответный пакет с параметрами температур**
Вы посмотрите, а потом решим когда)
![[0x1111_descrtxt.txt]]
У меня возникает недопонимание тут,
![[0x7777_task_command.txt]]
вместе с начальным током перестроения лазера 1, устанавливается ток лазера 1
и я не могу понять в **каком месте он ставит этот ток при сообщении 0х7777** -- DONE
0х7777 передается один раз при установке настроек
Непонятно **как измеренные значения назад отправляются по команде 4444**
![[device_commands.py]]
![[1_1_Report_generator_heterodyne_20240124.pdf]]
# Контроль температуры во время TASK.
## Проблема
Во время варьирования тока лазера никакая температура не измеряется и не поддерживается.
## Анализ
### Быстрый фикс:
Поставить старую поддержку температуры на варьирование тока второго лазера. На task варьирования тока первого -- оставить как было.
### Нормальное решение
1 цикл измерения температуры 35 us.
Это больше, чем минимальный временной шаг изменения тока.
Следовательно, есть 2 подхода:
- написать асинхронные MPhD_T() и Set_LTEC().
- сделать варьирование тока через DMA, а температуры контролировать обычным способом. Это более перспективно, т.к.разгрузит вычислительные ресурсы во время варьирования.
- сделать варьирование тока в обработке прерывания, а температуру контролировать в блокирующем цикле.
#### Варьирование тока в прерывании
Добавил глобальную переменную task_state
task_state = 0 -- task не выполняется -- устанавливается в конце работы в прерывании.
task_state = 1 -- task в процессе выполнения. Устанавливается после подготовок в main.c
# Что такое Temp_ext_1/2?
Парсинг ответа на команду 0x4444:
data = {}
data['datetime'] = datetime.now()
data['Header'] = get_word(dh, 0)
data['I1'] = cnv.conv_I_N_to_mA(get_int_word(dh, 1))
data['I2'] = cnv.conv_I_N_to_mA(get_int_word(dh, 2))
data['TO_LSB'] = get_int_word(dh, 3)
data['TO_MSB'] = get_int_word(dh, 4)
data['Temp_1'] = cnv.conv_T_N_to_C(get_int_word(dh, 5))
data['Temp_2'] = cnv.conv_T_N_to_C(get_int_word(dh, 6))
data['Temp_Ext_1'] = cnv.conv_TExt_N_to_C(get_int_word(dh, 7))
data['Temp_Ext_2'] = cnv.conv_TExt_N_to_C(get_int_word(dh, 8))
data['MON_3V3'] = cnv.conv_U3V3_N_to_V(get_int_word(dh, 9))
data['MON_5V1'] = cnv.conv_U5V_N_to_V(get_int_word(dh, 10))
data['MON_5V2'] = cnv.conv_U5V_N_to_V(get_int_word(dh, 11))
data['MON_7V0'] = cnv.conv_U7V_N_to_V(get_int_word(dh, 12))
data['Message_ID'] = get_word(dh, 13) # Last received command
data['CRC'] = get_word(dh, 14)
dh -- принятый ответ, формируемый в MCU в виде массива LongData.
Формирование LongData:
```
Long_Data[1] = LD1_param.POWER;//Translate Data from monitor photodiode of LD1 to Long_Data
Long_Data[2] = LD2_param.POWER;//Translate Data from monitor photodiode of LD2 to Long_Data
Set_LTEC(1,LD1_curr_setup.CURRENT);//Drive Laser diode 1
Set_LTEC(2,LD2_curr_setup.CURRENT);//Drive Laser diode 2
//Prepare DATA of internals ADCs
//Put the temperature of LD2 to Long_Data:
temp16 = Get_ADC(0);
temp16 = Get_ADC(1); // measure ADC1 IN2 -- PA2 -- 3V_monitor
Long_Data[7] = temp16; // 3V_monitor -- Temp_Ext_1
//Put the temperature of LD2 to Long_Data:
temp16 = Get_ADC(1); // measure ADC1 IN8 -- PB0 -- U_Rt2_ext_Gain
Long_Data[8] = temp16; // U_Rt2_ext_Gain -- Temp_Ext_2
//Put the temperature of LD2 to Long_Data:
temp16 = Get_ADC(1); // measure ADC1 IN9 -- PB1 -- U_Rt1_ext_Gain
Long_Data[9] = temp16; // U_Rt1_ext_Gain -- MON_3V3
//Put the temperature of LD2 to Long_Data:
temp16 = Get_ADC(1); // measure ADC1 IN10 -- PC0 -- 5V1_monitor
Long_Data[10] = temp16; // 5V1_monitor -- MON_5V1
//Put the temperature of LD2 to Long_Data:
temp16 = Get_ADC(1); // measure ADC1 IN11 -- PC1 -- 5V2_monitor
Long_Data[11] = temp16; // 5V2_monitor -- MON_5V2
temp16 = Get_ADC(2); // turn ADC1 OFF
//Put the temperature of LD2 to Long_Data:
temp16 = Get_ADC(3);
temp16 = Get_ADC(4); // measure ADC3 IN 15 -- PF5 -- 7V_monitor
Long_Data[12] = temp16; // 7V_monitor -- MON_7V0
temp16 = Get_ADC(5); // turn ADC3 OFF
//Put the timer tick to Long_Data:
TO6_stop = TO6;
Long_Data[3] = (TO6_stop)&0xffff;
Long_Data[4] = (TO6_stop>>16)&0xffff;
//Put the average temperature of LD1 to Long_Data:
Long_Data[5] = LD1_param.LD_CURR_TEMP;
//Put the average temperature of LD2 to Long_Data:
Long_Data[6] = LD2_param.LD_CURR_TEMP;
```
ADC1 -- scan conversion mode.
# [[синхронное детектирование]]
[[]]
# Кривые тайминги варьирования тока
## Проблема:
- Камиль: 1 шаг перестроения тока -- не 50 мкс (как надо), а 70 мкс.
- после удаления поддержания температуры -- 1 шаг перестройки -- на 10 мкс меньше установленного. Если установлен шаг менее 30 мкс -- GUI вылетает.
## анализ
#### В коде GUI:
Установка шага времени.
1. GUI -> params['Delta_Time']
2. в create_TaskEnableCommand(): запись в посылаемые данные: sending_param['Dt']\*100 //(Word 6)
3. в main(): sending_param['Dt'] = float(params['Delta_Time'])
Тоесть "передаваемое значение" = "значение из GUI" \* 100.
#### В коде MCU:
TIM10 тактируется от APB2 (184 MHz), prescaler=183, ARR = 9. => **TIM10 update -- каждые 10 мкс**. (проверено на железе -- верно )
Обработка значения:
1. task.dt = "принятое значение"/100 (main.c:2070)
2. TO10_counter = task.dt / 10 - 1 (main.c:2080, 625)
=> из GUI и кода MCU:
**период события TIM10_coflag = ('Delta_Time'/10 - 1) * 10 мкс**
## решение
т.к. период события TIM10_coflag = ('Delta_Time'/10 - 1) * 10 мкс
Получаемый период варьирования тока -- на 10 мкс меньше, чем в GUI.
main.c:2080,625: "TO10_counter = task.dt / 10 - 1;" -> "TO10_counter = task.dt / 10;"
в итоге период события TIM10_coflag = ('Delta_Time'/10) * 10 мкс.
Сделать период обновления TIM10 менее 10 мкс -- сложно, т.к. увеличится частота прерываний. => шаг времени -- 10 мкс. **добавим в описание поля в GUIte**
# Клоки для модулятора и АЦП недетерменированно выключаются в конце ЛЧМ.
## Проблема
Наблюденные варианты выключения клоков в конце ЛЧМ.
Желтый -- клок АЦП (семплирование по спадающему фронту)
Синий -- сигнал на модулятор Маха-Цандера.
Розовый -- триггер (рассматривается конец процедуры ЛЧМ, триггер произошел 176 мс назад)
![[RigolDS5 1.png]]
![[RigolDS6 1.png]]
![[RigolDS8 1.png]]
Дополнительная проблема: процедура ЛЧМ не всегда содержит одинаковое число шагов.
## анализ
Проблема в выключении таймеров. Так как выключение (HAL_TIM_PWM_Stop(&htim11, TIM_CHANNEL_1)) происходит в коде по завершению ЛЧМ -- точный момент выключения зависит от выполнения остального кода, не детерменирован. Надо как-то
## решение
### Вариант 0
Выключать таймеры атомарной записью в регистр, а не через HAL.
Реализация:
### Вариант 1.
Зафиксировать число шагов ЛЧМ. Выключать клоки в обработчике прерывания TIM10.
## Вариант 2. Реализован
Когда приходит пора выключить таймеры, включаем прерывание TIM11. В прерывании переводим оба таймера в one-pulse mode. Они сами выключаются. Затем перед следующим запуском ЛЧМ -- выключаем one-pulse, прервывание, обнуляем счетчики и запускаем.
![[RigolDS9 1.png]]
![[RigolDS10.png]]
![[RigolDS11.png]]
![[RigolDS12.png]]
![[RigolDS13.png]]
![[RigolDS14.png]]
TODO: сделать атомарный запуск обоих таймеров.
TODO: настроить сдвиг фазы АЦП относительно модуляции.
# настройка таймингов модулятора и АПЦ
## Проблема
Клок АЦП плохо соотносится с принятым модулированным сигналом.
| ![[RigolDS16.png]] |
| ----------------------------------------- |
| Синий -- на модулятор Маха-Цандера |
| Желтый -- клок АЦП (запуск по спаду) |
| Голубой -- принятый модулированный сигнал |
Сигнал с АЦП
![[newplot(3).png]]
## Анализ
Проблема возникала из-за плохой настройки фаз клоков АЦП и модулятора Маха-Цандера. Большая малопредсказуемая задержка привносилась функцией запуска таймеров HAL_TIM_PWM_Start(&htim11, TIM_CHANNEL_1) (main.c 437,438).
## Решение
После запуска таймеров повторно атомарно обнуляем счетчики (TIM -> CNT = 0).
| ![[RigolDS17.png]] |
| ----------------------------------------- |
| Синий -- на модулятор Маха-Цандера |
| Желтый -- клок АЦП (запуск по спаду) |
| Голубой -- принятый модулированный сигнал |
Сигнал с АЦП:
![[newplot(2).png]]
# развитие
Установлена небольшая задержка при запуске клока АЦП, чтобы семплирование происходило в конце периода модуляции. Таким образом, при увеличении задержек в радиочастотном тракте семплирование не будет происходить в момент изменения уровня сигнала. Запас по времени ~400 нс (120 м).
![[RigolDS20.png]]
Код:
`TIM4 -> CNT = TIM4 -> ARR - 20` (main.c:441)
#git commit f20ad2301b91b86eddc709a79106fe1518cce531 (HEAD -> master)
# оцифровка сигнала радара
[[АЦП E-502]]
# Нагрузка детекторной головки
## Проблема
Детекторная головка требует шунтирования резистором на землю.
Если роль резистора играет аттенюатор на выходе головки -- появляются непонятные колебания сигнала частотой ~ 100кГц.![[RigolDS23.png]]
Без непонятных помех:
![[RigolDS24.png]]
## Анализ
Колебания появляются также при подключении терминатора 50 Ом посередине кабеля от головки к осциллографу, в т.ч. при парралельном соединении АЦП и осциллографа. Однако, пропадают при подключении терминатора через тройник непосредственно на входе осциллографа или переключении входа осциллографа на 50 Ом.
При подключении осциллографа щупом к аттенюатору -- проблема не решается.
## Решение
Поставить аттенюатор непосредственно на вход осла и АЦП?
# Сделать [[обработка данных на blackfin в АЦП подготовка]]
## Проблема
## Анализ
## Решение
#
## Проблема
## Анализ
## Решение
#
## Проблема
## Анализ
## Решение