Go Down

Topic: SPI Conflict Help Please (Read 744 times) previous topic - next topic

yeti195

Hello, and thank you for reading this and any help is greatly appreciated.
I have been working on a project for some time now, and learning a lot.  It's my first big project.  
My goal is to have a multi-channel voltage meter with an LCD display.  I also would like to have it speak Modbus protocol to a SCADA HMI to display voltages and trend the data.  
I have the voltage meter part working great using a shield from rascalmicro.com called the The Precision Voltage Shield[font=Helvetica Neue, Helvetica, Arial, sans-serif]  [/font]Here's a picture of the shield reading voltages very accurately of a 48v battery array.  




At the time of the picture I was using Ethernet shield v1 from Seeedstudio.   I've had some trouble with it, so I now have V2.  It's got a w5200 chip, and other improvements.   I found a library that's a modified version of the Arduino included w5100.h and .cpp files to allow you to use the examples with this shield.  It seams to work great when using it by itself.  No other shields attached.  
I seem to have everything working, but not together.  I can get a modbus project working great when only using the Ethernet shield.  The voltage shield works great, with the LCD.  It's when I try to add it all together it fails.  
Here's what fails. and I'll include all the code.   With it all together, I see the voltages on the LCD, and in the serial monitor.  I can not get the Modbus protocol to work.  I can ping the IP address of the Ethernet shield with no problem, but when I try to connect to port 502 it refuses the connection.  I'm using a program called Hercules to try to establish a connection, and here's a screen shot of it.





Since I can get everything working when done individually, I'm guessing it's maybe a SPI conflict somehow?  Now, again I'm new to this and still have lots to learn.  

Here's the code:

Arduino Sketch

Code: [Select]
#include <SPI.h>
#include <LiquidCrystal.h>
#include <Ethernet.h>
#include <Mudbus.h>

LiquidCrystal lcd(14, 15, 16, 17, 18, 19);

Mudbus Mb;

#define SCALE_FACTOR 0.000152587890625
#define SCALE_FACTOR_1 SCALE_FACTOR * 3.681
#define SCALE_FACTOR_2 SCALE_FACTOR * 6.642
#define SCALE_FACTOR_3 SCALE_FACTOR * 11.096
#define SCALE_FACTOR_4 SCALE_FACTOR * 12.982

// 10/(2^16) = 0.000152587890625
// To find multiply factor (R2+R1)/R2

#define BUSY 3
#define RESET 2
#define START_CONVERSION 5
#define CHIP_SELECT 9
#define MISO 12
#define TOTAL_RAW_BYTES 16

int bytesToRead = TOTAL_RAW_BYTES;  
byte raw[TOTAL_RAW_BYTES];  
signed long parsed[8];


void setup() {  
  
  uint8_t mac[]     = { 0x90, 0xA2, 0xDA, 0x00, 0x51, 0x06 };
  uint8_t ip[]      = { 192, 168, 1, 143 };
  uint8_t gateway[] = { 192, 168, 1, 1 };
  uint8_t subnet[]  = { 255, 255, 255, 0 };
      
  pinMode(BUSY, INPUT);
  pinMode(RESET, OUTPUT);
  pinMode(START_CONVERSION, OUTPUT);
  pinMode(MISO, INPUT);

  SPI.begin();
  Ethernet.begin(mac, ip, gateway, subnet);
  Serial.begin(115200);
  lcd.begin(20, 4);
  
  digitalWrite(START_CONVERSION, HIGH);  
  digitalWrite(CHIP_SELECT, HIGH);
  digitalWrite(RESET, HIGH);
  delay(1);
  digitalWrite(RESET, LOW);
  }

