Hi!
I am currently working on project aiming at connecting fuel meters, etc to the NMEA2000-network in my boat.
A part of the work is to create a simulator for the devices on the boat. My first task is to emulate the flow meters.
They transmit pulses of which is proportional to the volume of fuel passed. The boat is equipped with two diesel engines,
so four meters are needed.
The current setup is two Teensy chips (4.0 and 4.1), of which the 4.0 is acting as simulator.
I've programmed this as four threads acting on four pins, one for each flow meter. My intention was to be able to
pulse rates between 20 - 100 Hz.However, some problem appears...
When the following rates are used, it works nicely:
Pin #2 50 Hz
Pin #3 25 Hz
Pin #5 50 Hz
Pin #6 25 Hz
The scope reports: 45 Hz and 22 Hz, which is not dead on, but reasonable for my purpose. (See attachment. The frequency is shown in the bottom left hand corner.)
However, when I run it with the following:
Pin #2 80 Hz
Pin #3 25 Hz
Pin #5 50 Hz
Pin #6 25 Hz
I get the same 45 Hz output and I am surprised. I would have anticipated something around 90 Hz here.
Am I doing something wrong, if so please enlighten me.
Rgds,
Göran
I am currently working on project aiming at connecting fuel meters, etc to the NMEA2000-network in my boat.
A part of the work is to create a simulator for the devices on the boat. My first task is to emulate the flow meters.
They transmit pulses of which is proportional to the volume of fuel passed. The boat is equipped with two diesel engines,
so four meters are needed.
The current setup is two Teensy chips (4.0 and 4.1), of which the 4.0 is acting as simulator.
I've programmed this as four threads acting on four pins, one for each flow meter. My intention was to be able to
pulse rates between 20 - 100 Hz.However, some problem appears...
When the following rates are used, it works nicely:
Pin #2 50 Hz
Pin #3 25 Hz
Pin #5 50 Hz
Pin #6 25 Hz
The scope reports: 45 Hz and 22 Hz, which is not dead on, but reasonable for my purpose. (See attachment. The frequency is shown in the bottom left hand corner.)
However, when I run it with the following:
Pin #2 80 Hz
Pin #3 25 Hz
Pin #5 50 Hz
Pin #6 25 Hz
I get the same 45 Hz output and I am surprised. I would have anticipated something around 90 Hz here.
Am I doing something wrong, if so please enlighten me.
Rgds,
Göran
Code:
#include "JeevesIISimulatorNMEA2000.h"
/*******************************************************************************
Function name:
Description:
Parameters:
Return:
Written by: Göran Andersson
Date: 2021-MM-DD
Version history
First issue ver 1.0
*******************************************************************************/
/*
TODO
====
+ Separate the start of pulse generating threds, so maybe better performance can be acheived?
*/
bool TraceFlag = true,
TraceFlag2 = false,
SyncTimePC = true,
TestOnly = true,
FuncTest = false;
// Containing all data we need for the threads.
ThreadsDef_t FlowmeterThread[NbrOfThreads];
void setup()
{
if(TraceFlag
||
TraceFlag2)
{
Serial.begin(115200);
while(!Serial)
delay(10);
delay(2000);
Serial.println("Buuu");
Serial.print("FlowmeterHz: ");
Serial.println(FlowmeterHz);
}
Initialise();
}
void loop()
{
}
/*******************************************************************************
Function name: BBPrimaryFlowMeter
Description:
Parameters:
Return: None
Written by: Göran Andersson
Date: 2021-12-20
Version history
First issue ver 1.0
*******************************************************************************/
void BBPrimaryFlowMeter(void)
{
int State = HIGH;
threads.delay(ThreadStartDelay + 13);
while(Forever)
{
digitalWriteFast(PrimaryBBFlowmeterPin, State);
State = (~State) & StateMask;
if(DelayTimeBBPrimary < 30)
threads.delay_us((1000*DelayTimeBBPrimary) >> 1);
else
threads.delay(DelayTimeBBPrimary >> 1);
}
}
/*******************************************************************************
Function name: BBReturnFlowMeter
Description:
Parameters:
Return: None
Written by: Göran Andersson
Date: 2021-12-20
Version history
First issue ver 1.0
*******************************************************************************/
void BBReturnFlowMeter(void)
{
int State = HIGH;
threads.delay(ThreadStartDelay + 7);
while(Forever)
{
digitalWriteFast(ReturnBBFlowmeterPin, State);
State = (~State) & StateMask;
if(DelayTimeBBReturn < 30)
threads.delay_us((1000*DelayTimeBBReturn) >> 1);
else
threads.delay(DelayTimeBBReturn >> 1);
}
}
/*******************************************************************************
Function name: SBPrimaryFlowMeter
Description:
Parameters:
Return: None
Written by: Göran Andersson
Date: 2021-12-20
Version history
First issue ver 1.0
*******************************************************************************/
void SBPrimaryFlowMeter(void)
{
int State = HIGH;
threads.delay(ThreadStartDelay + 5);
while(Forever)
{
digitalWriteFast(PrimarySBFlowmeterPin, State);
State = (~State) & StateMask;
if(DelayTimeSBPrimary < 30)
threads.delay_us((1000*DelayTimeSBPrimary) >> 1);
else
threads.delay(DelayTimeSBPrimary >> 1);
}
}
/*******************************************************************************
Function name: SBReturnFlowMeter
Description:
Parameters:
Return: None
Written by: Göran Andersson
Date: 2021-12-20
Version history
First issue ver 1.0
*******************************************************************************/
void SBReturnFlowMeter(void)
{
int State = HIGH;
threads.delay(ThreadStartDelay + 3);
while(Forever)
{
digitalWriteFast(ReturnSBFlowmeterPin, State);
State = (~State) & StateMask;
if(DelayTimeSBReturn < 30)
threads.delay_us((1000*DelayTimeSBReturn) >> 1);
else
threads.delay(DelayTimeSBReturn >> 1);
}
}
/*******************************************************************************
Function name: Initialise
Description:
Parameters:
Return: None
Written by: Göran Andersson
Date: 2021-12-20
Version history
First issue ver 1.0
*******************************************************************************/
void Initialise(void)
{
ThreadIdx_t ThreadIdx;
FlowmeterThread[BBPrimaryThread] = {
BBPrimaryFlowMeter,
"BBPrimaryFlowMeter",
ThreadFailed
};
FlowmeterThread[BBReturnThread] = {
BBReturnFlowMeter,
"BBReturnFlowMeter",
ThreadFailed
};
FlowmeterThread[SBPrimaryThread] = {
SBPrimaryFlowMeter,
"SBPrimaryFlowMeter",
ThreadFailed
};
FlowmeterThread[SBReturnThread] = {
SBReturnFlowMeter,
"SBReturnFlowMeter",
ThreadFailed
};
pinMode(PrimaryBBFlowmeterPin, OUTPUT);
pinMode(PrimarySBFlowmeterPin, OUTPUT);
pinMode(ReturnSBFlowmeterPin, OUTPUT);
pinMode(ReturnBBFlowmeterPin, OUTPUT);
StartFlowmeterThreads();
}
/*******************************************************************************
Function name: AddFlowmeterThread
Description: The function starts a thread that is defined in the control structure 'FlowmeterThread'.
The outcome is sent the 'Serial' interface.
Parameters: ThreadIdx An index of the 'FlowmeterThread' array
Return: None
Written by: Göran Andersson
Date: 2021-12-20
Version history
First issue ver 1.0
*******************************************************************************/
void AddFlowmeterThread(ThreadIdx_t ThreadIdx)
{
int TmpThreadID = threads.addThread(FlowmeterThread[ThreadIdx].Tread_F);
if(TraceFlag)
{
Serial.println("####### Entry AddFlowmeterThread #######");
// Serial.println(TmpThreadID);
// Serial.println(JeevesIIThread[ThreadIdx].ThreadName);
}
if(TmpThreadID == ThreadFailed)
{
if(TraceFlag)
{
Serial.print("Failed creating thread: ");
Serial.print(FlowmeterThread[ThreadIdx].ThreadName);
Serial.println("! Harakiri...");
}
exit(1);
}
else
{
if(TraceFlag)
{
Serial.print("Created thread: ");
Serial.println(FlowmeterThread[ThreadIdx].ThreadName);
Serial.print(" Thread state: ");
Serial.println(threads.getState(TmpThreadID));
Serial.print(" Thread ID: ");
Serial.println(TmpThreadID);
}
}
FlowmeterThread[ThreadIdx].ThreadID = TmpThreadID;
if(TraceFlag)
Serial.println("####### Exit AddFlowmeterThread #######");
}
/*******************************************************************************
Function name: StartFlowmeterThreads
Description: The function starts all the threads
Parameters: None
Return: None
Written by: Göran Andersson
Date: 2021-12-20
Version history
First issue ver 1.0
*******************************************************************************/
void StartFlowmeterThreads(void)
{
ThreadIdx_t ThreadIdx = FirstThread;
while(ThreadIdx < NbrOfThreads)
{
AddFlowmeterThread(ThreadIdx);
ThreadIdx = ThreadIdx_t (ThreadIdx + 1);
}
}
Code:
#include <strings.h>
//#include <stdint.h>
#include <TeensyThreads.h>
#ifndef _JEEVESII_SIMULATOR_NMEA2000_H
#define _JEEVESII_SIMULATOR_NMEA2000_H
#define MaxTicks 4294967295 // + 1 -> 0
#define PrimaryBBFlowmeterPin 2
#define ReturnBBFlowmeterPin 3
#define PrimarySBFlowmeterPin 5
#define ReturnSBFlowmeterPin 6
#define ThreadFailed -1
#define FlowmeterHz 50 // 83 OK, but not 84! // Hz
// Pulse period
#define DelayTimeBBPrimary 20 //10 // ms
#define DelayTimeBBReturn 40 // ms
#define DelayTimeSBPrimary 20 // ms
#define DelayTimeSBReturn 40 // ms
#define ThreadStartDelay 1000
#define StateMask 1
typedef enum
{
FirstThread, BBPrimaryThread = FirstThread, BBReturnThread, SBPrimaryThread, SBReturnThread, NbrOfThreads
}ThreadIdx_t;
typedef struct ThreadsDef
{
ThreadFunctionNone Tread_F;
char *ThreadName;
int ThreadID;
}ThreadsDef_t;
void BBPrimaryFlowMeter(void);
void BBReturnFlowMeter(void);
void SBPrimaryFlowMeter(void);
void SBReturnFlowMeter(void);
void AddFlowmeterThread(ThreadIdx_t ThreadIdx);
void StartFlowmeterThreads(void);
void Initialise(void);
static bool Forever = true;
// #include "JeevesIINMEA2000.h"
#endif