Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 8 of 8

Thread: Teensy 3.2 Air core gauge. 3pin

  1. #1

    Teensy 3.2 Air core gauge. 3pin

    I got a hold on few 3 pin air core stepper gauges. How I shoud drive them ? Is it the same as 4 pin? With sin & cos ? Plan is to put one of them to show coolant temperature in a car cluster. Should I use designated air gauge chip instead and feed signal to it from teensy ? Teensy is doing CAN bus reading anyhow.
    Gauges are internally wired that one end of both coils are tied together and other ends are separate.

  2. #2
    This has gone further a bit. I decided to use ordinary stepper motor as coolant temperature gauge and air core gauge as speedometer. For speedometer I ordered couple LD8190 DIP16 chips. This leads me to a question.
    How I can scale stepper motor steps to the signal what it follows? I tried to use map command but it didn't go well with it or I did something wrong here.

    Here is the code without map command. I have been playing with divider and multiplying in the code. But it is still way off.
    Teensy is reading Megasquirt CANbus and turning it's coolant temperature value to stepper motor steps. Input value is not 0-255. It is 140 at 60'c and 1400 at 120'c. So how to scale stepper so that that all happends in lets say 500 steps or less? Best is not to move at all under 60'c. I think that could be done with if/or/else commands afterwards?
    #include <FlexCAN.h>
    #include <Stepper.h>
    #define STEPS 600
    static CAN_message_t txmsg, rxmsg;
                        //18 19 5 20
    Stepper stepper(STEPS, 5, 20, 18, 19);
    long previous = STEPS /2;
    //Megasquirt data vars
    byte indicator[7]; // where to store indicator data
    float  BATTV, IAC, dwell, idle_tar, AFRtgt, AFR, newBATTV, oldBATTV;
    unsigned int MAP, SPKADV, RPM, TPS, MAT, CLT, injduty, Baro, PW1, nexAFR, nexCLT;
    void setup() {
        Serial.begin(115200); //***Uncomment this section to output CAN message IDs to Serial Monitor***
    void loop(void) {
      //Look for CAN broadcasts
      if ( ) {
        switch ( { // ID's 1520+ are Megasquirt CAN broadcast frames. EAch frame represents a data group
          case 1520: // Group 0
            RPM = (float)(word(rxmsg.buf[6], rxmsg.buf[7]));
            PW1 = (float)(word(rxmsg.buf[2], rxmsg.buf[3]));
            injduty = ((PW1 / 1000 * RPM / 120) / 10);
          case 1521: // Group 1
            SPKADV = (float)(word(rxmsg.buf[0], rxmsg.buf[1]));
            indicator[0] = rxmsg.buf[3]; // engine
            AFRtgt = (float)(word(0x00, rxmsg.buf[4]));
          case 1522: // Group 2
            Baro = (float)(word(rxmsg.buf[0], rxmsg.buf[1]));
            MAP = (float)(word(rxmsg.buf[2], rxmsg.buf[3]));
            MAT = (float)(word(rxmsg.buf[4], rxmsg.buf[5]));
            CLT = (float)(word(rxmsg.buf[6], rxmsg.buf[7]));
            nexCLT = (float)(word(rxmsg.buf[6], rxmsg.buf[7]));
          case 1523: // Group 3
            TPS = (float)(word(rxmsg.buf[0], rxmsg.buf[1]));
            BATTV = (float)(word(rxmsg.buf[2], rxmsg.buf[3]));
            AFR = (float)(word(rxmsg.buf[4], rxmsg.buf[5]));
            nexAFR = (float)(word(rxmsg.buf[4], rxmsg.buf[5]));
          case 1524: // Group 4
          case 1526: // Group 6
            IAC = (float)(word(rxmsg.buf[6], rxmsg.buf[7])); //IAC = (IAC * 49) / 125;
          case 1529: // 9
            dwell = (float)(word(rxmsg.buf[4], rxmsg.buf[5]));
          case 1530: // Group 10
            indicator[1] = rxmsg.buf[0]; // status 1
            indicator[2] = rxmsg.buf[1]; // status 2
            indicator[3] = rxmsg.buf[2]; // status 3
            indicator[6] = rxmsg.buf[6]; // status 6
            indicator[7] = rxmsg.buf[7]; // status 7
          case 1537: // Group 17
          case 1548: // Group 28
            idle_tar = (float)(word(rxmsg.buf[0], rxmsg.buf[1]));
          case 1551: // Group 31
          case 1574: // Group 54
            indicator[4] = rxmsg.buf[2]; // cel
              long val = (long)CLT * STEPS /400 ;
          stepper.step(val - previous);
      previous = val;

  3. #3
    Senior Member
    Join Date
    Nov 2017
    Assuming the coolant tmp returned by the CAN bus can be < 60deg or > 120deg but you want the stepper only to move between 60deg and 120deg and that the temp reading is linear.

    I took the liberty to rename a few variables to make it more readable.

    //the physical stepper position needs to be manually set at the 60deg position before powering the teensy
    //or during setup with the help of an end switch
    long current_stepper_pos = 0; //corresponds to 60deg
    void setup() {
      //home stepper
    void loop() {
      //read CLT from CANbus
      if(CLT < 140) CLT = 140;
      if(CLT > 1400) CLT = 1400;
      long desired_stepper_pos = map(CLT, 140, 1400, 0, 499); // map temp to 500 steps
      long steps_to_move = desired_stepper_pos - current_stepper_pos;
      current_stepper_pos = desired_stepper_pos;

  4. #4
    Thank you so much! Your tweaks worked very nice. Of course I remembered clt values wrong and step amount needed to be way less than 500. But I managed to make it work. Found out that everyday situation shutting car down engine hot and starting up again when cold didn't work at all with the code. That is of course because code doesn't know where stepper is when Teensy is powered up. I added -200 steps every powerup. It works but it is a bit crude.

    Let's see what issues speedometer brings on in time. I do have working gps signal code from earlier speedometer tryout, so it should be easier..

  5. #5
    Got the air core gauge connected to LD8190. Found out that gauge control isn't too easy. With Tone function, gauge oscillates badly. By increasing frequency oscillation get's wider and so fort. But never stops. With analogWrite function gauge is stable but I have to use way too high pwm values to be usable.
    Here should be working url for the chip
    I did measure needed pointer swing angle and as gauge coil resistance is same in example in the sheet so I used it to build it. Modded the gauge motor from 3 pin to 4pin.

  6. #6
    I've done more bench testing and head scraching. Found out that my megasquirt can bus to speedo code isn't working too well and that causes the oscillation. Simple tone command doesn't oscillate at all. But the main thing is that the swing is not near what it should be. And the CS8190 what I got is getting very hot very soon. 320mA is going through it when running just tone command. I need about 120 degrees of swing at 160hz input frequency and all I have is let's say 20 degrees at 160hz. Over 160hz doesn't swing it further so something is right.. or not.

  7. #7
    YES ! It works.
    Looks like all what I had wrong was wrong pin in teensy code + major bugs in can bus code.
    As 4pin modded gauge motor is very skechy I tried 3 pin again and it works too. Maybe it is a bit less accurate. But we will see that. Now it is time to make a test install gauge to the cluster.

  8. #8
    This has gone now back to the zero after fiqure eight. I had to discard air core gauge speedometer because it was way too weak and therefore not possible to scale the view propely. There was nasty mechanical failures too in the dash.

    I reverted back to the stepper motor speedo. So from now on I have two 4 wire stepper motors running coolant gauge and speedometer. I understand and tested for practise that Stepper.h is really easy use and therefore best to me but it is blocking type. Answer is clearly AccelStepper.h.

    I've tried to make this very basic few steps clockwise and same amount steps counter clockwise Stepper.h code in AccelStepper. I just cant make it work. Either needles moves very slowly one in the time or one goes wrong direction and then nothing. Could somebody give me an direction and turn this Stepper.h code to AccelStepper? Thanks

    #include <Stepper.h>
    #define STEPS 250
    Stepper nopeus(STEPS, 5, 6, 9, 10);
    Stepper lampo(STEPS, 22, 21, 20, 23);
    void setup() {
      // put your setup code here, to run once:
    void loop() {
      // put your main code here, to run repeatedly:

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts