Hi there,
I wanted to show you my little project I´m working on for a very long time now.
I am building my own engine dyno utilizing a water brake which I manufactured myself.
It is one of those project where you wanted a DIY solution because you thaught it would be too expensive to buy one, but ends up costing you years of your life
In short, a water brake is a very very inefficient water pump. In fact it is so bad of a pump, that all the power of an engine is transformed into heat.
The absorbed power is proportional to the amount of water inside the water brake.
The more water, the more power is absorbed.
I don´t want to go too much in the "mechanical" details, because I want to focus on my problems with electronics and programming. If someone has interest on the mechanical stuff, I´m happy to talk about it. At last I´m just a mechanical engineer and not very good at prorgamming.
You can´t measure power directly, that´s where the arduino stuff comes in.
To get power, we need torque and RPM.
RPM is measured by a light barrier and a disc with 18 holes on the shaft of the waterbrake.7
Tourque is measured by a load cell (utilizing a HX711 module) mounted on a torque arm.
To regulate the amount of water inside the housing I built two stepper valves out of stepper motors, planetary gearboxes and normal sliding valves. I mounted a potentiometer to the back of the stepper motor via a worm gear to get absolute positioning.
These two stepper valves get their juice from two Pololu T500 TIC stepper drivers.
All this stuff to this point is sitting in a small electrical cabinet directly on the water brake and is controlled by an Arduino Nano.
Later I want to "remote control" all the stuff to get a safe distance to a running engine at full power
That´s why I plan on building a small box or case with all the buttons, switches, displays and so on where I can control everything and see all my values.
Right now this box is just a second Arduino Nano
I hope this gives you a small idea what my setup/plan looks like.
Right now I need some help with the I2C communication between the stepper drivers and the two Arduinos.
The Arduino on the water brake is my master right now and is reading a potentiometer which transaltes to a desired valve position (to two valve position to be exact) and sends them over to the T500s.
This is working fine right now.
My problem is the communication between the two Arduinos.
The Master sends values over to the slave, which prints them out to the serial port.
I have a very long cable between those two Nanos (10m), that´s why I reduced the clock speed drastically. I wanted to be on the safe side, because I think that I will have a lot more noice from running electrical motors, a running combustion engine and so on, so I added two Adafruit LTC4311 active terminators. One to each end of the chain.
Now comes the fun part:
If I unplug both of the LTC4311s and reboot the system, everything is working fine.
If I plug them in and reboot, the I2C bus just stops working.
I double checked all the connections a hundred times, but can´t find an error.
The best part is, if I unplug the LTC4311 while the system is running (well... not running) the I2C bus immediatly jumps to life and is working again.
Has someone ever had similar problems with these LTC4311s?
A second (future) problem is, that I will need a two way communication (I´m not sure if this is the right name) between the two Nanos.
Both need to read values from potentiometers or buttons and send them to each other.
I utilized the "I2C_anything"-library because I need to send int, float and so on, not just bytes.
But I can´t find an example where the master is reading AND writing on the I2C-Bus.
Can anyone help me out here?
I will post my two codes down here. The master is the Nano on the water brake and the slave is my little "box".
MASTER:
//DYNO MASTER
#include <Wire.h>
#include <HX711.h>
#include <I2C_Anything.h>
#include <Tic.h>
#define DZM_InputPin 2
#define LOADCELL_DOUT_PIN 10
#define LOADCELL_SCK_PIN 9
#define posBrakeValvePin A0
#define posBypassValvePin A1
#define targetValvePin A2
//I2C communication
const byte SLAVE_ADDRESS = 8;
//variables for RPM measurement
volatile unsigned long RPM_T2 = 0;
volatile unsigned long RPM_Count = 0;
unsigned int RPM = 0;
unsigned long RPM_T1 = 0;
int teeth = 18;
// variables for scale
int force;
//variables for potentiometers
int posBypassValve = 0;
int posBrakeValve = 0;
int targetValve = 0;
//variables for valves
int32_t TicPosBrake = 0;
int32_t TicPosBypass = 0;
int32_t TicBrakeCurrentPos = 0;
int32_t TicBypassCurrentPos = 0;
int32_t TargetTicPosBrake = 0;
int32_t TargetTicPosBypass = 0;
//variables for calculations
//int targetRPM = 0;
//int RPMmin = 0;
//int RPMmax = 9000;
HX711 scale;
TicI2C TicBrake(14);
TicI2C TicBypass(15);
void setup(){
Wire.begin();
//Wire.setClock(1000);
TWBR = 255;
TWSR = 3;
Serial.begin(9600);
//defining pins
pinMode(DZM_InputPin, INPUT_PULLUP);
pinMode(posBrakeValvePin, INPUT);
pinMode(posBypassValvePin, INPUT);
pinMode(targetValvePin, INPUT);
//setup interrupts for rpm measurement
attachInterrupt(0, RPM_Meter, FALLING); // Interrupt0 wird bei fallender Flanke auf Pin2
//initializing of scale
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
scale.set_scale(2280.f);
scale.tare();
//Setup for Tics
TicBrake.exitSafeStart();
TicBypass.exitSafeStart();
posBrakeValve = analogRead(posBrakeValvePin);
posBypassValve = analogRead(posBypassValvePin);
TicPosBrake = map(posBrakeValve, 65, 820, 0, 236805);
TicPosBypass = map(posBypassValve, 65, 820, 0, 236805);
TicBrake.haltAndSetPosition(TicPosBrake);
TicBypass.haltAndSetPosition(TicPosBypass);
}
void resetCommandTimeout()
{
TicBrake.resetCommandTimeout();
TicBypass.resetCommandTimeout();
}
void loop(){
//RPM measurement
if (RPM_T2 > RPM_T1) {
RPM = (unsigned)(long)(60000 * RPM_Count / (RPM_T2 - RPM_T1));
RPM = RPM/teeth;
RPM_T1 = RPM_T2;
RPM_Count = 0;
}
else {
RPM = 0;
}
//Getting force value
force = scale.get_units(5),1;
//Getting potentiometer values
posBrakeValve = analogRead(posBrakeValvePin);
posBypassValve = analogRead(posBypassValvePin);
targetValve = analogRead(targetValvePin);
//Setting Valve Positions
if(targetValve <= 512){
TargetTicPosBrake = map(targetValve, 0, 512, 0, 236805);
TargetTicPosBypass = 236805;
}
if(targetValve >= 512){
TargetTicPosBrake = 236805;
TargetTicPosBypass = map(targetValve, 512, 1024, 236805, 0);
}
TicBrake.setTargetPosition(TargetTicPosBrake);
TicBypass.setTargetPosition(TargetTicPosBypass);
delay(10);
//Calculating values
// targetRPM = map(targetRPMRaw, 2, 1021, RPMmin, RPMmax);
// //Getting Tic positions
// TicBrake.exitSafeStart();
// TicBypass.exitSafeStart();
//
// posBrakeValve = analogRead(posBrakeValvePin);
// posBypassValve = analogRead(posBypassValvePin);
//
// TicPosBrake = map(posBrakeValve, 65, 820, 0, 236805);
// TicPosBypass = map(posBypassValve, 65, 820, 0, 236805);
//
// TicBrake.haltAndSetPosition(TicPosBrake);
// TicBypass.haltAndSetPosition(TicPosBypass);
//
// TicBrakeCurrentPos = TicBrake.getCurrentPosition();
// TicBypassCurrentPos = TicBypass.getCurrentPosition();
//
// resetCommandTimeout();
//Printing values on serial monitor
Serial.print("RPM: ");
Serial.println(RPM);
Serial.print("Force: ");
Serial.println(force);
Serial.print("Brake Valve Pos.: ");
Serial.println(posBrakeValve);
Serial.print("Bypass Valve Pos.: ");
Serial.println(posBypassValve);
Serial.print("Target Valve: ");
Serial.println(targetValve);
// Serial.print("Target RPM: ");
// Serial.println(targetRPM);
Serial.print("Current Pos Brake: ");
Serial.println(TicBrakeCurrentPos);
Serial.print("Current Pos Bypass: ");
Serial.println(TicBypassCurrentPos);
Serial.print("Calculated Pos Brake: ");
Serial.println(TicPosBrake);
Serial.print("Calculated Pos Bypass: ");
Serial.println(TicPosBypass);
Serial.print("Target Pos Brake: ");
Serial.println(TargetTicPosBrake);
Serial.print("Target Pos Bypass: ");
Serial.println(TargetTicPosBypass);
Serial.println();
delay(10);
Wire.beginTransmission (SLAVE_ADDRESS);
//I2C_writeAnything (targetRPM);
I2C_writeAnything (RPM);
I2C_writeAnything (force);
I2C_writeAnything (posBrakeValve);
I2C_writeAnything (posBypassValve);
Wire.endTransmission ();
delay (10);
TicBrake.exitSafeStart();
TicBypass.exitSafeStart();
}
//Function for RPM measurement
void RPM_Meter () {
RPM_Count++;
RPM_T2 = millis();
}
And the SLAVE:
//DYNO SLAVE
#include <Wire.h>
#include <I2C_Anything.h>
const byte MY_ADDRESS = 8;
void setup()
{
Wire.begin (MY_ADDRESS);
Serial.begin (9600);
Wire.onReceive (receiveEvent);
}
volatile boolean haveData = false;
//volatile int targetRPM = 0;
volatile unsigned int RPM = 0;
volatile int force = 0;
volatile int posBrakeValve = 0;
volatile int posBypassValve = 0;
void loop()
{
if (haveData)
{
//Serial.print("Target RPM: ");
//Serial.println(targetRPM);
Serial.print("RPM: ");
Serial.println(RPM);
Serial.print("Force: ");
Serial.println(force);
Serial.print("Brake Valve Pos.: ");
Serial.println(posBrakeValve);
Serial.print("Bypass Valve Pos.: ");
Serial.println(posBypassValve);
Serial.println();
haveData = false;
}
}
// called by interrupt service routine when incoming data arrives
void receiveEvent (int howMany)
{
if (howMany >= (sizeof RPM) + (sizeof force) + (sizeof posBrakeValve) + (sizeof posBypassValve))
{
//I2C_readAnything (targetRPM);
I2C_readAnything (RPM);
I2C_readAnything (force);
I2C_readAnything (posBrakeValve);
I2C_readAnything (posBypassValve);
haveData = true;
}
}
Please be kind, as I said I´m not a programming guy. To be honest I´m miles away from it
Regards,
Josh