RoboDurden / Hoverboard-Firmware-Hack-Gen2.x

with different defines_2-x.h for different board layouts :-) Compiles with Keil version 6
GNU General Public License v3.0
73 stars 24 forks source link

Torque mode, FOC? #11

Open robcazzaro opened 1 year ago

robcazzaro commented 1 year ago

Just wondering if you are planning to add FOC and torque mode like the Eferu project, or if you know of any FOC algorithm implemented for the GD32F130C8T6.

If not, I might want to try "merging" your base GD32 code with the FOC algorithm from Eferu

Candas1 commented 1 year ago

Hi,

Your nickname rings a bell. Are you in the simpleFOC community?

If you want to port FOC, check this, someone had started to port it, I did small adjustments but couldn't finish as I was busy with something else.

Another idea I had is This It could potentially lead to use simplefoc but a lot has to happen before (testing/arduino core for gd32, sensor smoothing in simplefoc), so it's more long term

RoboDurden commented 1 year ago

Oh yes, https://simplefoc.com/ looks very promising. And fully object orientend as far as i can see: https://docs.simplefoc.com/source_code

Not only the stm32f1 family but also the stm32f4 family is said to be supported: https://docs.simplefoc.com/stm32_mcu If the code runs on a bluepill (stm32f103), then it should directly run on an old gen1 board (stm32f103 and gd32f103). But the doc says that only 1 motor low-side current sensing is possible.

But to my understanding, phase current sensing is only needed without hall sensors. But Candas said the EFeru FOC code needs two phase currents (the third can be derived from the first two). I think, FOC basically is only the closed loop to control the six mosfet in a rotating coordinate system which makes the closed loop simpler. The rotation should also be able to be found from the hall sensors. But the current sensing is analog whereas the hall sensors are digital...

The docs of SimpleFOC in https://docs.simplefoc.com/code says:

proceed to initializing and configuring the current sense, if available of course. If current sense is not available you can skip this step. The library supports two types of current sense architecture:

    in-line current sensing InlineCurrentSense.
    low-side current sensing LowsideCurrentSense.

That example code looks really nice and it should be straight forward to get two motors (without phase current sensing) running on the old stm32f103 and the new stm32f403 boards !?

There is https://github.com/keyboardio/ArduinoCore-GD32-Keyboardio but maybe only the GD32F303 is supported and not the GD32F130 that is found on these Gen2 boards.

Adding FOC to my Gen2.x repo is not really on my todo list. At the moment i am merging the two serial communications (Esp32-Hover_master + Hover_master-Hover_slave) into one universal uart communication that can chain several baords. For example a robot arm on a moving platform:

typedef struct __attribute__((packed, aligned(1))) {
   uint16_t cStart = START_FRAME;   // new version
   uint8_t iSize;
   Server2HoverSpeedSteer oMover; // digger moving wheels
   Server2HoverPos oPos1;   // robot arm servo 1
   Server2HoverPos oPos2;   // robot arm servo 2
   uint16_t checksum;
} Server2Hover;

So additional structs Server2HoverTorque or Server2HoverRpm might be in reach. But these structs should of course be c++ classes derived from an abstarct class Server2HoverControl with an element function (method) Control() that hosts the closed loop needed to control a position or torque or rpm in these classes.

So yes when i have finished a closed loop for positioning a rotation angle, it would be easy to add a torque mode.

@Candas1 i have probed the DIO2032 dual opamp outputs of the gen2.2 board with my dso and they do not seem to be current and voltage: gen2 2 opamp dso

Do you recognize these outputs (motor was spinning) as tow low-side phase currents ? Then at least the 2.2 layout might support the EFeru FOC code ?

Greetings from sunny Germany :-)

Candas1 commented 1 year ago

No simplefoc cannot handle 2 motors yet. Phase current is needed for FOC. Hall sensors are needed for motor angle but as simplefoc was mainly used with encoders, it has not extrapolation of the angle between hall changes yet as Eferu's firmware uses it for SIN and FOC. It's work in progress.

RoboDurden commented 1 year ago

Thanks Candas1 for your feedback! If simpleFOC is truely object oriented then of course it should support as many motors as there are IO pins availble. And all motors should share the same 16 kHz interrupt to handle the foc control loop. Our hoverbord motors have 90 hall steps per revolution and with 14 rpm/V we have 5-8 revs/s yielding 450-630 Hz. Should be no problem to make a quadratic extrapolation somehow like s(t) = v*t + 1/2 a * t² to boost that to 16 kHz

