NeoGPS, speed to pwm output Teensy 3.2.

Status
Not open for further replies.

Vauxi

Member
Hello.
I've been strugling to make topic thing to happen. I have GPS speed at serial monitor. I don't understand how to use currentFix feature. Compile stops to error: invalid use of non-static member function outputValue = map(currentFix.speed_kph, 1, 3, 50, 250);

If I did understand "instructions" correctly, I should be able to use speed value anywhere in the code when currentFix is used?

Code:
#include <NMEAGPS.h>
#include <GPSport.h>

NMEAGPS  gps; // This parses the GPS characters
gps_fix  currentFix; // This holds on to the latest values
int viisari = 6;
int outputValue = 0;


void setup()
{
  Serial.begin(115200);
  Serial.print( F("NMEAsimple.INO: started\n") );

  gpsPort.begin(9600);
  pinMode(viisari, OUTPUT);
}

//--------------------------

void loop()
{
  while (gps.available( gpsPort )) {
    currentFix = gps.read();

    Serial.println( F("Speed: ") );
    if (currentFix.valid.speed) 
      Serial.println( currentFix.speed_kph(), 1 );
    
    outputValue = map(currentFix.speed_kph, 1, 3, 50, 250);
    analogWrite(viisari, outputValue);
    Serial.println(outputValue);
  }
}

I can't swing gps antenna enough fast so that's why mapping values are so low :)
 
for the compile error, i would use parentheses, and also map from 0 to 3:

outputValue = map(currentFix.speed_kph(), 0, 3, 50, 250);

Code:
Speed: 0.241
66
Speed: 0.167
61
Speed: 0.204
63

for analogWrite() you don't need pinMode(viisari, OUTPUT);


Even with your GPS stationary you should see the speed_kph() values changing. To see even more jitter print altitude() :eek:
 
Last edited:
Those () did the trick ! :cool: Thank you. Yeah, but outside the house is now -5´c, so I hesitate go out to swing antenna :D Yes I do see jumping speed from indoors. That raised a question. How to limit pwm dutycycle rise? This may not be issue ever. But with those testing purpose only values I saw control values go over the roof by like 400. :D I'm learning to code and for my coding skill level I like to make some basic settings that I remember. Thats why there is pinMode.
 
Those () did the trick ! :cool: Thank you. Yeah, but outside the house is now -5´c, so I hesitate go out to swing antenna :D Yes I do see jumping speed from indoors. That raised a question. How to limit pwm dutycycle rise? This may not be issue ever. But with those testing purpose only values I saw control values go over the roof by like 400. :D

Limit the slew rate, either with a low pass or with a non linear filter.
 
Hello
Didn't want to start another thread coz it is still the same unit.
I'm implementing tachometer. Tacho accepts 12 volt square wave signal pulses as signal. I fiqured that analog.write will not compute this time. Signal frequency has to be alteterd not the witdth. Is it possible? digital.Write ?
 
I fiqured that analog.write will not compute this time. Signal frequency has to be alteterd not the witdth.

You can analogWriteFrequency() to chance the PWM frequency. Details here:

https://www.pjrc.com/teensy/td_pulse.html

However, Theremingenieur's suggestion to use tone() might work better if you are making regular changes to the frequency. With analogWriteFrequency(), the PWM output is stopped temporarily, then restarted at the new frequency. If you make many rapid changes to the frequency, it's possible those small disruptions to the output may give you a terrible signal.

With tone(), changes in frequency while the output is running are done very gracefully. When you set a new frequency, the change is actually delayed until the end of the current cycle. Then the next cycle begins seamlessly, but at the new frequency. The output never stops & restarts, as you would get with PWM using analogWriteFrequency. However, the change to the new frequency is delayed until the next cycle, so the choice is really between graceful & seamless but delayed chances, or immediate but possibly disruptive changes. For simulating a tachometer, you probably want the seamless changes.


Might also be worth mentioning, the graceful transition from 1 frequency to another with tone() is a Teensyduino extension. You will not get this graceful change if using tone() on regular Arduino boards.
 
Ok.
I built simple npn transistor pull up confiquration. Basic digitalwrite sketch works nice but tone not at all. Have to scope it. Rpm input is coming in at 50hz so I'll quess that small delay here and there isn't gonna be promplematic.
Pulsed output is what I'm after. Fixed (let's say like 3ms) DutyCyle but frequency is what has to follow decoded rpm.
 
