Skip to content

Commit e337585

Browse files
committed
feat: add Nano MCU temperature telemetry
1 parent 200dc2b commit e337585

12 files changed

Lines changed: 304 additions & 182 deletions

File tree

.github/workflows/altair-v5-ui-check.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,13 @@ jobs:
4848
const app = fs.readFileSync('js/app.js', 'utf8');
4949
if (!app.includes('version: "0.8.0"')) throw new Error('app.js must identify v0.8.0');
5050
if (app.includes('applyV6BrandingAndRadioProfile')) throw new Error('Legacy v6 runtime override is still present');
51+
if (!app.includes('"VOLT", "TEMP", "MODE"')) throw new Error('MCU temperature must follow battery voltage in UI telemetry order');
5152
5253
const index = fs.readFileSync('index.html', 'utf8');
5354
if (!index.includes('<script src="js/v8.js"></script>')) throw new Error('v8.js is not connected in index.html');
5455
if (!index.includes('<script src="js/v8-final.js"></script>')) throw new Error('v8-final.js is not connected in index.html');
56+
if (!index.includes('Температура бортового компьютера')) throw new Error('MCU temperature card is missing');
57+
if (!index.includes('Команды, передаваемые на спутник')) throw new Error('Uplink panel purpose is unclear');
5558
5659
const v8Runtime = fs.readFileSync('js/v8.js', 'utf8');
5760
if (!v8Runtime.includes('control.disabled = !connected')) throw new Error('Visible command controls are not synchronized with serial state');
@@ -63,6 +66,7 @@ jobs:
6366
const charts = fs.readFileSync('js/charts.js', 'utf8');
6467
if (!charts.includes('datasetFor(chart, id)')) throw new Error('Multi-ID chart datasets are missing');
6568
if (!charts.includes('pointRadius: 2.7')) throw new Error('Visible chart points are missing');
69+
if (!charts.includes('TEMP: { title: "Температура бортового компьютера"')) throw new Error('MCU temperature chart is not connected');
6670
6771
const finalRuntime = fs.readFileSync('js/v8-final.js', 'utf8');
6872
if (!finalRuntime.includes('bandwidth: "203"')) throw new Error('v8 UI must enforce RX BW 203 kHz');
@@ -80,12 +84,13 @@ jobs:
8084
grep -Fq 'APPLICATION_XOR_CHECK=DISABLED' "$ground_esp32"
8185
grep -Fq '$CMD,RF,' "$ground_esp32"
8286
grep -Fq '$CMD,RADIO_STATUS' "$ground_esp32"
83-
grep -Fq 'FW_VERSION[] = "8.3.0"' "$ground_esp32"
87+
grep -Fq 'FW_VERSION[] = "8.3.1"' "$ground_esp32"
8488
grep -Fq 'radio.setPacketReceivedAction(onRfPacketReceived);' "$ground_esp32"
8589
grep -Fq 'const int state = radio.readData(packet);' "$ground_esp32"
8690
grep -Fq '$CMD,RADIO,SET,' "$ground_esp32"
8791
grep -Fq '$CMD,RADIO,RESET' "$ground_esp32"
8892
grep -Fq 'RADIO_CONFIG_APPLIED' "$ground_esp32"
93+
grep -Fq 'Serial.print(",MCU_TEMP=");' "$ground_esp32"
8994
if grep -Fq 'const int state = radio.receive(packet);' "$ground_esp32"; then
9095
echo 'Blocking CC1101 receive must not be used in the ESP32 gateway'
9196
exit 1
@@ -96,6 +101,10 @@ jobs:
96101
test -f firmware/ground_station/arduino_nano/Altair_Ground_Arduino_Nano/Altair_Ground_Arduino_Nano.ino
97102
test -f firmware/satellite/stm32/Altair_Satellite_STM32/Altair_Satellite_STM32.ino
98103
test -f firmware/satellite/arduino_nano/Altair_Satellite_Arduino_Nano/Altair_Satellite_Arduino_Nano.ino
104+
static_nano='firmware/satellite/arduino_nano_static_tx/Altair_Satellite_Arduino_Nano_Static_TX/Altair_Satellite_Arduino_Nano_Static_TX.ino'
105+
grep -Fq '1.00,4.20,' "$static_nano"
106+
grep -Fq 'readMcuTemperatureC()' "$static_nano"
107+
grep -Fq 'calculateXorChecksum' "$static_nano"
99108
100109
grep -Fq '435.000' js/v8.js
101110
grep -Fq 'rawSerialConsole' js/v8.js