We have to find such a solution anyway for the modern stm32f403 boards anyway ?

robcazzaro commented 1 year ago

Also: the "split boards style" hoverboards all have a processor and drive only one motor, communicating with each other over serial. So, all those are great candidates for Simplefoc. It's the first generation boards that used a single processor driving both motors (and using side boards for the IMUs).

Thanks for the additional links @Candas1 (and, yes, it's me on SimpleFOC forums :). I'll have a look at them, especially the Arduino port,

But the GD code (https://github.com/CommunityGD32Cores/ArduinoCore-GD32) is still pretty untested, so I will need to get a GD32F130 chip, replace it on a Bluepill, and verify that PWM, ADC and timers all work as expected before trying it on a board where the wrong signal can result in magic smoke release from the MOSFETs.

The split board hoverboards are a near perfect source of high power drivers: I just got a 25V/250W hoverboard with a dead battery for $10. Basically $2.5 each for drivers and motors :) Problem is, they all use different processors and it's a crapshoot to know what you will find when you open one, so a generic framework is the best option. And I'm ok using encoders instead of the Hall motors, if that makes SimpleFOC easier to run on them

Candas1 commented 1 year ago

Also: the "split boards style" hoverboards all have a processor and drive only one motor, communicating with each other over serial. So, all those are great candidates for Simplefoc. It's the first generation boards that used a single processor driving both motors (and using side boards for the IMUs).

Thanks for the additional links @Candas1 (and, yes, it's me on SimpleFOC forums :). I'll have a look at them, especially the Arduino port,

But the GD code (https://github.com/CommunityGD32Cores/ArduinoCore-GD32) is still pretty untested, so I will need to get a GD32F130 chip, replace it on a Bluepill, and verify that PWM, ADC and timers all work as expected before trying it on a board where the wrong signal can result in magic smoke release from the MOSFETs.

The split board hoverboards are a near perfect source of high power drivers: I just got a 25V/250W hoverboard with a dead battery for $10. Basically $2.5 each for drivers and motors :) Problem is, they all use different processors and it's a crapshoot to know what you will find when you open one, so a generic framework is the best option. And I'm ok using encoders instead of the Hall motors, if that makes SimpleFOC easier to run on them

There is even a i2ccommander that could be used to control more than 2 boards.

Again I am not saying it's easy, this will take time. But if we get there we would have made gd32-arduino and simplefoc better, and we can go further than EFeru's FOC as simplefoc has also position control, it's more maintainable and has more support. Last few months I struggled improving EFeru's FOC because of the Matlab model. I started this experiment with the sideboards as a proof of concept because those are mostly splitboards without motor control. I already found some issues with gd32-arduino that need to be fixed.

The quickest solution if you only care about FOC and torque would be the link I shared with EFeru's foc. But you need to find a board that has the current sensing.

If you want to go fast, go alone. If you want to go far, go together

Candas1 commented 1 year ago

And the work recently done by @RoboDurden to document the different board layout is very useful, we could use those different define.h files

Candas1 commented 1 year ago

Thanks Candas1 for your feedback! If simpleFOC is truely object oriented then of course it should support as many motors as there are IO pins availble. And all motors should share the same 16 kHz interrupt to handle the foc control loop. Our hoverbord motors have 90 hall steps per revolution and with 14 rpm/V we have 5-8 revs/s yielding 450-630 Hz. Should be no problem to make a quadratic extrapolation somehow like s(t) = v*t + 1/2 a * t² to boost that to 16 kHz

We have to find such a solution anyway for the modern stm32f403 boards anyway ?

Actually one of the improvements I did on mainboards that I didn't share yet is separating the current sensing and FOC for each motor.

But again mainboards would need even more work on the simpleFOC side, so I would focus on splitboards for now.

The extrapolation is not a problem in normal conditions, but you need to take care of transient cases like when direction changes, EFeru's does this well.

RoboDurden commented 1 year ago

Okay i better cancel my uart chain protocol and start with simpleFOC :-) I was able to compile https://github.com/CommunityGD32Cores/gd32-pio-projects/tree/main/gd32-arduino-blinky with PlatformIO in VisualCode with the readme.me of https://github.com/CommunityGD32Cores/gd32-pio-projects/

i switched to the available genericGD32F130R8 using the project environment switcher in the bottom taskbar. The R8 has the same hardware as the C8 but offers more io pins in the 64 pin package. gd32F130xx devices features

Choosing an led pin from one of my defines2-x https://github.com/RoboDurden/Hoverboard-Firmware-Hack-Gen2.x/tree/main/HoverBoardGigaDevice/Inc should make the blinky code make a hoverboard led blink:

#include <Arduino.h>

#ifdef LED_BUILTIN
#define LED LED_BUILTIN
#else 
#define LED PC13
//#define LED PB13
#endif 

void setup(){
    pinMode(LED, OUTPUT);
}

void loop(){
    digitalWrite(LED, LOW);
    delay(500);
    digitalWrite(LED, HIGH);
    delay(500);
}

I will try to upload the bin file later the day. But i am totally new to PIO (platformIO).

Candas1 commented 1 year ago

You can also check what I did here

RoboDurden commented 1 year ago

Oh yes thanks for the reminder. I was not aware that the sideboards of the gen1 hardware also have a gd32f130 on board. Sideboards gd32f130c6

Now seeing your serial code I am more confident to build a standalone replacement for gen2.x based on simpleFOC. But the i2ccommander has more benefits.

RoboDurden commented 1 year ago

@robcazzaro if you want to join the gd32 coding and live inside Europe I would be happy to ship you two sideboards with a gd32f130c6 for free :-) But you should be willing to spend some hours on the project!

