Hi, I've been trying to implement SPI transactions on an ADE7753 library so I can share the SPI Bus with the nrf8001 breakout board from adafruit. I started from this code wich Paul posted on the adafruit forum
I deleted the SD part and it runs without problem. So I started adding the ADE7753 code with the transactions implementation. This is my try.
The thing is, those meter.analogSetup(GAIN_1,GAIN_1, 0,0,0,0); meter.setMode(0x0080); functions only involve writing to some registers, but when I uncomment the meter.vrms() function (wich is a reading function), the bluetooth part just doesn't work anymore.
Here is the rest of the code involved
Maybe is just the way I add the transactions part to the ade7753 library but so far I have no clue, I hope anyone can help me, thanks.
Code:
// http://forum.pjrc.com/threads/27069-Adafruit_nrf8001-and-SDFat-problem-on-teensy-3-1
#include <SPI.h>
#include <Adafruit_BLE_UART.h>
#include <SD.h>
#define SDCARD_CS 4
#define ADAFRUITBLE_REQ 10
#define ADAFRUITBLE_RST 9
#if defined(__AVR__) && defined(TEENSYDUINO)
#define ADAFRUITBLE_RDY 5 // pin 5 on Teensy 2.0
#else
#define ADAFRUITBLE_RDY 2 // pin 2 on Arduino Uno & Teensy 3.1
#endif
Adafruit_BLE_UART uart = Adafruit_BLE_UART(ADAFRUITBLE_REQ, ADAFRUITBLE_RDY, ADAFRUITBLE_RST);
/**************************************************************************/
/*!
This function is called whenever select ACI events happen
*/
/**************************************************************************/
void aciCallback(aci_evt_opcode_t event)
{
switch(event)
{
case ACI_EVT_DEVICE_STARTED:
Serial.println(F("Advertising started"));
break;
case ACI_EVT_CONNECTED:
Serial.println(F("Connected!"));
break;
case ACI_EVT_DISCONNECTED:
Serial.println(F("Disconnected or advertising timed out"));
break;
default:
break;
}
}
/**************************************************************************/
/*!
This function is called whenever data arrives on the RX channel
*/
/**************************************************************************/
void rxCallback(uint8_t *buffer, uint8_t len)
{
Serial.print(F("Received "));
Serial.print(len);
Serial.print(F(" bytes: "));
for(int i=0; i<len; i++)
Serial.print((char)buffer[i]);
Serial.print(F(" ["));
for(int i=0; i<len; i++)
{
Serial.print(" 0x"); Serial.print((char)buffer[i], HEX);
}
Serial.println(F(" ]"));
/* Echo the same data back! */
uart.write(buffer, len);
}
/**************************************************************************/
/*!
Configure the Arduino and start advertising with the radio
*/
/**************************************************************************/
void setup(void)
{
// first, bring both chip selects up to logic high
// each library will make the pin an output, but
// this prevents either device from "hearing" the
// communication to the other's initialization.
pinMode(ADAFRUITBLE_RDY, INPUT_PULLUP);
pinMode(SDCARD_CS, INPUT_PULLUP);
pinMode(14, OUTPUT);
digitalWrite(14, LOW); // test LED on pin 14
delay(50);
Serial.begin(9600);
while(!Serial); // Leonardo/Micro should wait for serial init
Serial.println(F("Adafruit Bluefruit Low Energy nRF8001 Callback Echo demo"));
//SD.begin(SDCARD_CS);
uart.setRXcallback(rxCallback);
uart.setACIcallback(aciCallback);
uart.setDeviceName("NEWNAME"); /* 7 characters max! */
uart.begin();
}
/**************************************************************************/
/*!
Constantly checks for new events on the nRF8001
*/
/**************************************************************************/
void loop()
{
uart.pollACI();
}
void get_sd_card_files()
{
Serial.println(F("Opening SD card to generate list"));
Serial.print("EIMSK = ");
Serial.println(EIMSK);
if (SD.begin(SDCARD_CS)) {
Serial.println(F("SD card is ok :-)"));
//printDirectory(SD.open("/"), 0);
} else {
Serial.println(F("no SD card"));
}
Serial.print("EIMSK = ");
Serial.println(EIMSK);
//Serial.print("SPI.interruptMode = ");
//Serial.println(SPI.interruptMode);
}
void printDirectory(File dir, int numTabs) {
while(true) {
File entry = dir.openNextFile();
if (! entry) {
// no more files
//Serial.println("**nomorefiles**");
break;
}
for (uint8_t i=0; i<numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
printDirectory(entry, numTabs+1);
} else {
// files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}
}
I deleted the SD part and it runs without problem. So I started adding the ADE7753 code with the transactions implementation. This is my try.
Code:
#include <SPI.h>
#include <Adafruit_BLE_UART.h>
#include "ADE7753.h"
#define ADAFRUITBLE_REQ 8
#define ADAFRUITBLE_RDY 2 // This should be an interrupt pin, on Uno thats #2 or #3
#define ADAFRUITBLE_RST 7
#define ratioTraf (127/12.3) //18.3
Adafruit_BLE_UART uart = Adafruit_BLE_UART(ADAFRUITBLE_REQ, ADAFRUITBLE_RDY, ADAFRUITBLE_RST);
/**************************************************************************/
/*!
This function is called whenever select ACI events happen
*/
/**************************************************************************/
void aciCallback(aci_evt_opcode_t event)
{
switch(event)
{
case ACI_EVT_DEVICE_STARTED:
Serial.println(F("Advertising started"));
break;
case ACI_EVT_CONNECTED:
Serial.println(F("Connected!"));
break;
case ACI_EVT_DISCONNECTED:
Serial.println(F("Disconnected or advertising timed out"));
break;
default:
break;
}
}
/**************************************************************************/
/*!
This function is called whenever data arrives on the RX channel
*/
/**************************************************************************/
void rxCallback(uint8_t *buffer, uint8_t len)
{
Serial.print(F("Received "));
Serial.print(len);
Serial.print(F(" bytes: "));
for(int i=0; i<len; i++)
Serial.print((char)buffer[i]);
Serial.print(F(" ["));
for(int i=0; i<len; i++)
{
Serial.print(" 0x"); Serial.print((char)buffer[i], HEX);
}
Serial.println(F(" ]"));
/* Echo the same data back! */
uart.write(buffer, len);
// Triger card read if 'K" is in the buffer.
// if (*buffer == 'K' || *buffer == 'k') {
// get_sd_card_files();
// }
}
/**************************************************************************/
/*!
Configure the Arduino and start advertising with the radio
*/
/**************************************************************************/
void setup(void)
{
// first, bring both chip selects up to logic high
// each library will make the pin an output, but
// this prevents either device from "hearing" the
// communication to the other's initialization.
pinMode(ADAFRUITBLE_RDY, INPUT_PULLUP);
delay(50);
Serial.begin(9600);
while(!Serial); // Leonardo/Micro should wait for serial init
Serial.println(F("Adafruit Bluefruit Low Energy nRF8001 Callback Echo demo"));
//SD.begin(SDCARD_CS);
uart.setRXcallback(rxCallback);
uart.setACIcallback(aciCallback);
uart.setDeviceName("NEWNAME"); // 7 characters max!
uart.begin();
}
/**************************************************************************/
/*!
Constantly checks for new events on the nRF8001
*/
/**************************************************************************/
void loop()
{
ADE7753 meter = ADE7753();
uart.pollACI();
meter.analogSetup(GAIN_1,GAIN_1, 0,0,0,0);
meter.setMode(0x0080);
long v1,i1,e1,e2,e3,ae1,ae2,ae3,r1,r2,r3;
float totEnergy = 0;
float kv,ki,ke,ka,kt,f1,basetime;
float voltage, current, energy, aparent, reactive, PF, litros;
String typeLoad = "";
int t1;
int loopCounter = 1;
char buffer[10];
//Constantes de proporcionalidad.
kv = (ratioTraf)*VOLTDIV*(0.5/0x2851EC); //(0.5/0x2851EC) From Datasheet
ki = CURRDIV*(0.5/0x17D338); //(0.5/0x17D338) From Datasheet
ke = (10/16.0)*VOLTDIV*CURRDIV/4096.0; // 1/(2^12)
kt = CLKIN/8; //period register, resolution x.y[us]/LSB -per bit-
basetime = (1.0*NUMCYC)/100.0; // tiempo por el cual se acumula energia
//--Medición de voltaje--
//v1=meter.vrms();
}
The thing is, those meter.analogSetup(GAIN_1,GAIN_1, 0,0,0,0); meter.setMode(0x0080); functions only involve writing to some registers, but when I uncomment the meter.vrms() function (wich is a reading function), the bluetooth part just doesn't work anymore.
Here is the rest of the code involved
Code:
void ADE7753::analogSetup(char gain_ch1, char gain_ch2,char os_ch1,char os_ch2,char scale_ch1,char integrator_ch1){
char pga = (gain_ch2<<5) | (scale_ch1<<3) | (gain_ch1);
char sign = 0;
char ch1os = 0, ch2os = 0;
write8(GAIN,pga);//write GAIN register, format is |3 bits PGA2 gain|2 bits full scale|3 bits PGA1 gain
//ch1 offset, sign magnitude and integrator
if(os_ch1<0){
sign=1;
os_ch1=-os_ch1;
}
ch1os = (integrator_ch1<<7) | (sign<<5) | os_ch1;
write8(CH1OS,ch1os);
//ch2 offset, sign magnitude (ch2 doesn't have integrator) and the offset applied is inverted (ie offset of -1 sums 1)
if(os_ch2<0){
sign=0;
os_ch1=-os_ch1;
}
else{
sign=1;
}
ch2os = (sign<<5) | os_ch2;
write8(CH2OS,ch2os);
}
Code:
void ADE7753::write8(char reg, char data){
SPI.beginTransaction(SPI_BLE_SETTINGS);
enableChip();
//we have to send a 1 on the 8th bit in order to perform a write
reg |= WRITE;
delayMicroseconds(10);
SPI.transfer((unsigned char)reg); //register selection
delayMicroseconds(5);
SPI.transfer((unsigned char)data);
delayMicroseconds(5);
disableChip();
SPI.endTransaction();
}
Code:
void ADE7753::setMode(int m){
write16(MODE, m);
}
Code:
void ADE7753::write16(char reg, int data){
SPI.beginTransaction(SPI_BLE_SETTINGS);
enableChip();
char aux=reg;
unsigned char data0=0,data1=0;
reg |= WRITE;
//split data
data0 = (unsigned char)data;
data1 = (unsigned char)(data>>8);
//register selection, we have to send a 1 on the 8th bit to perform a write
delayMicroseconds(10);
SPI.transfer((unsigned char)reg);
delayMicroseconds(5);
//data send, MSB first
SPI.transfer((unsigned char)data1);
delayMicroseconds(5);
SPI.transfer((unsigned char)data0);
delayMicroseconds(5);
disableChip();
SPI.endTransaction();
}
Code:
long ADE7753::vrms(){
char i=0;
long v=0;
getVRMS();//Ignore first reading to avoid garbage
for(i=0;i<20;++i){
v+=getVRMS();
}
return v/20;
}
Code:
long ADE7753::getVRMS(void){
long lastupdate = 0;
ADE7753::getresetInterruptStatus(); // Clear all interrupts
lastupdate = millis();
while( ! ( ADE7753::getInterruptStatus() & ZX ) ) // wait Zero-Crossing
{
}
// while( ! ( ADE7753::getInterruptStatus() ) ) // wait Zero-Crossing
// {}
return read24(VRMS);
}
Code:
ADE7753::ADE7753() {
pinMode(CS, INPUT_PULLUP);
pinMode(CS,OUTPUT);
digitalWrite(CS, HIGH);//disabled by default
// SPI Init
SPI.begin();
// Serial.begin(9600);//enable serial port
delay(10);
}
Code:
void ADE7753::enableChip(void){
digitalWrite(CS,LOW);
}
void ADE7753::disableChip(void){
digitalWrite(CS,HIGH);
}
Maybe is just the way I add the transactions part to the ade7753 library but so far I have no clue, I hope anyone can help me, thanks.