rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
Functions
hellen_board_id.cpp File Reference

Detailed Description

Board-Id detector for Hellen boards.

Author
andreika prome.nosp@m.theu.nosp@m.s.pcb.nosp@m.@gma.nosp@m.il.co.nosp@m.m
Andrey Belomutskiy, (c) 2012-2022

The main idea is to measure the capacitor charge/discharge time through a series resistors using standard digital I/O pins. One pin is used to provide a Vcc(3.3) or Vdd(0) voltage to the capacitor through a resistor, and another pin is used as a digital input. Then vice versa.

The algo: 1) Completely discharge the capacitor (all pins are low) 2) Charge the capacitor until the voltage crosses the 0->1 voltage threshold (Vt) and measure the charging time #1 (Tc1). 3) Immediately discharge the capacitor to some unknown low voltage (Vl) - it should be well below the Vt threshold, using the same period of time used for charging as the discharge period (Td = Tc1). 4) Immediately charge the capacitor again and measure the time crossing the same 0->1 voltage threshold again (Tc2). 5) Repeat the procedure several times to get more precise timings. 6) Do some math and find the R and C values. 7) Board_Id = the unique combination of indices of the "measured" R1 and R2.

The math proof:

Definition in file hellen_board_id.cpp.

Functions

static void hellenBoardIdInputCallback (void *arg, efitick_t nowNt)
 
int detectHellenBoardId ()
 

Function Documentation

◆ detectHellenBoardId()

int detectHellenBoardId ( )

Definition at line 308 of file hellen_board_id.cpp.

308 {
309 int boardId = -1;
310#if defined( HELLEN_BOARD_ID_PIN_1) && !defined(HW_HELLEN_SKIP_BOARD_TYPE)
311 efiPrintf("Starting Hellen Board ID detection...");
312 Timer t;
313 t.reset();
314
315 const int numPins = 2;
316 Gpio rPins[numPins] = { HELLEN_BOARD_ID_PIN_1, HELLEN_BOARD_ID_PIN_2};
317
318 // We start from the estimated capacitance, but the real one can be +-10%
319 float C = HELLEN_BOARD_ID_CAPACITOR;
320
321 // we need to find the resistor values connected to the mcu pins and to the capacitor.
322 float R[numPins] = { 0 };
323 int rIdx[numPins] = { 0 };
324
325 HellenBoardIdFinder<numPins> finder(rPins);
326
327 // init some ChibiOs objects
328 chSemObjectInit(&finder.state.boardId_wake, 0);
329
330 // R1 is the first, R2 is the second
331 for (int i = 0; i < numPins; i++) {
332#ifdef HELLEN_BOARD_ID_DEBUG
333 efiPrintf("*** Resistor R%d...", i + 1);
334#endif /* HELLEN_BOARD_ID_DEBUG */
335
336 float Tc1_us = 0, Tc2_us = 0;
337 // We need several measurements for each resistor to increase the precision.
338 // But if any of the measurements fails, then abort!
339 if (!finder.measureChargingTimesAveraged(i, Tc1_us, Tc2_us))
340 break;
341
342 // Now roughly estimate the resistor value using the approximate threshold voltage.
343 float Rest = finder.calcEstimatedResistance(Tc1_us, C);
344 // check if we are inside the range
345 if (Rest < 300.0f || Rest > 15000.0f) {
346 efiPrintf("* Unrealistic estimated resistor value (%f)! Aborting!", Rest);
347 break;
348 }
349
350 // for the first resistor, we test only "major" values because we don't know the exact capacitance yet
351 bool testOnlyMajorSeries = (i == 0);
352
353 float Rmeasured, newC;
354 // Now calculate the R and C
355 R[i] = finder.calc(Tc1_us, Tc2_us, Rest, C, testOnlyMajorSeries, &Rmeasured, &newC, &rIdx[i]);
356 C = newC;
357
358#ifdef HELLEN_BOARD_ID_DEBUG
359 efiPrintf("* R = %f, Rmeasured = %f, Rest = %f, Creal = %f", R[i], Rmeasured, Rest, C);
360#endif /* HELLEN_BOARD_ID_DEBUG */
361 }
362
363 // in case the process was aborted
364 for (size_t k = 0; k < numPins; k++) {
365 efiExtiDisablePin(rPins[k]);
366 // release the pins
367 palSetPadMode(getBrainPinPort(rPins[k]), getBrainPinIndex(rPins[k]), PAL_MODE_RESET);
368 }
369
370 float elapsed_Ms = t.getElapsedSeconds() * 1000;
371
372 // Check that all resistors were actually detected
373 bool allRValid = true;
374 for (size_t i = 0; i < numPins; i++) {
375 allRValid &= R[i] != 0;
376 }
377
378 // Decode board ID only if all resistors could be decoded, otherwise we return -1
379 if (allRValid) {
380 boardId = HELLEN_GET_BOARD_ID(rIdx[0], rIdx[1]);
381 } else {
382 boardId = -1;
383 }
384
385 efiPrintf("* RESULT: BoardId = %d, R1 = %.0f, R2 = %.0f (Elapsed time: %.1f ms)", boardId, R[0], R[1], elapsed_Ms);
386#endif /* HELLEN_BOARD_ID_PIN_1 */
387 return boardId;
388}
void efiExtiDisablePin(brain_pin_e brainPin)
C
int getBrainPinIndex(Gpio brainPin)
ioportid_t getBrainPinPort(brain_pin_e brainPin)

Referenced by detectHellenBoardType().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ hellenBoardIdInputCallback()

static void hellenBoardIdInputCallback ( void *  arg,
efitick_t  nowNt 
)
static

Definition at line 68 of file hellen_board_id.cpp.

68 {
69 UNUSED(arg);
71 // Now start discharging immediately! This should be the first command in the interrupt handler.
72 palClearPad(state->rOutputPinPort, state->rOutputPinIdx);
73
74 state->timeChargeNt = nowNt;
75
76 chibios_rt::CriticalSectionLocker csl;
77 chSemSignalI(&state->boardId_wake); // no need to call chSchRescheduleS() because we're inside the ISR
78}
UNUSED(samplingTimeSeconds)
state("state", SensorCategory.SENSOR_INPUTS, FieldType.INT8, 1871, 1.0, -1.0, -1.0, "")

Referenced by HellenBoardIdFinder< NumPins >::measureChargingTimes().

Here is the call graph for this function:
Here is the caller graph for this function:

Go to the source code of this file.