Candas1 commented 1 year ago

Oh yes thanks for the reminder. I was not aware that the sideboards of the gen1 hardware also have a gd32f130 on board. Sideboards gd32f130c6

Now seeing your serial code I am more confident to build a standalone replacement for gen2.x based on simpleFOC. But the i2ccommander has more benefits.

Step by step I wanted to start with a proof of concept that is already useful

RoboDurden commented 1 year ago

Okay i am able to flash with PlatformIO. The flash header in the image of EFeru was wrong for me: https://raw.githubusercontent.com/EFeru/hoverboard-sideboard-hack-GD/main/docs/pictures/sideboard_pinout.png

My header needed GND , DIO , CLK , 3.3V

I powered the board with 14V but no led blinking. So i tried debug but the code seems to halt at startup

gd32F130 first debug

@Candas1 did you succeed with your https://github.com/Candas1/Sideboard-Arduino and the firmware is running and can be debugged ?

RoboDurden commented 1 year ago

YES, the Candas1 Sideboad code works. At least i can debug step by step :-) Tomorrow i will test led output and pwm with his code. Then i might already try to add the simpleFOC library. Great work @Candas1 :-)

robcazzaro commented 1 year ago

@robcazzaro if you want to join the gd32 coding and live inside Europe I would be happy to ship you two sideboards with a gd32f130c6 for free :-) But you should be willing to spend some hours on the project!

Nice collection of sideboards you have, @RoboDurden 😊

I live in the USA, probably shipping cost from Europe would be too much, given the size of those boards. Ordering a couple of Bluepills and GD32F130 from Aliexpress would be around $10, with delivery in <15 days. I have all the necessary tools to swap a processor easily and have done some very fine SMD soldering (0201, BGA). And, now that I think of it, I could get the different GC32 processors used in the split boards, so I could easily test various low level stuff safely. I need to check the HW for the various split boards and ensure I get all the processors used, just in case.

