Commit 86c2b1f1 authored by Jake Read's avatar Jake Read
Browse files

working on speed measurement

parent 58d2e446
......@@ -92,7 +92,7 @@ void flash_write_value(float val){
void Step_CL::print_table(void){
sysError("reading from lut");
for(uint32_t i = 0; i < ENCODER_COUNTS * 2; i ++){
for(uint32_t i = 0; i < ENCODER_COUNTS; i ++){
float ra = lut[i * 2];
float pa = lut[i * 2 + 1];
sysError("real angle at enc " + String(i) + ": " + String(ra) + "phase angle: " + String(pa));
......@@ -123,23 +123,23 @@ void Step_CL::run_torque_loop(void){
#define MAP_7p2_TO_1 (1.0F / 7.2F)
#define TICKS_PER_SEC 50000.0F
#define SECS_PER_TICK 1.0F / TICKS_PER_SEC
volatile float _ra;
volatile float _ra_last;
volatile float _ra_s; // real angle / sec
volatile float _deg_s; // real angle / sec
volatile float _pa;
float Step_CL::get_deg_sec(void){
return _deg_s;
}
void ENC_AS5047::on_read_complete(uint16_t result){
if(step_cl->is_calibrating) return;
_ra = lut[result * 2]; // the real angle (position 0-360)
_pa = lut[result * 2 + 1]; // the phase angle (0 - 1 in a sweep of 4 steps)
// want to calculate speeds,
//here
// need to calculate speed but in context of wrap'd angle: is there a quick way?
// then test with scope
// then do JS running some loop, maybe 1khz possible? *awk face* send cmd effort down, retrieve datas
// probably just will want to retrieve speed ... then see about sweeping the field to build your table,
// then next step would be real calib against something known ?
_ra_s = (_ra - _ra_last) / TICKS_PER_SEC;
// just this is not going to be good enough: have to wrap that angle
_deg_s = (_ra - _ra_last) * TICKS_PER_SEC;
_ra_last = _ra; // upd8 for next tick
// this is the phase angle we want to apply, 90 degs off & wrap't to 1
if(step_cl->get_torque() < 0){
......
......@@ -33,6 +33,7 @@ class Step_CL {
void print_table(void);
void set_torque(float tc);
float get_torque(void);
float get_deg_sec(void);
void run_torque_loop(void);
boolean calibrate(void);
boolean is_calibrating;
......
......@@ -175,6 +175,8 @@ void OSAP::handleAppPacket(uint8_t *pck, uint16_t pl, uint16_t ptr, uint16_t seg
reply[rl ++] = AK_SET_TC;
chunk_float32 tcs = { .bytes = { pck[ptr ++], pck[ptr ++], pck[ptr ++], pck[ptr ++] }};
step_cl->set_torque(tcs.f);
float deg_sec = step_cl->get_deg_sec();
ts_writeFloat32(deg_sec, reply, &rl);
break;
}
default:
......
......@@ -1063,7 +1063,65 @@ So the first move is to build in to the lower level a velocity measurement. For
What's a reasonable 'end spiral' for this?
- do phase advance parameter,
I do want to get to phase advance today & the beginnings of the JS 'looping' interface: that will determine if I need to build better underlaying architecture before continuing... py serial, or rpi node->uart.
### Phase Advance
So let's see... I want to know about angular velocity's relation to RPM / relation to angular phases / second.
```
1 rpm = 6 deg/s
7.2 deg/s = 1 magnetic phase / sec
```
So there is a nice kind of parity here,
```
1 rpm = 0.83 magnetic phase / sec
```
Supposing that the stator 'points' immediately at the end of each loop, I'll have one speed limit related to the angular travel in between each loop: if I set my phase 90deg ahead at the end of one loop, but the rotor is moving more than 90deg (magnetic: 1.8 physical) per loop period, I'm in trouble. This limit actually seems quite high: it's about 15krpm.
| rpm | deg/s | mag phases / sec | us / mag phase | us / quarter mag phase |
| --- | --- | --- | --- | --- |
| 15000 | 90000 | 12500 | 80 | 20 |
| 10000 | 60000 | 8333 | 120 | 30 |
This doesn't mean that's *absolute max* speed, it's just a crossing point where I would be applying some negative torque during part of the rotation if I went any faster.
Since optimal torque is applied at 90* out of phase with the current rotor position, to do this ideally I would set the magnetic vector of the stator ahead of 90* by 1/2 of the phase angle covered by the rotor during the loop time, so that, during the rotation taking place during this period of the loop, the effective angle would average to 90*.
Of course, I'm not pointing my magnetic vector *immediately* when I write the DACs - indeed, even the chopper drive in the A4950s has a 25us fixed off time during current decay, about half of my loop cycle time.
![chopper](2020-10-17_a4950-decay-time.png)
Besides this, there's the actual rise time of the coils: the real magnetic lag. This means that in reality, I'll want to set my phase advance well ahead of the *ideal* 90 deg, to compensate for slower parts of the system.
Were I a bit more intrepid, I could do things like measure phase inductance, etc, and could probably figure pretty well exactly how far ahead it were reasonable to set the phase advance. However! In reality, this is probably a tuned variable: and one that is probably not hard to search for.
### Roughing It
That said! I want to set it and forget about it for now: I can come back here if I ever want to chase some more gains. I showed up here just trying to ballpark a first guess. Basically, I think I should set my phase advance at 90deg when rpm = 0, and then scale it to a maximum of 180deg when things are going quite fast: based on my control-loop-speed guessing above (where the abs max before crossover was 15krpm) and based on my intuitive knowledge that I am unlikely to spin this stepper faster than 10krpm, I'll set the top there.
```
where 0.5 == 180 degs of phase advance
phase advance = 0.25 + min(0.25, deg/s * 0.000004)
```
This is a kind of crazy small floating point, and I besides need to calculate my speed - which, really, I should do some filtering there because I know there's a few ticks of error in the encoder.
### Speed Maths
Discrete deeeeeerivatiiiives
I think this is probably not hard, however, doing it fast is maybe more challenging. I also need to set up some infrastructure I think to do it well: this js looping situation. Maybe that first.
- phase advance can be 'roughly' to do 0.25 + min(speed * x, 0.25) where x is set such that speed * x goes to 0.25 around 2000rpm (by intuition) but really I should make a spreadsheet to figure where (if current writing is direct) the pole-rotation time starts to sync with the 50khz, you know what I mean?
- also read ur datasheets abt current chopping time ?
- in the end, phase advance probably just tuned
- do manuel-set phase advance parameter,
- do js interface for tc down, degs/sec up, plot on loop
- see about sweeping parameter space, learning real torque
- measure against real values, from, what?
\ No newline at end of file
- measure against real values, from, what?
- to learn PID, command PID params down, return accumulated error over set evaluation period, do learning over sample gcodes ? means integration into bus, etc
- seems likely that PID learning is related to acceleration setting in smoothie, maybe somehow do multiple accel vals? also return w/ pid an average effort used, and a maximum? ideally tunes motor PID, and per-axis accel all together
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment