Arduino Ethernet Shield + SPI ADC
Hello togehter,
Currently I’m working on a project on an Arduino Mega. I want to use an Ethernet shield (driver Chip: Wiz5500) in combination with an external 13 Bit ADC (Microchip MCP3304) and a LC-Display.
I created a sketch with 3 Timeslices, which are triggered by a Timer Interrupt. The interrupt Routine is executed 400 times per second.
Basically the Ethernet should listen to several Commands (Called SCPI_Commands). They were sended by an external PC as raw Strings over the TCP/IP Connection. I used the standard Ethernet setup with the Arduino Ethernet Library. The incoming SCPI_Command points on a Function, which the Arduino should execute. This part of code stands in the setup function. This Timeslice is called every 10 ms
In the second Timeslice print out the 8 Voltage Values on the display, which are measured by the external ADC in the third Timeslice.
The Ethernet part works fine if the SPI wires from the external ADC are not connected to the SPI Bus. The combination of both cause that it is not possible anymore to send commands to the System. Without the external ADC that works fine.
The connection via Putty seems to work fine as well, the error message occurs after sending the first command.
The strange thing for me is that I can trigger via Ethernet the Function MeaVol (that’s not the Function which is triggered in Timeslice 3). This function is triggered by the SCPI_Command :MEA:VOL and returns the Value of Chanel 0 of the external ADC. That works fine as well.
I know that there are several articles in different Forums but the only message that I found is that the Ethernetshield and the other SPI device need different CS Pins. In my case the CS for the Ethernet shield should be by default on Pin 10 and the CS for the ADC is on pin 49. The SS Pin (on the MEGA pin 53 is set to an OUTPUT but not used in my case.
I postet the Code below this text. I posted the Arduino Sketch and the library for the external ADC. To get the Values of the ADC the code in the library changes the SPI Settings a little bit maybe that could cause my Problems but I don’t think so.
My Questions are if anybody can help me with some ideas what could be wrong.
One another Question: Is it possible to use an Ethernet Shield with another SPI device or not.
Thanks for your Support.
That’s the Arduino Sketch
#include <Arduino.h>
#include <Ethernet.h>
#include “Vrekrer_scpi_parser.h”
#include “global_defs.h”
#include “MCP3304.h”
#include “LiquidCrystal_I2C.h”
#include “Wire.h”
//Beginning of Auto generated function prototypes by Atmel Studio
void Identify(SCPI_C commands, SCPI_P parameters, EthernetClient& client);
void SetBrightness(SCPI_C commands, SCPI_P parameters, EthernetClient& client);
void GetBrightness(SCPI_C commands, SCPI_P parameters, EthernetClient& client);
void MeaVol(SCPI_C commands, SCPI_P parameters, EthernetClient& client);
void IncDecBrightness(SCPI_C commands, SCPI_P parameters, EthernetClient& client);
void MeaTemp(SCPI_C commands, SCPI_P parameters, EthernetClient& client);
void TIM1_callback();
void MEA_VOL();
void printlcd();
//End of Auto generated function prototypes by Atmel Studio
byte mac = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 178, 177);
IPAddress myDns(0, 0, 0, 0);
IPAddress gateway(10, 11, 146, 254);
IPAddress subnet(255, 255, 252, 0);
MCP3304 adc(49);
EthernetServer server(23);
SCPI_Parser my_instrument;
LiquidCrystal_I2C lcd(0x27,16,2);
int brightness = 0;
const int ledPin = 9;
const int intensity[11] = {0, 3, 5, 9, 15, 24, 38, 62, 99, 159, 255};
int counters[NO_COUNTERS];
float Voltages[8];
void setup() {
lcd.begin();
pinMode(ledPin, OUTPUT);
Ethernet.begin(mac, ip);//, myDns, gateway, subnet);
server.begin();
my_instrument.RegisterCommand(F("*IDN?"), &Identify);
my_instrument.SetCommandTreeBase(F("SYSTem:ULtracap"));
my_instrument.RegisterCommand(F(":BRIGhtness"), &SetBrightness);
my_instrument.RegisterCommand(F(":BRIGhtness?"), &GetBrightness);
my_instrument.RegisterCommand(F(":BRIGhtness:INCrease"), &IncDecBrightness);
my_instrument.RegisterCommand(F(":BRIGhtness:DECrease"), &IncDecBrightness);
my_instrument.RegisterCommand(F(":MEA:VOL"),&MeaVol);
my_instrument.RegisterCommand(F(":MEA:TEMP"),&MeaTemp);
Serial.begin(115200);
Timer1.initialize(1000000UL/INTS_PER_SECOND); // Timer Interrupt every 2500µs → 400 Ints per Second…
Timer1.attachInterrupt(TIM1_callback);
pinMode(7,OUTPUT);
for (byte i = 0; i < NO_COUNTERS; i++)
{
counters[i] = -1;
}
}
void loop() {
if (counters[ETH_BUS] < 1) {
counters[ETH_BUS] = 4;
EthernetClient client = server.available();
if(client.connected()){
my_instrument.Execute(client);
}
}
if (counters[LC_Display] < 1) {
counters[LC_Display] = 23 ;
printlcd();
}
if (counters[ADConverter] < 1) {
counters[ADConverter] = 10 ;
MEA_VOL();
}
}
void Identify(SCPI_C commands, SCPI_P parameters, EthernetClient& client) {
client.println(F(“Vrekrer,Arduino SCPI Ethernet Instrument,#00,v0.4”));
}
void SetBrightness(SCPI_C commands, SCPI_P parameters, EthernetClient& client) {
if (parameters.Size() > 0) {
brightness = constrain(String(parameters[0]).toInt(), 0, 10);
analogWrite(ledPin, intensity[brightness]);
}
}
void GetBrightness(SCPI_C commands, SCPI_P parameters, EthernetClient& client) {
client.println(String(brightness, DEC));
}
void IncDecBrightness(SCPI_C commands, SCPI_P parameters, EthernetClient& client) {
String last_header = String(commands.Last());
last_header.toUpperCase();
if (last_header.startsWith(“INC”)) {
brightness = constrain(brightness + 1, 0, 10);
} else { // “DEC”
brightness = constrain(brightness - 1, 0, 10);
}
analogWrite(ledPin, intensity[brightness]);
}
void MeaVol(SCPI_C commands, SCPI_P parameters, EthernetClient& client) {
client.print("VOLTAGE = ");
client.println(adc.readSgl(0));
}
void MeaTemp(SCPI_C commands, SCPI_P parameters, EthernetClient& client) {
client.print("Temp = ");
client.println(adc.readSgl(1));
}
void TIM1_callback()
{
byte i = 0;
for (i = 0; i < NO_COUNTERS; i++)
{
if (counters[i] > -1)
counters[i]--;
}
}
void MEA_VOL(){
for(int i = 0; i<8;i++){
Voltages[i]=adc.readSgl(i);
}
}
void printlcd(){
lcd.setCursor(0,0);
lcd.print("V1 ");
lcd.print(Voltages[0],3);
lcd.setCursor(0,1);
lcd.print("V2 ");
lcd.print(Voltages[1],3);
}
that’s the read Function from the MCP3304 Library
int MCP3304::readAdc(int pin, boolean sgl) {
pin %= 8; //no more then 8 pins
SPI.setClockDivider(SPI_CLOCK_DIV16); //Set Clockdivider for 1MHz SPI freq.
SPI.setBitOrder(MSBFIRST); //set to most significatn bit first
SPI.setDataMode(SPI_MODE0); // SPI 0,0 as per MCP330x data sheet
byte configBits;
sgl ? configBits=0x0C : configBits=0x08; // 1100 for SGL mode, 1000 for DIFF mode
digitalWrite(_CS, LOW); //activate Chipselect
SPI.transfer(configBits | (pin >> 1)); //4bits 0, startbit, SGL/DIFF, 2 Channelbits (D2, D1)
byte hi = SPI.transfer(pin << 7); //lowest Channelbit (D0), rest dont care;return= first 2 returnbits undef, nullbit, Signbit, 4 highest databits
byte lo = SPI.transfer(0x00); //send dont care;return= 8 lowest databits
digitalWrite(_CS, HIGH); //deactivate Chipselect
byte sign = hi & 0x10; //extract Sign Bit for DIFF
int adcValue = ((hi & 0x0f) << 8) + lo; //combinig the 2 return Values
if(sign){
adcValue -= 4096; //if CH- > CH+
}
SPI.setClockDivider(SPI_CLOCK_DIV4); //set back to default SPI speed
return adcValue;
}