But if you don't mind checking the cost of shipping to Seattle, WA, I'd appreciate if you could let me know the cost, though (I'd pay for shipping)

Definitely happy to cooperate, sounds like a very worthwhile project. Caveat: I'm really good at the low level stuff (debugging, hw registers, timing, etc) and I have a collection of necessary tools (oscilloscope, logic analyzer, etc), not as good at the high level object oriented stuff.

robcazzaro commented 1 year ago

I took some time to look at the various layouts (I have a layout 2 board), and they all seem to use the GD32F130. Most seem to use the GD32F130C8T6, one uses the GD32F130K8, and if I see correctly the layout 4 uses a GD32F130C6T6. So only the F130 family needs to be supported.

@RoboDurden can you please confirm the above?

C8 is the most complete one, C6 has half the FLASH and half the RAM (32k and 4k), one less 16bit timer, only one I2C and SPI buses. The K8 is the same as the C8, obviously with fewer pins than the C8 (32 vs 48).

We need to pay attention to the memory optimizations, it's easy to run out of FLASH or RAM if the Arduino framework doesn't do a good job (on the C6 only, C8 is not a concern).

Based on the above, I'd get a C8 and a C6 processor to install on a Bluepill, as to be able to test every HW variation. I could get a K8 adapter, but the C8 and K8 are the same internally, so I doubt that the pin routing will cause issues. Having a Bluepill would help troubleshoot HW issues (isolate the processor from the rest of the HW), methinks

Candas1 commented 1 year ago

There are some STM32f103 also https://github.com/EFeru/hoverboard-firmware-hack-FOC/wiki/Firmware-Compatibility#splitboards

robcazzaro commented 1 year ago

There are some STM32f103 also https://github.com/EFeru/hoverboard-firmware-hack-FOC/wiki/Firmware-Compatibility#splitboards

Good point 😊. But for those a normal Bluepill suffice, and in any case the Arduino support is fully working. Definitely something to keep in mind, but I was focusing on GD32 HW and worried about the quality of the GD32 Arduino port for things like injected mode ADC, timers, DMA, etc

RoboDurden commented 1 year ago

And yess, finally i can code object oriented on a GD32. These changes in Candas1 main.cpp do work:

class CIO
{   
private:
    int m_iPin;
public:
    CIO(int iPin);
    void Setup(int iType = INPUT_PULLUP);
    void Set(bool bOn = true);
    bool Get(void);
};

CIO::CIO(int iPin){ m_iPin = iPin;  }
void CIO::Setup(int iType){  pinMode(m_iPin, iType);  } 
void CIO::Set(bool bOn){ digitalWrite(m_iPin,bOn); }    
bool CIO::Get(void){  return digitalRead(m_iPin); }

CIO aoLed[5] = {CIO(LED1_PIN), CIO(LED2_PIN), CIO(LED3_PIN), CIO(LED4_PIN), CIO(LED5_PIN) };

void setup()
{
  // Define Leds as output
  for (int i=0; i<5; i++) aoLed[i].Setup(OUTPUT);
  // Turn all Leds ON for half a second and then OFF
  for (int i=0; i<5; i++) aoLed[i].Set(HIGH);
  delay(500);
  for (int i=0; i<5; i++) aoLed[i].Set(LOW);

@robcazzaro shipping to Seattle will simply take too long for joining the party now. I rather donate $5 via paypal to you so you buy some GD32F130 sideboards on used items platform. What layout do you have with your split hoverboards ? The original 2.0 or some newer board ? The 2.0 does not have dedicated gate driver chips and indeed you could shortcut the battery when the highside and lowside mosfet of one phase are set . With the gate driver chips i have the feeling that they do not allow LO and HI to be high at the same time.

RoboDurden commented 1 year ago

I took some time to look at the various layouts (I have a layout 2 board), and they all seem to use the GD32F130. Most seem to use the GD32F130C8T6, one uses the GD32F130K8, and if I see correctly the layout 4 uses a GD32F130C6T6. So only the F130 family needs to be supported.

You mean you have a set of gen2.2 and gen2.4 ? gen2.2 has a K8 on board, gen2.3 and gen2.4 a C8. Maybe the 2.1 layout only has a C6. But this does not really matter. We just have to ensure not to use the additonal hardware of the better MCUs.

I do not see much value in your bluepill approach. A sideboard with its many LEDs and the two photo diodes for analog input on the backside as well as an IMU via I2c and a uart header is fine to test all the basics. And when adding the simpleFOC library we will need 3 meaningful hall sensor inputs and 6 mosfet outputs anyway to see something happen.

RoboDurden commented 1 year ago

Okay i added the simpleFOC library via https://docs.simplefoc.com/library_platformio Then adding this code to main.cpp already compiles:

#include <Arduino.h>
#include <Defines.h>
#include <Config.h>
#include <SimpleFOC.h>

// Hall sensor instance
// HallSensor(int hallA, int hallB , int hallC , int pp)
//  - hallA, hallB, hallC    - HallSensor A, B and C pins
//  - pp                     - pole pairs
HallSensor sensor = HallSensor(2, 3, 4, 11);

// Interrupt routine initialization
// channel A and B callbacks
void doA(){sensor.handleA();}
void doB(){sensor.handleB();}
void doC(){sensor.handleC();}

But before going further with simpleFOC i should test the bascics the library needs. Timer, interrupts, analogRead i guess.

Candas1 commented 1 year ago

I was reading this thread again https://community.simplefoc.com/t/hoverboard-main-board-with-simplefoc/2610/19?u=candas1

It could be more work for pwm and adc

RoboDurden commented 1 year ago

Sure but I should find all the gd32 init code needed in my gen2.x repo

robcazzaro commented 1 year ago

You mean you have a set of gen2.2 and gen2.4 ? gen2.2 has a K8 on board, gen2.3 and gen2.4 a C8. Maybe the 2.1 layout only has a C6. But this does not really matter. We just have to ensure not to use the additonal hardware of the better MCUs.

I do not see much value in your bluepill approach. A sideboard with its many LEDs and the two photo diodes for analog input on the backside as well as an IMU via I2c and a uart header is fine to test all the basics. And when adding the simpleFOC library we will need 3 meaningful hall sensor inputs and 6 mosfet outputs anyway to see something happen.

I have a "layout 2.0" board, the one without gate drivers. So it's not safe for development for an unproven core like the GD32 one. And I have no way to buy a sideboard. I could try to look for used hoverboards locally, but most sell in the $75-$150 range and it's a crapshoot on what I will find in those. I have bought 2 already, one uses split boards with MM32SPIN05PFOP, which is a really different processor, and one has the layout 2.0 split boards. And I'd rather not kill those 😊

So I was thinking that, if I want to help, my best option is to have a Bluepill with the right processor. Also, in my experience, when chasing problems (like ADC sampling noise), it's convenient to have a known good reference board to identify problems due to the processor quirks vs the board components itself.

Otherwise I can wait until you have a working implementation on the layout 2.0, and at that point use my split boards as development platforms.

Any other suggestion?

RoboDurden commented 1 year ago

Okay @robcazzaro it might indeed be more fruitful if we each follow a siglthy different route. So you with a bare gd32 might test and solve problems that I can not.

robcazzaro commented 1 year ago

Sure but I should find all the gd32 init code needed in my gen2.x repo

In the past I looked at the STM32duino implementation. It relies very heavily on the STM32 HAL, to the point of adding al ot of problems and workarounds for those problems. And SimpleFOC really builds on top of that abstraction, too.

So I expect problems with more complex aspects like injected ADC sampling and timers. I might well be wrong, but I'd be surprised if you don't run into some unexpected behavior due to the differences between the GD32F130 and STM32F103 (to be clear: not doubting your skills). The GD32F103 is pretty much directly compatible, but not the F130. That's where I think that a dev board might be necessary and a good backup to have if anything goes wrong on your side

Candas1 commented 1 year ago

I worked on injected adc for stm32f1, I should be able to help on gd32f130. I have a power supply, oscilloscope, and probably any type of splitboard.

robcazzaro commented 1 year ago

I worked on injected adc for stm32f1, I should be able to help on gd32f130. I have a power supply, oscilloscope, and probably any type of splitboard.

Whoops. I started looking into the GD32F130 reference manual, and the ADC is significantly simplified compared to the STM32F103. There's no injected mode at all, and many fewer modes...

So a new ADC strategy is needed for GD32F130-based boards

STM32F103 (look at bit 7, 10, 12, 16-19, 22, all "reserved" in the GD32) image

GD32F130 image

Candas1 commented 1 year ago

Weird, I saw that in the spl drivers https://github.com/RoboDurden/Hoverboard-Firmware-Hack-Gen2.x/blob/c350d800c7913a62c501d02a916795ebcdea70dc/HoverBoardGigaDevice/RTE/Device/GD32F130C6/gd32f1x0_adc.c#L374

robcazzaro commented 1 year ago

Weird indeed... it's there, even in the SPL downloaded directly from the Gigadevice site (https://www.gd32mcu.com/download/down/document_id/288/path_type/1), but it looks like the SPL is referring to registers that, at least according to the reference manual (https://www.gigadevice.com.cn/Public/Uploads/uploadfile/files/20230209/GD32F1x0_User_Manual_EN_Rev3.6.pdf) don't exist. The reference manual jumps from register 0x34 to 0x4C, while the SPL uses all these

define ADC_ISQ REG32(ADC + 0x00000038U) /!< ADC inserted sequence register /

define ADC_IDATA0 REG32(ADC + 0x0000003CU) /!< ADC inserted data register 0 /

define ADC_IDATA1 REG32(ADC + 0x00000040U) /!< ADC inserted data register 1 /

define ADC_IDATA2 REG32(ADC + 0x00000044U) /!< ADC inserted data register 2 /

define ADC_IDATA3 REG32(ADC + 0x00000048U) /!< ADC inserted data register 3 /

define ADC_RDATA REG32(ADC + 0x0000004CU) /!< ADC regular data register /

The scary part is that I can find mentions of "inserted ADC" in an old version of the reference manual (2.0 from Jan 2016, latest is 3.6 from Jul 2022), so it looks as if they determined that the inserted ADC is not reliable enough to be documented anymore (it happens a lot in the embedded space, ST also has a lot of errata recommending not to use certain functions in certain HW revisions)

So this is something that might or might not work reliably...

EDIT: It was documented still in V3.1, from Jan 2018 https://www.zlgmcu.com/data/upload/file/Utilitymcu/GD32F1x0_User_Manual_EN_v3.1.pdf. But not anymore in official Gigadevice docs

Candas1 commented 1 year ago

Maybe it's worth trying. But keep in mind the current EFeru FOC is not even using injected adc.

robcazzaro commented 1 year ago

Maybe it's worth trying. Keep in mind the current EFeru FOC is not even using injected adc.

Oh,, yes, definitely worth trying. Sorry, didn't really mean to discourage it, mostly just point out that it might have issues. It's always better to have a sense of which areas might require more attention. It's very possible that Gigadevice found some edge case and decided to officially drop the support while keeping it in the SPL. Plausible deniability in case the customer finds a problem...

RoboDurden commented 1 year ago

Yes, analogRead does not seem to be fully functional:

  unsigned long timeNow = millis();
  int iAnalog1 = analogRead(SENSOR1_PIN);
  int iAnalog2 = analogRead(SENSOR2_PIN);
  digitalWrite(LED1_PIN, (timeNow % (iAnalog1*2)) < iAnalog1 );
  digitalWrite(LED2_PIN, (timeNow % (iAnalog2*2)) < iAnalog2 );

Both led are blinking to the frequency of iAnalog1 read from SENSOR1_PIN At least analogRead(SENSOR1_PIN); does output an analog value as i can slow down the blinking by inserting a light blocker into the backside photo detector.

Sideboard adc

analogRead(SENSOR2_PIN); seems to output zero and the leds are not blinking at all. So when i simply replace the two analogRead lines, BOTH led stop blinking:

  unsigned long timeNow = millis();
  int iAnalog2 = analogRead(SENSOR2_PIN);
  int iAnalog1 = analogRead(SENSOR1_PIN);
  digitalWrite(LED1_PIN, (timeNow % (iAnalog1*2)) < iAnalog1 );
  digitalWrite(LED2_PIN, (timeNow % (iAnalog2*2)) < iAnalog2 );

When i put a delay(100); in between the two analogRead, then everything works as expected. (Apart from SENSOR2_PIN maybe not being PC14)

RoboDurden commented 1 year ago

But it is nice to simple hit F12 on analogRead an quickly end up here: https://github.com/CommunityGD32Cores/ArduinoCore-GD32/blob/main/cores/arduino/analog.cpp#L180

I guess GD32F1x0 is defined for me ? So the following delay(1U); seems to be to short.

robcazzaro commented 1 year ago

But it is nice to simple hit F12 on analogRead an quickly end up here: https://github.com/CommunityGD32Cores/ArduinoCore-GD32/blob/main/cores/arduino/analog.cpp#L180

I guess GD32F1x0 is defined for me ? So the following delay(1U); seems to be to short.

But that line is only executed once, when the ADC is invoked for the first time and it gets calibrated. There is a small delay between enabling the ADC and calibrating it. After the initial calibration, that code is not executed anymore. Lines 195-199 are executed each time to read the actual value

adc_regular_channel_config(0U, channel, ADC_SAMPLETIME_7POINT5);
adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
while (!adc_flag_get(ADC_FLAG_EOC));
adc_flag_clear(ADC_FLAG_EOC);
value = adc_regular_data_read();

And that code doesn't seem to need a delay, since it check the end of ADC conversion before reading the value. A delay in the Arduino code should not make a difference, unless there is a timing issue with clearing the flag...

I ordered the GD32F130 and the sacrificial Bluepill, now waiting for the delivery. This is the kind of stuff I'm usually good at, but I need a debug board to be able to look into it...

RoboDurden commented 1 year ago

I guess i better move on to the Gen2.2 test setup and spend my time debugging the SimpleFOC components :-/ When i comment the first analogRead in the sideboard firmware, the code hangs exactly at

while (!adc_flag_get(ADC_FLAG_EOC));

Maybe A4 needs to be initialized before C14 :-/

56 seconds video: https://youtu.be/DjCeojvbNx8

As HallSensor sensor = HallSensor(2, 3, 4, 11); already compiles and only needs digitalRead and interrupts, i better start debugging that :-)

@Candas1 , tell me if you would like me to continue testing your nice sideboard project. How ist that #define DEBUG_SERIAL rtt working ? Does it use the st-link and some PIO feature ? I simple printed to Serial2 = HOVER_SERIAL. Where are the rx and tx pins of Serial2 are set ??

Good night and good luck.

In case you haven't yet noticed my masterplan for world peace: https://youtu.be/GeG9Alww80M -> www.RoboDurden.de

Candas1 commented 1 year ago

I guess i better move on to the Gen2.2 test setup and spend my time debugging the SimpleFOC components :-/ When i comment the first analogRead in the sideboard firmware, the code hangs exactly at

while (!adc_flag_get(ADC_FLAG_EOC));

Maybe A4 needs to be initialized before C14 :-/

56 seconds video: https://youtu.be/DjCeojvbNx8

As HallSensor sensor = HallSensor(2, 3, 4, 11); already compiles and only needs digitalRead and interrupts, i better start debugging that :-)

