zapta / simple_stepper_motor_analyzer

A DYI stepper motor analyzer. This is a new design that is based on Raspberry Pi Pico and users a compact single PCB design. NOTE: The legacy STM32 based stepper analyzer was moved to this repository https://github.com/zapta/legacy_stepper_motor_analyzer.
Other
145 stars 33 forks source link

Question about ADC reading and code structure. #10

Open AndyEveritt opened 2 years ago

AndyEveritt commented 2 years ago

I can not currently source the ACS70331EOLCTR-2P5B3 current sensors so I have been looking for alternatives.

I found this sensor from TI https://www.ti.com/lit/ds/symlink/tmcs1101-q1.pdf?HQS=dis-dk-null-mousermode-dsf-pf-null-wwe&ts=1641839042153 which seems to be approximately the same, but the sensitivity for the 3.3V version only goes up to 200mV/A (instead of 400mV/A).

To make sure that I could change the source code to accept this sensor I looked for where the sensitivity and and current range is set. Potentially I am misunderstanding but the datasheet for the current sensor says its +/-2.5A with 400mV/A and 1.5V at 0A. image

In the code src/misc/hardware_config.h, the sensor struct appears to be defined

struct SensorSpec {
  const char* name;
  const uint16_t range_milliamps;
  const float volts_per_amp;
  // These computed values are cached to speed up unit conversions.
  const float counts_per_amp;
  const float amps_per_count;
  const float milliamps_per_count;

  SensorSpec(const char* name_, uint16_t range_milliamps_, float volts_per_amp_)
      : name(name_),
        range_milliamps(range_milliamps_),
        volts_per_amp(volts_per_amp_),
        counts_per_amp(volts_per_amp * 4096 / 3.3),
        amps_per_count(1 / counts_per_amp),
        milliamps_per_count(1000 / counts_per_amp) {}

  // Convert adc value to milliamps.
  int adc_value_to_milliamps(int adc_value) const {
    return (int)(adc_value * milliamps_per_count);
  }

  // Convert adc value to amps.
  float adc_value_to_amps(int adc_value) const {
    return ((float)adc_value) * amps_per_count;
  }
};

As far as I can tell the conversion of adc value to (milli)amps does not take into account the 1.5V @ 0A offset that the sensor has?

For example, you create an instance of this struct using static const SensorSpec GMR_2P5_SENSOR("G2P5A", 2500, 0.4);. If the sensor was measuring 0A, it would output 1.5V, I believe this would read 2048 on the ADC (if you are using the an external 3.0V shunt reference for the ADC_VREF pin to improve ADC performance, which I can't see in the schematic either so might be a nice addition? Otherwise it will read ~1862).

Having just gone even deeper into trying to understand the code, I have now found that there is an offset for each of the ADC's in src/aquisition/analyzer.h which is applied to the value before it is converted to (milli)amps, which answers my question about if the sensor offset was being accounted for.

My new question (based on trying to get more familiar with embedded programming by learning from others) is why have you split the offset and other current sensor specific variables across 2 structs? I assume it is because the offset varies sensor to sensor so you need to calibrate it dynamically which would mean you couldn't use const for the sensor definition, which I assume is for some minor speed gain?

I appoligse for the long and convoluted question. I started typing as I was discovering to keep track of my train of thought. In essence, I would just like to understand why you have structured the code the way you have so I can learn and either apply or avoid it in my own coding.

Also it may be interesting to apply the recommended change to the circuit to improve the ADC performance image

globalcitizen commented 2 years ago

The TI part is hall effect based. The originally specified part was GMR. There are also TMR parts. This paper and this site explain the differences. Based on that, maybe it would be best to look for TMR parts and these guys seem promising.

zapta commented 2 years ago

In another forum, somebody suggested this one https://www.mouser.it/ProductDetail/ACEINNA/MCA1101-5-3?qs=PzGy0jfpSMs%252BNw%2FnqBFIdA%3D%3D . May require configuration tweaks because it has a different A/V sensitivity.

It's difficult to find parts these days.

On Fri, Apr 22, 2022 at 6:43 PM Walter Stanish @.***> wrote:

The TI part is hall effect based. The originally specified part was GMR. There are also TMR parts. This paper explains the differences https://crocus-technology.com/wp-content/uploads/2019/03/AN117-From-Hall-Effect-to-TMR-Rev0.1.pdf .

Based on that, maybe it would be best to look for TMR parts and these guys https://www.sinomags.com/En.html seem promising.

— Reply to this email directly, view it on GitHub https://github.com/zapta/simple_stepper_motor_analyzer/issues/10#issuecomment-1107165291, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAQVMQLE5LOC7XABWGUS7NTVGNITLANCNFSM5OAJN3FQ . You are receiving this because you are subscribed to this thread.Message ID: @.***>

globalcitizen commented 2 years ago

Yep. MCA1101-5-3 is AMR based, according to the datasheet. This 2015 review (part one, part two compares AMR to the other approaches in more quantum physical detail than my mathematical literacy will stand for. But the result seems to be: if it's not TMR, it's functionally prior-generation and therefore potentially not the best thing to design for in terms of design longevity.