Got it working !
I've already used analogWriteFrequency command and lowered value to pretty slow. So tone was the way to go. It might work okay. I'll have to test it on a real tachometer. To achieve somewhat controllable tone length I have to use delay command. I kinda don't like it. With low delay value(20 or less) I don't get rpm less than 1500 on a tach output. If I rise value up to the 50 or so, I get tacho to under 500rpm but at the same time response to the input signal is pretty slow. And I don't know how delay affects to the rest of the code. Pjrc example tells that I can set the tone duration by number. That doesn't work at all.
 
Oh no. Speedometer gauge is worn out. So I have to ditch the gauge and turn the needle by stepper motor. Tested the stepper motor controller with simplest test code. Hooked up two led's to the controller. Next I implemented remembering code from pjrc tutorials and it works (atleast when linked it to the CAN bus coolant temp sensor pot). Led s blinks in both ways depending wich way pot is turned.

Problem is when I insert if and else commands wich are necessary for the coolant temp gauge to work. After this stage stepper motor control loses other coil control completely. What is going on ?
Code:
#include <FlexCAN.h>
#include <Stepper.h>
#define STEPS 600
static CAN_message_t txmsg, rxmsg;
Stepper stepper(STEPS, 6, 20, 18, 19);
long previous = STEPS / 2;
#include <NMEAGPS.h>
#include <GPSport.h>

NMEAGPS  gps; // This parses the GPS characters
gps_fix  currentFix; // This holds on to the latest values

//int viisari = 5;
int outputValue = 0;
int val;


//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() {
 analogWriteResolution(12); //Full resolution of Teensy 3.2
  analogWriteFrequency(5, 250);
  stepper.setSpeed(60);
Can0.begin(500000);

    Serial.begin(115200); //***Uncomment this section to output CAN message IDs to Serial Monitor***
    gpsPort.begin(9600);

}


void loop(void) {



  //Look for CAN broadcasts
  if ( Can0.read(rxmsg) ) {
    switch (rxmsg.id) { // ID's 1520+ are Megasquirt CAN broadcast frames. EAch frame represents a data group http://www.msextra.com/doc/pdf/Megasquirt_CAN_Broadcast.pdf
      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);
        break;
      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]));
        break;
      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]));

        break;
      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]));
        break;
      case 1524: // Group 4
        break;
      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]));
        break;
      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
        break;
      case 1537: // Group 17

        break;
      case 1548: // Group 28
        idle_tar = (float)(word(rxmsg.buf[0], rxmsg.buf[1]));
        break;
      case 1551: // Group 31
        break;
      case 1574: // Group 54
        indicator[4] = rxmsg.buf[2]; // cel
        break;

    }

    
{
  while (gps.available( gpsPort )) {
    currentFix = gps.read();

   // Serial.println( F("Speed: ") );
    if (currentFix.valid.speed) 
      Serial.println( currentFix.speed_kph(), 1 );
       long val = (long)currentFix.speed_kph() * STEPS / 160;
    stepper.step(val - previous);
  previous = val;
  Serial.println(val);
  
  


 outputValue = map(CLT, 326, 2300, 2300, 1780);
 // if (outputValue > 2000)
  //{
  // analogWrite(5, 4096);
 // }
 // else
  //{
    analogWrite(5, outputValue);
   
    
}
  //Serial.println(CLT);
  //Serial.println(viisari);
 
  
  }

  

    
  
  }  
 }

Code is messy coz trying to fiqure out what is wrong. Coolant temp gauge map command is last one.
 
are you using 12bit analog writing hmm? ;)

analogWriteResolution(12);

oh wait you are

that while loop could be a problem
 
Nope. Standard analogRead resolution wasn't the fix. :( I did some work with the declaretions and took stepper motor control out of gps loop. Tried to overclock the cpu just for kicks. :) Is there another way to scale the decoded clt signal from CAN to the pwm output ? It has to have options to scale as I've done it. I slowed the signal rate from megasquirt to 10hz from 50hz. It didn't make a difference. Baud speed was the same.
 
FAIL. Massive FAIL ! :mad: All the time after switching to the stepper motor I've been using wrong pin in the code. After fiquring that out with multimeter teensy jammed and gps didnt want to work correctly. That solved out with power off. Sun is shining again to this bedroom. :D
 
Hello
It crossed my mind that how (if needed) I tell the stepper code what is my top speed ? So it can scale itself correctly. Otherwise it would set scaling low point as zero but who knows where is the top speed going to be set. Or have I set it allready with "(long)currentFix.speed_kph() * STEPS / 160;" with the /160 ?
 
Status
Not open for further replies.
Back
Top