@Candas1 , tell me if you would like me to continue testing your nice sideboard project. How ist that #define DEBUG_SERIAL rtt working ? Does it use the st-link and some PIO feature ? I simple printed to Serial2 = HOVER_SERIAL. Where are the rx and tx pins of Serial2 are set ??

Good night and good luck.

In case you haven't yet noticed my masterplan for world peace: https://youtu.be/GeG9Alww80M -> www.RoboDurden.de

Have you seen this? https://github.com/Candas1/Sideboard-Arduino#debug

robcazzaro commented 1 year ago

I guess i better move on to the Gen2.2 test setup and spend my time debugging the SimpleFOC components :-/ When i comment the first analogRead in the sideboard firmware, the code hangs exactly at

while (!adc_flag_get(ADC_FLAG_EOC));

Maybe A4 needs to be initialized before C14 :-/

56 seconds video: https://youtu.be/DjCeojvbNx8

It looks as if the ADC is not properly initialized for SENSOR2_PIN. Even if I don't have the board, I can probably still help. Do you have a repository with the code you are trying to run? Ideally the full Platformio project directory.

That way I can look at the same code you are, and we can proceed in parallel

EDIT: are you even sure that SENSOR2_PIN is connected to an ADC input? If I read the docs in your repository correctly, the light barrier are connected to PA7 and PA11. According to the datasheet )https://www.gigadevice.com.cn/Public/Uploads/uploadfile/files/20230314/GD32F130xxDatasheetRev3.7.pdf) PA7 can be used as ADC_IN7, but PA11 has no ADC connection possible. If so, that would explain why one channel works but not the other. Granted, the SPL should generate an exception when you try to use an unsupported pin, but many of those low level libraries are written assuming that the user knows which pins to use

