Success with messageport and CS4122 chips

Support for Arduino in combination with Air Manager and Air Player

Moderators: russ, Ralph

Post Reply
Message
Author
brianbarr
Posts: 25
Joined: Wed Apr 01, 2020 4:44 pm

Success with messageport and CS4122 chips

#1 Post by brianbarr »

So after some trial and error I was able to get my oddball vintage Frasca aircore instruments working with CS4122 driver chips, an Adruino UNO and messageport.

They actually work pretty well and are quite accurate.

The CS4122 needs a max of about 170ma of power at ~7V in to drive an aircore gauge in the 45 degree quadrants (~80ma for 0,90,180,270) - so these gauges are somewhat power hungry.

My next trick is to get the altimeters working.They have a 10 turn 10k pot geared to the internals and a 6v mini planetary gear motor to move the needles.

I going to use a polou jrk G2 21v3 to via i2c and see if it can be made to work.

Code: Select all

#include <si_message_port.hpp>
#include <SPI.h>
#define ChipSelectPinA 8
#define ChipSelectPinB 9

SiMessagePort* messagePort;

int t_delay = 50;
unsigned int gaugePosA = 0;
unsigned int gaugePosB = 0;
unsigned long millis_now = 0;



static void new_message_callback(uint16_t message_id, struct SiMessagePortPayload* payload) {

if (payload == NULL) {
messagePort->DebugMessage(SI_MESSAGE_PORT_LOG_LEVEL_INFO, (String)"Received without payload");
}
else {
switch(payload->type) {
case SI_MESSAGE_PORT_DATA_TYPE_BYTE:
messagePort->DebugMessage(SI_MESSAGE_PORT_LOG_LEVEL_INFO, (String)"Received " + payload->len + " bytes: " + payload->data_byte[0]);
break;
case SI_MESSAGE_PORT_DATA_TYPE_STRING:
messagePort->DebugMessage(SI_MESSAGE_PORT_LOG_LEVEL_INFO, (String)"Received string: " + payload->data_string);
break;
case SI_MESSAGE_PORT_DATA_TYPE_INTEGER:
// messagePort->DebugMessage(SI_MESSAGE_PORT_LOG_LEVEL_INFO, (String)"Received " + payload->len + " ints: " + payload->data_int[0]);
if (message_id == 41) {
gaugePosA = payload->data_int[0];
}
if (message_id == 42) {
gaugePosB = payload->data_int[0];
}
if (message_id == 81) {
gaugePosA = payload->data_int[0];
messagePort->DebugMessage(SI_MESSAGE_PORT_LOG_LEVEL_INFO, (String)"Received " + payload->len + " ints: " + payload->data_int[0]);
}
if (message_id == 82) {
gaugePosB = payload->data_int[0];
messagePort->DebugMessage(SI_MESSAGE_PORT_LOG_LEVEL_INFO, (String)"Received " + payload->len + " ints: " + payload->data_int[0]);
}
break;
case SI_MESSAGE_PORT_DATA_TYPE_FLOAT:
messagePort->DebugMessage(SI_MESSAGE_PORT_LOG_LEVEL_INFO, (String)"Received " + payload->len + " floats: " + payload->data_float[0]);
break;
}
}
}

// send a 12 bit message to one of two CS4122 chips connected via SPI. Target range is 0-1023.

void send_aircore(unsigned int channel,unsigned int target) {
unsigned int target1;
unsigned int oldval;
byte byte0;
byte byte1;

target1 = target;
if (target1 > 1023) { target1 = 0; }
byte1 = (target1 >> 8);
byte0 = (target1 & 0xFF); //0xFF = B11111111

if (channel == 0) {
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
digitalWrite (ChipSelectPinA, HIGH);
SPI.transfer(byte1);
oldval = SPI.transfer(byte0);
digitalWrite (ChipSelectPinA, LOW);
SPI.endTransaction();
} else {
SPI.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0));
digitalWrite (ChipSelectPinB, HIGH);
SPI.transfer(byte1);
oldval = SPI.transfer(byte0);
digitalWrite (ChipSelectPinB, LOW);
SPI.endTransaction();
}

}

// make the needles move around on power up

void aircore_init() {
send_aircore(0,0);
send_aircore(1,0);
delay(1000);
send_aircore(0,255);
send_aircore(1,255);
delay(1000);
send_aircore(0,511);
send_aircore(1,511);
delay(1000);
send_aircore(0,767);
send_aircore(1,767);
delay(1000);
send_aircore(0,0);
send_aircore(1,0);
delay(1000);

for (unsigned int i = 0; i<= 100; i++) {
send_aircore (0,i);
send_aircore (1,i);
delay(15);
}

for (unsigned int i = 100; i >= 0; i--) {
send_aircore (0,i);
send_aircore (1,i);
delay(15);
}
}

void setup() {
// Init library on channel G and Arduino type UNO
messagePort = new SiMessagePort(SI_MESSAGE_PORT_DEVICE_ARDUINO_UNO, SI_MESSAGE_PORT_CHANNEL_G, new_message_callback);
pinMode (ChipSelectPinA, OUTPUT);
pinMode (ChipSelectPinB, OUTPUT);
SPI.begin();
aircore_init();
}

void loop() {

messagePort->Tick();


if(millis() >= millis_now + t_delay){
millis_now += t_delay;

send_aircore(0,gaugePosA);
send_aircore(1,gaugePosB);
}
// You can send your own messages to Air Manager or Air Player
//messagePort->SendMessage(123);
//messagePort->SendMessage(123, "hello");
//messagePort->SendMessage(123, (int32_t)1000);
//messagePort->SendMessage(123, 2.5f);
//messagePort->SendMessage(123, (uint8_t) 0xAA);


}