void loop() {  
  
  Mb.Run();
  Mb.R[0] = 100;
  
  int i;

  digitalWrite(START_CONVERSION, LOW);
  delayMicroseconds(10);
  digitalWrite(START_CONVERSION, HIGH);

  while (digitalRead(BUSY) == HIGH) {
    // wait for conversion to complete
  }
  digitalWrite(CHIP_SELECT, LOW);
  while (bytesToRead > 0) {
    raw[TOTAL_RAW_BYTES - bytesToRead] = SPI.transfer(0x00);
    bytesToRead--;
  }
  digitalWrite(CHIP_SELECT, HIGH);
  bytesToRead = TOTAL_RAW_BYTES;

  parseRawBytes();
  
  for(i=0; i<8; i++) {
    Serial.print((float)parsed[i] * SCALE_FACTOR, 5);
    Serial.print(",");
  }
  Serial.print("\r\n");
  delay(1000);
  
// Battery 1
  lcd.setCursor(0, 0);
  lcd.print("1:");
  lcd.setCursor(3, 0);
  lcd.print(parsed[0] * SCALE_FACTOR_1, 2);
  lcd.setCursor(8, 0);
  lcd.print("  |");

// Battery 2
  lcd.setCursor(0, 1);
  lcd.print("2:");
  lcd.setCursor(3, 1);
  lcd.print(parsed[1] * SCALE_FACTOR_2 - parsed[0] * SCALE_FACTOR_1, 2);
  lcd.setCursor(8, 1);
  lcd.print("  |");

// Battery 3  
  lcd.setCursor(0, 2);
  lcd.print("3:");
  lcd.setCursor(3, 2);
  lcd.print(parsed[2] * SCALE_FACTOR_3 - parsed[1] * SCALE_FACTOR_2, 2);
  lcd.setCursor(8, 2);
  lcd.print("  |");

// Battery 4  
  lcd.setCursor(0, 3);
  lcd.print("4:");
  lcd.setCursor(3, 3);
  lcd.print(parsed[3] * SCALE_FACTOR_4 - parsed[2] * SCALE_FACTOR_3, 2);
  lcd.setCursor(8, 3);
  lcd.print("  |");
  
// Total Voltage
  lcd.setCursor(13, 0);
  lcd.print("Total");
  lcd.setCursor(13, 1);
  lcd.print(parsed[3] * SCALE_FACTOR_4, 2);
}

void parseRawBytes() {  
  
  int i;
  
  parsed[0] = (raw[0] << 8) + raw[1];
  parsed[1] = (raw[2] << 8) + raw[3];
  parsed[2] = (raw[4] << 8) + raw[5];
  parsed[3] = (raw[6] << 8) + raw[7];
  parsed[4] = (raw[8] << 8) + raw[9];
  parsed[5] = (raw[10] << 8) + raw[11];
  parsed[6] = (raw[12] << 8) + raw[13];
  parsed[7] = (raw[14] << 8) + raw[15];

for(i=0; i<8; i++) {
    parsed[i] = fixSignBit(parsed[i]);
  }
}
 
long fixSignBit(long reading) {
  
  if(reading & 0x8000) { // if reading is < 0 (stored as two's complement)
        return reading | 0xFFFF0000; // set bits 31-16
      } else {
        return reading;
      }
      }


I tried to post the modified w5100.h and .cpp files along with the Modbus files, but it would not allow me to.  So, I put them in a .zip file so you can download them if you want to see them as well.  

Again thank you for any help and guidance.  

SurferTim