RoboDurden commented 1 year ago

@robcazzaro , very nice to see someone so motivated to help !!! Do not really understand that. Who are you ? Do you have a youtube channel ?

So yes i happily forked the sideboard repo from Candas1 and added my code for you: https://github.com/RoboDurden/Sideboard-Arduino/blob/master/src/main.cpp

It is showing the same strange behavior as in my 57 seconds video.

The sensor pins are A4 and C14 and defined in https://github.com/RoboDurden/Sideboard-Arduino/blob/master/include/defines.h#L13

I doubt that A4 is correct as the analogRead only gives 0 (Except when it doubles the analogRead of C14with no delay(10) ) The mcu is the C6 variant. According to the datasheet, A4 (Default: PA4, Alternate: SPI0_NSS, USART1_CK, TIMER13_CH0, SPI1_NSS, Additional: ADC_IN4) can be an analog input, but PC14 (Default: PC14 Additional: OSC32IN) not.

I guess i should probe the pin connections with a needle on the hardeware :-/ But as i said, i rather want to move on to my gen2.2 test setup.

Maybe the analogRead of sensor2 = C14 simply shows the read of A4 because of timing issues and then of course removing the analogRead of sensor1 = A4 will cause the analogRead of C14 to hang.

The pinout of the sideboard repo is based on https://raw.githubusercontent.com/EFeru/hoverboard-sideboard-hack-GD/main/docs/pictures/sideboard_pinout.png , i think.

