Hello everyone, first time posting here so sorry if I do anything wrong.
I'm developing a meter using the IC in question. But I'm not quite sure about my coding to do it with Arduino. The problem is, I'm not sure if I'm reading data correctly to be further treated.
//----------Bibliotecas------------------
#include <LiquidCrystal.h>
#include <EEPROM.h>
#include <SPI.h>
//-------------Variaveis---------------------
#define sdo 11 // Data out pin
#define sdi 12 // Data in pin
#define sclk 13 // SPI clock pin
#define cs 10 // Chip select pin
#define mclr 9 // MCLR of MCP3909
#define G0 7
#define G1 8
LiquidCrystal LCD(2, 3, 4, 5, 6, A0);
int ch1[15];
int ch0[15];
//------------------------------------------
void setup() {
pinMode(sdo, OUTPUT);
pinMode(sdi, INPUT);
pinMode(sclk, OUTPUT);
pinMode(mclr, OUTPUT);
pinMode(cs, OUTPUT);
digitalWrite (G0, HIGH);
digitalWrite (G1, LOW);
SPI.begin();
Serial.begin(115200);
digitalWrite(mclr, LOW); // Hold cleared MCP3909
digitalWrite(cs, HIGH); // Disable slave device
delayMicroseconds(10);
//MSB transmitted first
/*SPI.setBitOrder(MSBFIRST);
//Set SPI clock to 16MHz/8
SPI.setClockDivider(SPI_CLOCK_DIV4);
//Set SPI_MODE1
SPI.setDataMode(SPI_MODE1);*/
SPI.beginTransaction (SPISettings (8000000, MSBFIRST, SPI_MODE1));
delayMicroseconds(10);
digitalWrite(mclr, HIGH); //Disable mclr for MCP3909
digitalWrite(cs, LOW); //Enable chip select
//Load the Dual channel Post-HPF operation mode directive
SPI.transfer(0xAC);
digitalWrite(cs,HIGH); //Disable chip select
LCD.begin(16, 2);
LCD.setCursor(2,0);
LCD.print("FTX Meter");
delay (2000);
LCD.clear();
}
void loop() {
digitalWrite(cs,LOW);
ch1=SPI.transfer16(0x00);
ch0=SPI.transfer16(0x00);
digitalWrite(cs,HIGH);
LCD.setCursor(0,0);
LCD.print(ch1);
Serial.println(ch1);
delay (1000);
LCD.setCursor(0,1);
LCD.print(ch0);
Serial.println(ch0);
delay (1000);
}
In my code I use the SPI transfer for 16bits since the complete data is 32bits, but I'm not sure if I can do it the way I'm doing.
I've also attached the datasheet. Thanks in advance for any helps;
Datasheet Mcp3909.pdf (703 KB)
TitodeMiranda:
I'm developing a meter using the IC in question. But I'm not quite sure about my coding to do it with Arduino. The problem is, I'm not sure if I'm reading data correctly to be further treated.
.......
In my code I use the SPI transfer for 16bits since the complete data is 32bits, but I'm not sure if I can do it the way I'm doing.
when you compile and upload the code what happens? is the behaviour what you expect?
you have not explain what is the problem you are facing here...
The program compiles and uploads, but, the data I'm receiving is not what I was expecting. I'm going to verify the time of the setup recommended by the datasheet to see if its correct.
The fact is, I'm not used to the SPI interface, and the IC is not a simple one to begin with. My doubts are about the treatment I'm giving to the data I receive.
from the datasheet, it seem that, the MCP3909 uses the pulse "DR" to say to the microcontroller ... "Hey! I have new data available" and after this pulse the MCP3909 sends the data.
After you set CS LOW, the MCP3909 starts (I think) this sequence ...
DR --- DATA --- DR --- DATA ...
and does it continuously until CS is pulled HIGH again... (I'm not sure, but I think you must do a "dummy read" before the MCP3909 starts sending anything !)
The pulse "DR" should be used, as an interrupt, to the microcontroller so that it knows when read the data from the MCP3909. So the SDO pin from the MCP3909 should be connected to the MISO (SDI) pin of the microcontroller and also to an interrupt pin!
To me it looks like you will need to redo part of your code so that it can detect the "DR" pulse.
hope that helps....
I thought that the SPI library had that dummy read in it.
So, let me see if I understood. I have to connect the same output pin from the mcp into another pin to read its high to low variation (DR), and then read the data 16+16?
TitodeMiranda:
So, let me see if I understood. I have to connect the same output pin from the mcp into another pin to read its high to low variation (DR), and then read the data 16+16?
that's what the datasheet appears to be saying. As I mentioned previously to " read its high to low variation (DR)" you may want to make use of interrupts.
TitodeMiranda:
I thought that the SPI library had that dummy read in it.
nope.
I am using a MLX90393, in single read mode.
I request that the MLX90393 read the magnetometers, the code is then held up from further processing till the MLX90393 signals that is has completed a reading. At which time the MLX90393 generates an interrupt so that the result set can be read.
Interrupt code
void IRAM_ATTR triggerMLX90393read()
{
BaseType_t xHigherPriorityTaskWoken;
xEventGroupSetBitsFromISR(eg, evtfMLX90393_ReadSensorTriggered, &xHigherPriorityTaskWoken);
}
This code triggers a read then waits till the interrupt indicates that there is valid data to read:
while (1)
{
vTaskDelayUntil( &xLastWakeTime, xFrequency );
// request a single data read
intError = fWriteSPIdata8bits2( _hMLX90393, MLX90393_REG_SM | MLX90393_AXIS_ALL ); // single measurement all axis and temperature
// after a request for data from the MLX90393 the function goes into a wait mode here
//triggered from void IRAM_ATTR triggerMLX90393read(), when the unit has data available
xEventGroupWaitBits ( eg, evtfMLX90393_ReadSensor, pdTRUE, pdTRUE, portMAX_DELAY);
intError = fReadSPIdataXbits( _hMLX90393, MLX90393_REG_RM | MLX90393_AXIS_ALL, rx, 9 );
I tried reading the data after the request for a data read, without waiting for the data to be ready. The data I got was all over the place. When I added in code to handle Data Ready, the data read became sensible.
I'll try the aprouch you're suggesting. Thanks.
So I did your suggestions to work with a interruption for the DR but I'm still not getting a Data which I think is trustable, I don't know if it's something about how I worked with the interuption or the data reading.
//----------Bibliotecas------------------
#include <LiquidCrystal.h>
#include <EEPROM.h>
#include <SPI.h>
//-------------Variaveis---------------------
#define sdo 11 // Data out pin
#define sdi 12 // Data in pin
#define sclk 13 // SPI clock pin
#define cs 10 // Chip select pin
#define mclr 9 // MCLR of MCP3909
#define G0 7
#define G1 8
#define DR 2
LiquidCrystal LCD(A1, 3, 4, 5, 6, A0);
int CH1;
int CH0;
//------------------------------------------
void setup() {
pinMode(sdo, OUTPUT);
pinMode(sdi, INPUT);
pinMode(sclk, OUTPUT);
pinMode(mclr, OUTPUT);
pinMode(cs, OUTPUT);
pinMode(G0, OUTPUT);
pinMode(G1, OUTPUT);
pinMode(DR, INPUT);
digitalWrite (G0, HIGH);
digitalWrite (G1, LOW);
SPI.begin();
SPI.beginTransaction (SPISettings (8000000, MSBFIRST, SPI_MODE1));
digitalWrite(mclr, LOW); // Hold cleared MCP3909
digitalWrite(cs, HIGH); // Disable slave device
delayMicroseconds(1);
digitalWrite(mclr, HIGH); //Disable mclr for MCP3909
digitalWrite(cs, LOW); //Enable chip select
delayMicroseconds(1); //Twinset
//Load the Dual channel Post-HPF operation mode directive
SPI.transfer(0xAC);
digitalWrite(cs,HIGH); //Disable chip select
//attachInterrupt(digitalPinToInterrupt(DR), Data, FALLING); It didn't workout
LCD.begin(16, 2);
LCD.setCursor(2,0);
LCD.print("FTX Meter");
delay (2000);
LCD.clear();
}
void loop() {
digitalWrite(cs,LOW);
SPI.transfer(0x00);
while (digitalRead(DR)){};
Data();
digitalWrite(cs,HIGH);
LCD.setCursor(0,0);
LCD.print(CH1);
delay (1);
LCD.setCursor(0,1);
LCD.print(CH0);
delay (1);
}
void Data() {
CH1=SPI.transfer16(0x00);
CH0=SPI.transfer16(0x00);
}
TitodeMiranda:
So I did your suggestions to work with a interruption for the DR but I'm still not getting a Data which I think is trustable, I don't know if it's something about how I worked with the interuption or the data reading.
if you have access to an oscilloscope/logic analyzer, I would suggest you probe the CS SCK and SDO lines and see how the signals looks like (as in do they behave as suggested in the datasheet?...)
Where is the code for the interrupt handler?
Perhaps this may show in a better way: Arduino - Interrupts
Idahowalker:
Where is the code for the interrupt handler?
Perhaps this may show in a better way: Arduino - Interrupts
I don't get it, would you please do a example of your code the way I could use with the arduino IDE?
I can't understand how will I verify a falling edge in a pin which has a data comming and will have a lot of rising and falling
I'm starting to think that I'm not being able to send the data mode to the IC in (32/MCLK), maybe it's not possible to use Arduino IDE for this.
What do you think?
TitodeMiranda:
I'm starting to think that I'm not being able to send the data mode to the IC in (32/MCLK), maybe it's not possible to use Arduino IDE for this.
What do you think?
see post #9. verify the signals...