User avatar
Ralph
Posts: 7878
Joined: Tue Oct 27, 2015 7:02 pm
Location: De Steeg
Contact:

Re: Success with messageport and CS4122 chips

#2 Post by Ralph »

So much investigation that goes into this :) But once you're done you can become an advisory ;) Or buy more and sell them?

User avatar
jph
Posts: 2846
Joined: Fri Apr 10, 2020 12:50 pm
Location: Somewhere over the rainbow..

Re: Success with messageport and CS4122 chips

#3 Post by jph »

brianbarr wrote: Wed Oct 07, 2020 7:53 pm So after some trial and error I was able to get my oddball vintage Frasca aircore instruments working with CS4122 driver chips, an Adruino UNO and messageport.

They actually work pretty well and are quite accurate.

The CS4122 needs a max of about 170ma of power at ~7V in to drive an aircore gauge in the 45 degree quadrants (~80ma for 0,90,180,270) - so these gauges are somewhat power hungry.

My next trick is to get the altimeters working.They have a 10 turn 10k pot geared to the internals and a 6v mini planetary gear motor to move the needles.

I going to use a polou jrk G2 21v3 to via i2c and see if it can be made to work.
Hi Brian, good to hear :) coming along well.
On the altimeter, It might also be worth considering a far cheaper solution using an L298N H bridge DC driver board (less than 2 dollars complete) (aliexpress)
ignore the 'stepper' bit in the item title - see the later article in the post here - it is standard h bridge dc motor driver - https://www.aliexpress.com/item/4001216 ... hweb201603_

You basically have 2 pins to control direction and state, and a pwm pin for speed.
Feed the analog output from the feedback 10k pot to a a 12 bit adc input on an Arduino 'Due' (or preferably a 16bit external adc to ANY arduino (really simple and cheap). you set desired position of needle by selecting the adc voltage reading required and move the motor in the direction and speed required until that level is reached (a normal servo type operation)
The units are so cheap, and even have 2 independent channels so you can drive 2 instruments from one board. The L298 has also been around a long time and is bullet proof.
here is a fairly good description -
https://lastminuteengineers.com/l298n-d ... -tutorial/
All you need to do is add the adc input from the instrument analogue output to create a pseudo servo (which is what the original design basically is)
Its another option worth considering.

The pololu is a nice unit but cannot (as far as I can see ?) offer speed AND position control, whereas the 298 board can offer you both as you have full control over it. if you have position sensing by analog feedback with the pololu then with a fixed speed the instrument would tend to jerk between movements, or lag depending on the fixed speed set.
I note this from the description of the pololu "With integrated support for analog voltage or tachometer (frequency) feedback, the second-generation G2 family of Jrk motor controllers makes it easy to add closed-loop control of speed or position (but not both!) of a single brushed DC motor to a variety of projects"
I must confess I haven't delved into the datasheets and destructions in any depth though. It does appear to have some programmable PID though.
It is easy to control speed with the h bridge pwm and is useful as you can tell the distance needed to move from the desired adc voltage and the actual. you can ramp up the speed and then gradually slow down as you approach the target etc. Just thinking out loud...
Joe.
Last edited by jph on Mon Oct 12, 2020 10:50 am, edited 1 time in total.
Joe. CISSP, MSc.

User avatar
jph
Posts: 2846
Joined: Fri Apr 10, 2020 12:50 pm
Location: Somewhere over the rainbow..

Re: Success with messageport and CS4122 chips

#4 Post by jph »

Hi again Brian - ok -
I have looked at the pololu datasheet and it is the same res on the adc as the DUE. (12bits)
Although that may be ok - I would err on the side of programmability and adaptation.
Using even a most basic arduino - I would suggest adding the ubiquitous ADS 1115 16bit adc (I2C Bus) for the feedback - you will also need a good quality external Vref - but you would need that with the pololu anyway - and they are cheap. The ADS1115 16bit I2C unit - link here (cheap as chips and damn good)
https://www.aliexpress.com/item/4000529 ... web201603_
is a really small simple and 4 channel 16 bit stabilised ADC. (less than 2 dollars) - can be used with ANY arduino.
You will get a true 15 bit ADC in single ended mode due to 2's compliment output - ie - a 'sign' bit for negative and positive values using one of the available 16 bits - in single ended mode (standard simple adc input) you will only ever be in the positive or negative range hence the 15 bit limit. 16 bit is only available in differential mode where 2 adc values are compared and the difference is registered - along with the sign bit. - but, basically, in single ended mode giving you 4 independent channels, the resolution is 15 bits or 32k 'steps' . no ADC is ever 100% accurate so the extra res makes up for that along with a simple median average type filter (I have some code if you need it) - you probably don't need it though in this case. (it is simply a multi sample adc reading code that you then take the median of the average. Again, that is icing on the cake that is almost certainly not needed here If you want a sample MA filter for arduino let me know.

These units are so cheap and great quality as to make them worth adding to ANY adc input really. - and all your favourite I2C lol :)

The resolution in altitude will be dictated by the ceiling height of the aircraft (or max altimeter reading) (needed for calibration of whatever you use) in relation to the adc resolution allowing for the adc error and Vref stability along with the mechanical stability of the 10K multiturn feedback potentiometer. Basically the higher the adc quality and resolution and the stability of the EXTERNAL adc reference voltage - electrically and mechanically) the more accurate the altimeter reading will be. Also, within reason, the higher your chosen altitude ceiling the lower the resolution, although, it is fairly minimal. having resolution to spare allows for greater altitude ceilings if you want to use the sim for another type of aircraft other than a 172 which has a theoretical MAX ceiling of FL 150.

Very cost effective solution.

Again, just thinking out loud.
Joe
Joe. CISSP, MSc.

Post Reply