RoboDurden commented 1 year ago

indeed, when i remove the C14 analogRead,

  iAnalog1 = analogRead(SENSOR1_PIN);
  //delay(10);
  //iAnalog2 = analogRead(SENSOR2_PIN);
  digitalWrite(LED1_PIN, (timeNow % (iAnalog1*2)) < iAnalog1 );
  //digitalWrite(LED2_PIN, (timeNow % (iAnalog2*2)) < iAnalog2 );

then analogRead of A4 just works nicely:

A4: 381  C14: 1000
A4: 381  C14: 1000
A4: 381  C14: 1000
A4: 380  C14: 1000

So i guess #define SENSOR2_PIN PC14 is wrong. Thanks @robcazzaro for the idea to look in the GD32 datasheet :-)

Candas1 commented 1 year ago

I will also try from my side. I only tried digitalread with those sensors so far, that's how it works in EFeru's sideboard firmware.

robcazzaro commented 1 year ago

Exactly. As per the datasheet

image

.

image

That means that PA4 is a valid pin for the ADC, while PC14 cannot be used as an ADC pin. So the call using PA4 works, because the pin is a valid ADC input, while the call using PC14 hangs: PC14 is not a valid ADC input pin, so the ADC conversion never takes place and the "ADC is done" flag is never set. That "while" loop checking for the completion flag never exits. PC14 can be used as a digital GPIO (or for the oscillator), so it can be read as a digital value.