README.md

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,21 +65,21 @@
6565
| Модуляция | 2-FSK |
6666
| Скорость в эфире | 4.8 kbps |
6767
| Девиация | 5 кГц |
68-
| Полоса RX | **203 кГц** |
68+
| Полоса приёмника ЦУПа | **203 кГц** |
6969
| Мощность TX | **5 дБм** |
7070
| Sync word | `0x12AD` |
7171
| Encoding | NRZ |
7272
| Длина пакета | variable |
7373
| CRC CC1101 | включён |
7474
| USB | 115200 бод |
7575

76-
Широкая полоса **203 кГц** выбрана намеренно: на стенде некоторые модули имели заметный частотный уход относительно 435.000 МГц. Этот набор значений используется как исходный профиль при включении ESP32. В панели команд можно изменить частоту, мощность TX и полосу RX, а кнопка **«Сбросить к исходным»** возвращает `435.000 МГц`, `5 дБм` и `203 кГц`.
76+
Широкая полоса приёмника ЦУПа **203 кГц** выбрана намеренно: на стенде некоторые модули имели заметный частотный уход относительно 435.000 МГц. Этот набор значений используется как исходный профиль при включении ESP32. В панели команд можно изменить частоту, мощность TX и полосу приёмника ЦУПа, а кнопка **«Сбросить к исходным»** возвращает `435.000 МГц`, `5 дБм` и `203 кГц`.
7777

7878
Доступные настройки CC1101:
7979

8080
- частота наземного модуля: от `387.000` до `464.000 МГц`;
8181
- мощность TX: `−30`, `−20`, `−15`, `−10`, `0`, `5`, `7` или `10 дБм`;
82-
- полоса RX: `58`, `68`, `81`, `102`, `116`, `135`, `162`, `203`, `232`, `270`, `325`, `406`, `464`, `541`, `650` или `812 кГц`.
82+
- полоса приёмника ЦУПа: `58`, `68`, `81`, `102`, `116`, `135`, `162`, `203`, `232`, `270`, `325`, `406`, `464`, `541`, `650` или `812 кГц`.
8383

8484
Настройки действуют до перезапуска ESP32. После перезапуска автоматически восстанавливается исходный профиль. При изменении частоты бортовой передатчик необходимо настроить на ту же частоту.
8585

@@ -150,32 +150,36 @@
150150
151151
## Телеметрия
152152

153-
Базовый пакет:
153+
Базовый пакет с температурой бортового компьютера:
154154

155155
```text
156-
02,00001,00015,3.00,4.20,1,33
156+
02,00001,00015,1.00,4.20,31.6,1,07
157157
```
158158

159159
Поля:
160160

161161
```text
162-
ID,PACKET,UPTIME,PANEL_POWER,VOLT,MODE,CHECKSUM
162+
ID,PACKET,UPTIME,PANEL_POWER,VOLT,MCU_TEMP,MODE,CHECKSUM
163163
```
164164

165+
`MCU_TEMP` — ориентировочная температура кристалла бортового микроконтроллера в градусах Цельсия. Поле располагается непосредственно после напряжения аккумулятора. Для точных абсолютных измерений внутренний датчик конкретной платы необходимо откалибровать.
166+
165167
Поддерживается и расширенный вариант с состоянием раскрытия антенны:
166168