A couple things I see right off is you are not disabling the w5200 before communicating with the device using D9 as the slave select. That could mess up both devices.
Code: [Select]
void setup() {
   pinMode(10,OUTPUT);
   digitalWrite(10,HIGH);

   // rest of your current setup


Next, the Ethernet.begin() call is missing a parameter.
Code: [Select]
// replace this
Ethernet.begin(mac, ip, gateway, subnet);
// with this
Ethernet.begin(mac, ip, gateway, gateway, subnet);


You are not declaring a server instance to accept a connection from another device, nor are you starting the server listening.
Code: [Select]
// in global variable declarations
EthernetServer server(502);

// then in setup() after Ethernet.begin(), start the server listening
   server.begin();

yeti195

Thank you for the really fast reply.  I really appreciate it.   I tried all three things and same results.  

Quote
[font=TyponineSans Regular 18]you are not disabling the w5200 before communicating with the device using D9 as the slave select.[/font]
I missed that one.
Quote
[font=TyponineSans Regular 18]Next, the Ethernet.begin() call is missing a parameter.

[/font]

Code: [Select]
// replace this[font='DejaVu Sans Mono', Monaco, Consolas, monospace][/font]
Ethernet.begin(mac, ip, gateway, subnet);[font='DejaVu Sans Mono', Monaco, Consolas, monospace][/font]
// with this[font='DejaVu Sans Mono', Monaco, Consolas, monospace][/font]
Ethernet.begin(mac, ip, gateway, gateway, subnet);

Just wondering why gateway twice?
Quote
[font=TyponineSans Regular 18]You are not declaring a server instance to accept a connection from another device, nor are you starting the server listening.
[/font]

Code: [Select]
// in global variable declarations[font='DejaVu Sans Mono', Monaco, Consolas, monospace][/font]
EthernetServer server(502);[font='DejaVu Sans Mono', Monaco, Consolas, monospace][/font]
[font='DejaVu Sans Mono', Monaco, Consolas, monospace][/font]
// then in setup() after Ethernet.begin(), start the server listening[font='DejaVu Sans Mono', Monaco, Consolas, monospace][/font]
   server.begin();

I added this as well, but I believe that this is in the Modbus.h file or .cpp. 
Again thank you for the response.  Any other ideas?

yeti195

Updated code with the suggestions:

Code: [Select]
#include <SPI.h>
#include <LiquidCrystal.h>
#include <Ethernet.h>
#include <Mudbus.h>

LiquidCrystal lcd(14, 15, 16, 17, 18, 19);

Mudbus Mb;

#define SCALE_FACTOR 0.000152587890625
#define SCALE_FACTOR_1 SCALE_FACTOR * 3.681
#define SCALE_FACTOR_2 SCALE_FACTOR * 6.642
#define SCALE_FACTOR_3 SCALE_FACTOR * 11.096
#define SCALE_FACTOR_4 SCALE_FACTOR * 12.982

// 10/(2^16) = 0.000152587890625
// To find multiply factor (R2+R1)/R2

#define BUSY 3
#define RESET 2
#define START_CONVERSION 5
#define CHIP_SELECT 9
#define MISO 12
#define TOTAL_RAW_BYTES 16
EthernetServer server(502);

int bytesToRead = TOTAL_RAW_BYTES; 
byte raw[TOTAL_RAW_BYTES]; 
signed long parsed[8];


void setup() { 
 
  uint8_t mac[]     = { 0x90, 0xA2, 0xDA, 0x00, 0x51, 0x06 };
  uint8_t ip[]      = { 192, 168, 1, 143 };
  uint8_t gateway[] = { 192, 168, 1, 1 };
  uint8_t subnet[]  = { 255, 255, 255, 0 };
     
  pinMode(BUSY, INPUT);
  pinMode(RESET, OUTPUT);
  pinMode(START_CONVERSION, OUTPUT);
  pinMode(MISO, INPUT);
  pinMode(10,OUTPUT);
  digitalWrite(10,HIGH);
 
  SPI.begin();
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  server.begin();
  Serial.begin(115200);
  lcd.begin(20, 4);
 
  digitalWrite(START_CONVERSION, HIGH); 
  digitalWrite(CHIP_SELECT, HIGH);
  digitalWrite(RESET, HIGH);
  delay(1);
  digitalWrite(RESET, LOW);
  }

void loop() { 
 
  Mb.Run();
  Mb.R[0] = 100;
 
  int i;

  digitalWrite(START_CONVERSION, LOW);
  delayMicroseconds(10);
  digitalWrite(START_CONVERSION, HIGH);

  while (digitalRead(BUSY) == HIGH) {
    // wait for conversion to complete
  }
  digitalWrite(CHIP_SELECT, LOW);
  while (bytesToRead > 0) {
    raw[TOTAL_RAW_BYTES - bytesToRead] = SPI.transfer(0x00);
    bytesToRead--;
  }
  digitalWrite(CHIP_SELECT, HIGH);
 
  bytesToRead = TOTAL_RAW_BYTES;

  parseRawBytes();
   
  for(i=0; i<8; i++) {
    Serial.print((float)parsed[i] * SCALE_FACTOR, 5);
    Serial.print(",");
  }
  Serial.print("\r\n");
  delay(1000);
 
// Battery 1
  lcd.setCursor(0, 0);
  lcd.print("1:");
  lcd.setCursor(3, 0);
  lcd.print(parsed[0] * SCALE_FACTOR_1, 2);
  lcd.setCursor(8, 0);
  lcd.print("  |");

// Battery 2
  lcd.setCursor(0, 1);
  lcd.print("2:");
  lcd.setCursor(3, 1);
  lcd.print(parsed[1] * SCALE_FACTOR_2 - parsed[0] * SCALE_FACTOR_1, 2);
  lcd.setCursor(8, 1);
  lcd.print("  |");

// Battery 3 
  lcd.setCursor(0, 2);
  lcd.print("3:");
  lcd.setCursor(3, 2);
  lcd.print(parsed[2] * SCALE_FACTOR_3 - parsed[1] * SCALE_FACTOR_2, 2);
  lcd.setCursor(8, 2);
  lcd.print("  |");

// Battery 4 
  lcd.setCursor(0, 3);
  lcd.print("4:");
  lcd.setCursor(3, 3);
  lcd.print(parsed[3] * SCALE_FACTOR_4 - parsed[2] * SCALE_FACTOR_3, 2);
  lcd.setCursor(8, 3);
  lcd.print("  |");
 
// Total Voltage
  lcd.setCursor(13, 0);
  lcd.print("Total");
  lcd.setCursor(13, 1);
  lcd.print(parsed[3] * SCALE_FACTOR_4, 2);
  }

void parseRawBytes() { 
 
  int i;
 
  parsed[0] = (raw[0] << 8) + raw[1];
  parsed[1] = (raw[2] << 8) + raw[3];
  parsed[2] = (raw[4] << 8) + raw[5];
  parsed[3] = (raw[6] << 8) + raw[7];
  parsed[4] = (raw[8] << 8) + raw[9];
  parsed[5] = (raw[10] << 8) + raw[11];
  parsed[6] = (raw[12] << 8) + raw[13];
  parsed[7] = (raw[14] << 8) + raw[15];

for(i=0; i<8; i++) {
    parsed[i] = fixSignBit(parsed[i]);
  }
}
 
long fixSignBit(long reading) {
 
  if(reading & 0x8000) { // if reading is < 0 (stored as two's complement)
        return reading | 0xFFFF0000; // set bits 31-16
      } else {
        return reading;
      }
      }

SurferTim

I hope the spelling is correct, but is the include and instance actually Mudbus?
Code: [Select]
#include <Mudbus.h>

LiquidCrystal lcd(14, 15, 16, 17, 18, 19);

Mudbus Mb;

Where did you get the Modbus library?

yeti195

I got the Modbus lib here.  [font=TyponineSans Regular 18]https://code.google.com/p/mudbus/  I have used it in other sketches with no problem.  It's just in this one.  [/font]

yeti195

Well, I think I'm going to give up on the Modbus protocol for this project.   Been trying for weeks now, with no success due to my lack of knowledge.

In the first sketch in my first post where is says this.

Code: [Select]

  for(i=0; i<8; i++) {
    Serial.print((float)parsed[i] * SCALE_FACTOR, 5);
    Serial.print(",");
  }
  Serial.print("\r\n");
  delay(1000);


It sends the reading out the serial port, and I can see it using the serial monitor.  How would I send this via udp to a specific IP address using the ethernet shield?

Thank you again for any and all help.  I do really appreciate it.

SurferTim

This link has the example code I use. Modify it as you desire.
http://forum.arduino.cc/index.php?topic=274009.msg1931616#msg1931616
It has both the Arduino "client" code and Linux "server" code based on the NTP examples.

Go Up