In general, embedded libraries don't do much error check for things like these. After all, these devices are fixed function and there is no value in doing runtime checks for pin assignment. Once the firmware works, there's no point in checking thousands of times a second if the ADC pin is valid 😉. The best embedded libraries check for things like these in "debug mode", raising an ASSERT and stopping execution, but in "release mode", simply define the ASSERT as an empty macro, removed by the compiler. That way you save time during the initial code writing (for things like the one you just ran into), and don't pay a penalty at runtime.

From the little I could see, the Gigadevice SPL is pretty good and streamlined, not as messy and wasteful as the STM32 HAL. On the other hand, no safety checks.

Candas1 commented 1 year ago

OK that's a missunderstanding then This is how we use those sensors

RoboDurden commented 1 year ago

yes my fault again. As there are no counter springs in that slides of the hoverboard that close the photo diodes, they must be digital only.

So i added a user header to get three digital inputs and successfully attached a hoverboard motor:

sideboard GD32F130C6 stlink and user header

sideboard test hall setup

simple digitalread in loop works:

  for (int i=0; i<3; i++)
  {
    boolean bOn = aoHall[i].Get(); 
    Serial2.print(bOn); Serial2.print("  ");
  }
0  1  1  A4: 668   C14: 1000
1  1  0  A4: 668   C14: 1000
1  1  0  A4: 669  C14: 1000
1  0  0  A4: 669  C14: 1000
1  0  1  A4: 669  C14: 1000

So i can now test the HallSensor sensor = HallSensor(2, 3, 4, 11);on a sideboard :-)

Candas1 commented 1 year ago

Nice. From my side I still need to figure out why usart RX fails after some time. I need to get I2C to work as well. I found out the default pins for I2C are not the ones we use on sideboards. We use PB6 and PB7.

Candas1 commented 1 year ago

I am updating the readme as I go so don't hesitate to check it. There is a simple debug menu now. And you can use 433mhz receiver/remotes.

I already see it's faster to implement new features thanks to all the libraries that are available. And it works for both STM32 and GD32. The downside is that ram and flash usage grows very quickly. I also need to find a good way to structure the code, I don't like having all the code in main.cpp.

RoboDurden commented 1 year ago

Good morning Candas1 :-) Indeed i dislike this non-OO c-style #ifdef confusion in main.cpp. My first idea would be to define a abstract/virtual class CControl wit a ::loop method and derive from that class all the features people might want to add. Then one array CControl aoControl[SIZE] with all of them and in (loop) simply for(int i=0; i<SIZE; i++) aoControl[i].loop();

I think that was somehow my idea for the "hoverboard operating system". All the different input methods of the EFeru firmware would be base on one abstract class CControl and the user would simply uncomment setting a derived class to the oControl.


I have trouble reading all the 3 hall inputs. The PA1 pin (not 5VT and 1kOhm) seems to work finde with the interrupt, but PA9 and PA10 (rx,tx , 5VT, no 1kOhm) does not seem to work and might even have killed the hall sensors in the bldc. I think i really should move on to the true hardware where the hall inputs get their propper hardware.

Candas1 commented 1 year ago

The #ifdef are there to completely remove the code for given features if it's not needed. As an example, when you debug the code is compiled without most of the code optimizations, so it won't fit in flash without turning features off.

In any case, I want something that works first, and then I will improve the code if needed. I will probably create additional files for IMU, debug, ....

RoboDurden commented 1 year ago

With

//CControl oControl = CControlADC(...):
CControl oControl = CControlUart(...):
//CControl oControl = CControlNunchuk(...):
//CControl oControl = CControlHoverboard(...):

you would also only compile the CControlUart code.

object oriented programming is a totally different approach to problem solving. You can not add it afterwards..