167169
```text
168-
02,00001,00015,3.00,4.20,1,1,33
170+
02,00001,00015,1.00,4.20,31.6,1,1,1A
169171
```
170172

171173
Поля:
172174

173175
```text
174-
ID,PACKET,UPTIME,PANEL_POWER,VOLT,MODE,ANTENNA,CHECKSUM
176+
ID,PACKET,UPTIME,PANEL_POWER,VOLT,MCU_TEMP,MODE,ANTENNA,CHECKSUM
175177
```
176178

177179
где `ANTENNA=1` — раскрыта, `ANTENNA=0` — сложена. Если поля `ANTENNA` нет, интерфейс показывает **Н/Д**.
178180

181+
Для совместимости ЦУП продолжает принимать прежние семипольные пакеты без температуры.
182+
179183
### Важно про контрольную сумму
180184

181185
В v8 **прикладная XOR-проверка намеренно отключена**. Поле `CHECKSUM` сохраняется и отображается, но не является причиной отбрасывания пакета.

css/v8.css

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,17 @@
142142
#rawSerialConsole .err { color: #ff8e9a; }
143143
#rawSerialConsole .info { color: #8cf0b4; }
144144

145+
.v8CommandScope {
146+
margin: 0 0 14px;
147+
padding: 10px 12px;
148+
border-left: 3px solid rgba(0,217,255,.72);
149+
border-radius: 7px;
150+
color: #b5c9dc;
151+
background: rgba(0,217,255,.055);
152+
font-size: .79rem;
153+
line-height: 1.45;
154+
}
155+
145156
.v8CommandTarget {
146157
display: grid;
147158
grid-template-columns: minmax(100px, 180px) 1fr;

firmware/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212

1313
Наземный скетч принимает телеметрию, передаёт её программе по USB со скоростью 115200 бод и отправляет команды спутнику через тот же CC1101.
1414

15-
В прошивке ESP32 версии **8.3.0** приём CC1101 работает неблокирующим способом по прерыванию `GDO0`. Поэтому USB-команды обрабатываются постоянно и передача начинается сразу после нажатия кнопки в ЦУПе, без ожидания тайм-аута приёмника. В строку подтверждения `$ACK,RF_TX` добавлено поле `TX_MS` с фактической длительностью радиопередачи.
15+
В прошивке ESP32 версии **8.3.1** приём CC1101 работает неблокирующим способом по прерыванию `GDO0`. Поэтому USB-команды обрабатываются постоянно и передача начинается сразу после нажатия кнопки в ЦУПе, без ожидания тайм-аута приёмника. В строку подтверждения `$ACK,RF_TX` добавлено поле `TX_MS` с фактической длительностью радиопередачи.
1616

17-
Частоту, мощность TX и полосу RX можно изменять из панели команд ЦУПа. Команда `$CMD,RADIO,RESET` возвращает исходные значения `435.000 МГц`, `5 дБм` и `203 кГц`. Настройки хранятся до перезапуска ESP32; после включения питания используется исходный профиль.
17+
Частоту, мощность TX и полосу приёмника ЦУПа можно изменять из панели команд. Команда `$CMD,RADIO,RESET` возвращает исходные значения `435.000 МГц`, `5 дБм` и `203 кГц`. Настройки хранятся до перезапуска ESP32; после включения питания используется исходный профиль.
1818

1919
## Спутник
2020

@@ -26,7 +26,7 @@
2626

2727
Бортовые скетчи передают телеметрию, принимают адресованные команды и поддерживают `PING`, `INFO`, `TM_START`, `TM_STOP`, `TM_PERIOD` и `USER`.
2828

29-
Упрощённый вариант `Static_TX` не включает приёмник и обработку команд. Он передаёт один статичный пакет `02,00001,00015,3.00,4.20,1,33` раз в секунду и предназначен для первичной проверки радиолинии.
29+
Упрощённый вариант `Static_TX` не включает приёмник и обработку команд. Поля ID, номер пакета, uptime, мощность панелей `1.00 Вт`, напряжение аккумулятора `4.20 В` и режим заданы заранее. Поле `MCU_TEMP` измеряется внутренним температурным каналом ATmega328P, располагается сразу после напряжения аккумулятора и передаётся раз в секунду. XOR-контрольная сумма пересчитывается автоматически для каждого значения температуры.
3030

3131
## Общий радиопрофиль
3232

firmware/ground_station/esp32/Altair_Ground_ESP32/Altair_Ground_ESP32.ino

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
#define CC_GDO0 4
2828
#define CC_GDO2 27
2929

30-
static constexpr char FW_VERSION[] = "8.3.0";
30+
static constexpr char FW_VERSION[] = "8.3.1";
3131
static constexpr float RF_FREQ_MHZ = 435.000f;
3232
static constexpr float RF_BITRATE_KBPS = 4.8f;
3333
static constexpr float RF_DEVIATION_KHZ = 5.0f;
@@ -365,18 +365,28 @@ void pollUsb() {
365365
void emitTelemetry(String packet) {
366366
packet.trim();
367367

368-
String fields[8];
368+
String fields[9];
369369
int count = 0;
370-
if (!splitCsv(packet, fields, 8, count) || (count != 7 && count != 8)) {
370+
if (!splitCsv(packet, fields, 9, count) || (count != 7 && count != 8 && count != 9)) {
371371
Serial.print("$RAW,");
372372
Serial.println(packet);
373373
return;
374374
}
375375

376-
// Семь полей: ID,PACKET,UPTIME,PANEL_POWER,VOLT,MODE,CHECKSUM.
377-
// Восьмое необязательное поле ANTENNA располагается перед CHECKSUM.
378-
const bool hasAntenna = (count == 8);
379-
const int checksumIndex = hasAntenna ? 7 : 6;
376+
// Поддерживаются три варианта пакета:
377+
// 7 полей — старый пакет без температуры и без ANTENNA;
378+
// 8 полей — новый пакет с MCU_TEMP либо старый пакет с ANTENNA;
379+
// 9 полей — новый пакет одновременно с MCU_TEMP и ANTENNA.
380+
// В новом восьмипольном формате температура всегда передаётся с десятичной
381+
// точкой, поэтому её можно отличить от бинарного MODE старого формата.
382+
const bool eighthFieldContainsTemperature =
383+
count == 8 && fields[5] != "0" && fields[5] != "1";
384+
const bool hasTemperature = count == 9 || eighthFieldContainsTemperature;
385+
const bool hasAntenna = count == 9 || (count == 8 && !eighthFieldContainsTemperature);
386+
const int temperatureIndex = hasTemperature ? 5 : -1;
387+
const int modeIndex = hasTemperature ? 6 : 5;
388+
const int antennaIndex = count == 9 ? 7 : (hasAntenna ? 6 : -1);
389+
const int checksumIndex = count - 1;
380390

381391
const float rssi = radio.getRSSI();
382392
const uint8_t lqi = radio.getLQI();
@@ -392,11 +402,17 @@ void emitTelemetry(String packet) {
392402
Serial.print(",UPTIME="); Serial.print(fields[2]);
393403
Serial.print(",PANEL_POWER="); Serial.print(fields[3]);
394404
Serial.print(",VOLT="); Serial.print(fields[4]);
395-
Serial.print(",MODE="); Serial.print(fields[5]);
405+
406+
if (hasTemperature) {
407+
Serial.print(",MCU_TEMP=");
408+
Serial.print(fields[temperatureIndex]);
409+
}
410+
411+
Serial.print(",MODE="); Serial.print(fields[modeIndex]);
396412

397413
if (hasAntenna) {
398414
Serial.print(",ANTENNA=");
399-
Serial.print(fields[6]);
415+
Serial.print(fields[antennaIndex]);
400416
}
401417

402418
// Поле выводится для совместимости, но шлюз его не проверяет.

0 commit comments

Comments
 (0)