SimpleFOClibrary 2.4.0
Loading...
Searching...
No Matches
current_sense/hardware_specific/rp2040/rp2040_mcu.h
Go to the documentation of this file.
1
2
3#pragma once
4
5/*
6 * RP2040 ADC features are very weak :-(
7 * - only 4 inputs
8 * - only 9 bit effective resolution
9 * - read only 1 input at a time
10 * - 2 microseconds conversion time!
11 * - no triggers from PWM / events, only DMA
12 *
13 * So to read 3 phases takes 6 microseconds. :-(
14 *
15 * The RP2040 ADC engine takes over the control of the MCU's ADC. Parallel ADC access is not permitted, as this would
16 * cause conflicts with the engine's DMA based access and cause crashes.
17 * To use the other ADC channels, use them via this engine. Use addPin() to add them to the conversion, and getLastResult()
18 * to retrieve their value at any time.
19 *
20 * For motor current sensing, the engine supports inline sensing only.
21 *
22 * Inline sensing is supported by offering a user-selectable fixed ADC sampling rate, which can be set between 500kHz and 1Hz.
23 * After starting the engine it will continuously sample and provide new values at the configured rate.
24 *
25 * The default sampling rate is 20kHz, which is suitable for 2 channels assuming you a 5kHz main loop speed (a new measurement is used per
26 * main loop iteration).
27 *
28 * Low-side sensing is currently not supported.
29 *
30 * The SimpleFOC PWM driver for RP2040 syncs all the slices, so the PWM trigger is applied to the first used slice. For current
31 * sensing to work correctly, all PWM slices have to be set to the same PWM frequency.
32 * In theory, two motors could be sensed using 2 shunts on each motor.
33 *
34 * Note that if using other ADC channels along with the motor current sensing, those channels will be subject to the same conversion schedule as the motor's ADC channels, i.e. convert at the same fixed rate in case
35 * of inline sensing.
36 *
37 * Solution to trigger ADC conversion from PWM via DMA:
38 * use the PWM wrap as a DREQ to a DMA channel, and have the DMA channel write to the ADC's CS register to trigger an ADC sample.
39 * Unfortunately, I could not get this to work, so no low side sensing for the moment.
40 *
41 * Solution for ADC conversion:
42 * ADC converts all channels in round-robin mode, and writes to FIFO. FIFO is emptied by a DMA which triggers after N conversions,
43 * where N is the number of ADC channels used. So this DMA copies all the values from one round-robin conversion.
44 *
45 *
46 */
47
48
49#define SIMPLEFOC_RP2040_ADC_RESOLUTION 256
50#ifndef SIMPLEFOC_RP2040_ADC_VDDA
51#define SIMPLEFOC_RP2040_ADC_VDDA 3.3f
52#endif
53
54
56 uint32_t value;
57 uint8_t raw[4];
58 struct {
59 uint8_t ch0;
60 uint8_t ch1;
61 uint8_t ch2;
62 uint8_t ch3;
63 };
64};
65
66
68
69public:
71 void addPin(int pin);
72 //void setPWMTrigger(uint slice);
73
74 bool init();
75 void start();
76 void stop();
77
78 ADCResults getLastResults(); // TODO find a better API and representation for this
79
80 int samples_per_second = 20000; // 20kHz default (assuming 2 shunts and 5kHz loop speed), set to 0 to convert in tight loop
81 float adc_conv = (SIMPLEFOC_RP2040_ADC_VDDA / SIMPLEFOC_RP2040_ADC_RESOLUTION); // conversion from raw ADC to float
82
83 //int triggerPWMSlice = -1;
86 //uint copyDMAChannel;
87 //uint triggerDMAChannel;
88
90 volatile uint8_t samples[4];
92 //alignas(32) volatile uint8_t nextResults[4];
93};
ADCResults getLastResults()
void addPin(int pin)