Log in

View Full Version : Arduino + Ethernet Shield Help


jwallace15
28-07-2013, 23:15
Alright, so I bought a book to help teach me about some Arduino programming. My Dad bought me an ethernet shield when I got my R3 and I never really knew what to do with it until I got the book, which dedicates a whole chapter to using Arduino with an ethernet shield.

I'm trying to hook this up to my train set and be able to turn things on and off from my upstairs computer (train set is in the basement). We took our old router and made it into a bridge to communicate to our current router to communicate to our computer. Pinging my Arduino's IP address works, so I know the connection is fine.

In the book it included code to be able to turn digital pin 8 on and off through a webpage. This is the code it had (that I copied into an Arduino Sketch):

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,1,130 };

const int MAX_PAGENAME_LEN = 8;
char buffer[MAX_PAGENAME_LEN+1];

EthernetServer server(80);

void setup()
{
Serial.begin(9600);
Ethernet.begin(mac, ip);
server.begin();
delay(2000);
}

void loop()
{
EthernetClient client = server.available();
if (client)
{
int type = 0;
while (client.connected())
{
if (client.available())
{
memset(buffer,0, sizeof(buffer));
if(client.find("/"))
if(client.readBytesUntil('/', buffer,sizeof(buffer)))
{
Serial.println(buffer);
if(strcmp(buffer,"POST ") == 0)
{
client.find("\n\r");
while(client.findUntil("PinD", "\n\r"))
{
int pin = client.parseInt();
int val = client.parseInt();
pinMode(pin, OUTPUT);
digitalWrite(pin, val);
}
}
sendHeader(client,"Post example");
client.println("<h2>Click buttons to turn pin 8 on or off</h2>");
client.print(
"<form action='/' method='POST'><p><input type='hidden' name='pinD8'");
client.println(" value='0'><input type='submit' value='Off'/></form>");
client.print(
"<form action='/' method='POST'><p><input type='hidden' name='pinD8'");
client.println(" value='1'><input type='submit' value='On'/></form>");
client.println("</body></html>");
client.stop();
}
break;
}
}
delay(1);
client.stop();
}
}
void sendHeader(EthernetClient client, char *title)
{
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
client.print("<html><head><title>");
client.print(title);
client.println("</title><body>");
}


I understand that the 2 HTML buttons assign the value of on or off (1 or 0) to the function digitalWrite(pin, val). However when I click either of the buttons on the webpage generated on the local IP address 130 nothing changes to the LED I have on digital pin 8. (and there are no electrical issues, I checked)

Can anyone help me? I've been stuck on this pretty much all day.

Thanks in advance.

tr6scott
29-07-2013, 06:30
Did not look at code, but can you control the led with the simple blink stater program to prove hardware functioning? If a board that has the led onboard for pin 13, maybe try that, just to prove hardware function.

jwallace15
29-07-2013, 10:08
Did not look at code, but can you control the led with the simple blink stater program to prove hardware functioning? If a board that has the led onboard for pin 13, maybe try that, just to prove hardware function.

This simple program to turn on the LED through ethernet is testing to see if I'll be able to control my much larger train set, which has different outputs and inputs (digital and analog). I just want to see if it can be done.

tr6scott
29-07-2013, 10:51
Well you need to look at what the arduino can source power at, and look at what you are trying to control on the train set to see if they are compatible, both volts and amp wise. Typically, to do anything but drive a led, or ttl level components, which I doubt the train set is, you will need to develop either isolation relay or triac interface between the arduino and the real world devices on the train. On the input side, again you are working with 0-5v analog on the arduino, so you may need some voltage division resistor network to get the voltage down to a range you can read.

We have our breakaway bot running on an arduino, and if you look at the picture, on the left you will see an eight relay interface board that we use to control the solenoids at 24vdc and the compressor at 12vdc.

http://www.mcbride4.org/wp-content/uploads/2013/03/2013-03-26_18-55-33_765.jpg

Also some trains run on ac, so you may have an issue there too.

jwallace15
29-07-2013, 11:03
I have this relay board that I was planning on using to turn things on and off. There are miscellaneous things all over my layout that I'm going to turn on and off with the relay board (blue thing).

I understand how everything will work electrically, I'm worried about the programming.

techhelpbb
29-07-2013, 14:49
I have this relay board that I was planning on using to turn things on and off. There are miscellaneous things all over my layout that I'm going to turn on and off with the relay board (blue thing).

I understand how everything will work electrically, I'm worried about the programming.

Make sure that board takes TTL input levels and provides the drive circuitry and bypass diodes for that circuitry to drive the relay coils in those relays.

You do not want to put an inductive load on your Arduino pins directly. Use the pins to drive a transistor or suitable IC to drive those relay coils. The picture does not show any drivers but they might be on the other side of the PCB.

jwallace15
29-07-2013, 14:51
The relay board has a VCC and GND pin. The Arduino outputs drive transistors on the board that power the relays.

tr6scott
29-07-2013, 15:42
Ok, I was just trying to see if you can control something with a basic sketch, to confirm it was working and wired, then add the ethernet control to the system.

I don't have the ethernet shield to play with, so I won't be of much help. Googling around, there appears to be a significant rewrite to the ethernet library, from the .002x to the 1.0.x versions, so it may be that code in the book, is worked with the pre 1.0 release of the IDE.

That being said, I did a search online, for some example code that was written post 1.0 and found the following examples.

http://bildr.org/2011/06/arduino-ethernet-pin-control//

and

http://startingelectronics.com/tutorials/arduino/ethernet-shield-web-server-tutorial/web-server-LED-control/

both look to be good examples of what you are trying to accomplish.

ajlapp
30-07-2013, 00:20
One simple option for testing...

Download and install the RobotOpen Driver Station App...

www.robotopen.biz

Then download the RobotOpen Library from the same area.

There are many example programs.

This code base will let you talk to the Arduino via wifi and control the outputs from a game pad.

It's a good place to start without actually understanding the underlying code.

techhelpbb
31-07-2013, 16:13
I have this relay board that I was planning on using to turn things on and off. There are miscellaneous things all over my layout that I'm going to turn on and off with the relay board (blue thing).

I understand how everything will work electrically, I'm worried about the programming.

Is the relay board pictured?
Just curious.

http://www.dhgate.com/product/new-5v-8-channel-relay-shield-for-arduino/114459520.html

jwallace15
31-07-2013, 16:21
One simple option for testing...

I'll look into that. My Dad won't be too thrilled because he worked for ages getting out old router to be a bridge (or something like that). But thanks for the option!

Is the relay board pictured? Just curious.

Judging by the URL it seems like it. That website is blocked on my computer under the category of "Ecommerce".

This is it: http://www.amazon.com/SainSmart-8-Channel-Relay-Module-Arduino/dp/B0057OC5WK

jwallace15
31-07-2013, 22:03
So you need to put something between your Arduino and that board if those numbers are even close to correct.

What sort of thing are you talking about? Resistor? Transistor? 1000µf capacitor?

(ok the capacitor was a joke but still, do you mean a transistor?)

I did notice when I first started using it that strange things would happen.. Such as when I'd try to close the circuit for all 8 relays that the LED's would dim and only 4 relays would click. I also had trouble with the digital input pins (I have emergency stop buttons on the control panels, and was trying to get it so that if the buttons were pressed it would turn on a relay that closed the circuit for a very bright red LED matrix to simulate a warning light) when the relay was activated.

I got my R3 from a kit off of Sparkfun (https://www.sparkfun.com/products/11576) and it included a toy motor to switched on by a transistor (but run off of the Arduino +5v output). It also had a temperature sensor. One day I was trying to simulate a thermostat by entering in a selected temperature into the Serial Monitor, and then if the current temperature was above the entered temperature it would turn on the motor. I'm not sure what happened but the temperature sensor started giving me bogus readings of 500+ degrees (it was not a programming error as I tested it with a code I had written before that worked fine). I think possibly I burnt out the sensor?

/tangent

Anyways, are you suggesting adding a transistor between the Arduino and the relay?

(and by the way for any of you wondering, "In that picture.. Is that an air pressure gauge on the left? And pneumatic tubing in the background?" well yes. I have pnuematics on my train set. Problem? ;) )

techhelpbb
31-07-2013, 22:07
What sort of thing are you talking about? Resistor? Transistor? 1000µf capacitor?

(ok the capacitor was a joke but still, do you mean a transistor?)

I did notice when I first started using it that strange things would happen.. Such as when I'd try to close the circuit for all 8 relays that the LED's would dim and only 4 relays would click. I also had trouble with the digital input pins (I have emergency stop buttons on the control panels, and was trying to get it so that if the buttons were pressed it would turn on a relay that closed the circuit for a very bright red LED matrix to simulate a warning light) when the relay was activated.

I got my R3 from a kit off of Sparkfun (https://www.sparkfun.com/products/11576) and it included a toy motor to switched on by a transistor (but run off of the Arduino +5v output). It also had a temperature sensor. One day I was trying to simulate a thermostat by entering in a selected temperature into the Serial Monitor, and then if the current temperature was above the entered temperature it would turn on the motor. I'm not sure what happened but the temperature sensor started giving me bogus readings of 500+ degrees (it was not a programming error as I tested it with a code I had written before that worked fine). I think possibly I burnt out the sensor?

/tangent

Anyways, are you suggesting adding a transistor between the Arduino and the relay?

Sorry I am quite tired.
I deleted my post above because it was going off on a tangent of it's own.

http://www.amazon.com/SainSmart-8-Ch.../dp/B0057OC5WK
The PCB layout image at your Amazon link says something like:

Input control signal LOW state current:
2.5V at 0.1mA
3.3V at 0.18mA
5V at 0.35mA

The Arduino use Atmel AVR MCU and they can sink and source a maximum of 40mA per I/O and generally a chip total of 200mA.
Look at the specification sheets for the Atmel AVR chips in question and this link:
http://forums.adafruit.com/viewtopic.php?f=24&t=17802

Here's the thing....it seems unlikely that board uses so little control current as it appears that the input goes through a resistor into the opto-isolator if you look at the blurry schematic.

From the pictures that board appears to have 817C opto-isolators (the close up shows B1312 and 817C).
The datasheet for that is likely here:
http://www.futurlec.com/LED/PC817.shtml

That part lists 50mA maximum forward current and is setup for a nominal 20mA current.

I suspect having thought about this that the numbers as shown on the layout provided are wrong.
How does one operate a 20mA LED with 20x less current and expect that to work?
So either I am wrong and those transistors are the buffer or there is no buffer and those specifications are wrong.

1. Wire that thing up.
2. Disconnect the Arduino.
3. Take a DC ammeter or a suitably configured DMM and measure the current when you close the circuit between one control input pin and the system ground.

If that current exceeds 30mA you do not want to drive it with the Arduino directly.
I suspect the inputs source more than that which is why the reviewers are complaining they can only turn on 5 with the Raspberry Pi.

The safe bet here, given how easy it is to test, is to test this.
If the measured current exceeds say 30mA greatly then drive the 8 relays with a ULN2803 (8 Darlington transistors) or 8 discrete transistors. Just remember to account for the junction voltage drops.
If the measured current is between 30mA and 40mA look at the TTL 7407 or 7417 chips.
Just keep in mind that TTL 7417s are rarely available from any company except Texas Instruments.
7407, 74LS07 and even 74HC07 (open-drain CMOS equivalent) are a bit easier to find these days.
If the measured current is around 20mA or less then it should be fine but just remember 20mA x 8 circuits = 160mA.
If you make all 8 Arduino outputs low then that 160mA will consume a large portion of total maximum drive the chip can handle. So be careful about what, besides that board, you put on there while it's like that.
If the potential for 160mA concerns you, then again, look at the 7407 because that will dramatically reduce the current demand on the Arduino (roughly 1/60 the current for all 8 circuits).

BornaE
01-08-2013, 02:37
Back to the code, what do you get printed on the serial port when you press the buttons?

jwallace15
01-08-2013, 11:08
Back to the code, what do you get printed on the serial port when you press the buttons?

Allow me to test (it did say something I just can't remember)

...

Alright testing now.

Accessed the webpage, serial printed...


HTTP
favicon.i,,

Pressing "On"

Prints the same. No LED.

Pressing "Off"

Same thing. And no LED.

When I press the buttons, the TX and RX leds blink on both the ethernet shield and the R3, and an LED I connected to pin 13 (it is not in the code though, it's just there to show me if the Arduino LED blinks) gets a little bit brighter when the TX and RX leds blink.

techhelpbb
01-08-2013, 11:41
When I press the buttons, the TX and RX leds blink on both the ethernet shield and the R3, and an LED I connected to pin 13 (it is not in the code though, it's just there to show me if the Arduino LED blinks) gets a little bit brighter when the TX and RX leds blink.

What are you powering this assembly with?
What voltage and current is the power source rated for?
Are you using the USB port for power?

The potential code issues aside make sure that you are not fooling yourself by powering that assembly with a power source that is not sufficient.

jwallace15
01-08-2013, 11:46
What are you powering this assembly with?
What voltage and current is the power source rated for?
Are you using the USB port for power?

The potential code issues aside make sure that you are not fooling yourself by powering that assembly with a power source that is not sufficient.

It is powered over my USB port.

I know that it is sufficient, I recently made a sketch with my MEGA that had 15+ LED's that would scroll in a marquee and the delay could be adjusted from a trim pot (all the way down to a ~10ms delay).

I also ran a servo off of the mega while doing that, and 3 more trim pots that could adjust the colour of an RGB LED.

daniel_dsouza
01-08-2013, 12:14
Can you add some print statements after the conditional logic steps in your code, and tell us what they give you?

I wonder if favicon.i is an icon? I hope not, because that would not make any sense.

It's good to see another person that loves trains.

jwallace15
01-08-2013, 12:23
Can you add some print statements after the conditional logic steps in your code, and tell us what they give you?

I wonder if favicon.i is an icon? I hope not, because that would not make any sense.

Do you mean add like an if-then statement, as in if the On button is pressed, serial.print("The Led is on");

and say the led is off if the Off button is pressed?

EDIT: ^ I added that sort of statement and when I press either the on of off buttons nothing is printed.

It's good to see another person that loves trains.

:D

http://www.chiefdelphi.com/forums/attachment.php?attachmentid=12959&d=1346106255 (as of last year. Much has changed since then. MUCH.)

techhelpbb
01-08-2013, 14:31
I put my Arduino Ethernet Shield R3 onto my Arduino Duo R3.

I cut a network cable in half.
Made an ethernet 'cross-over cable' like so:
Orange/White (one half) - Green/White (the other half)
White/Orange (one half) - White/Green (the other half)
Vice-versa
I used Scotch Tape as an insulator after twisting wires together.
MacGyvering during lunch....check.
Good thing that was a high quality dollar store cable ($1.34).

I put my 'cross-over cable' into my laptop (Dell E6400...yes I have several laptops) ethernet port.
I put the other end into the Arduino Ethernet Shield.

I disabled IPV6 (blah) on my laptop wired ethernet interface.
Set my wired connection in Windows 7 to: 192.168.1.131
Looked at the supplied code and it uses: 192.168.1.130
Set the gateway as: 192.168.1.1
Set the netmask to: 255.255.255.0

Loaded up your stored page in Firefox.
Regardless of what webpage button I press (On/Off) I get "HTTP" out the serial monitor.

When I get a chance I'll check the output pins.

However I do not get this:



HTTP
favicon.i,,


Care to clarify if you are using Internet Exploder....I mean Internet Explorer :)

I have version 1.05 stable of the Arduino software.

jwallace15
01-08-2013, 14:58
Care to clarify if you are using Internet Exploder....I mean Internet Explorer :)

Nope, Chrome. I openly admitted to using IE at robotics last year and recieved a major lashing for such blasphemy. Then I downloaded Chrome.

techhelpbb
01-08-2013, 15:42
I only get the 'favicon.i' if the serial monitor is open when the board first connects. Other than that just "HTTP" out of the serial monitor.

It did not appear on my DMM that either pin 7 or 8 was toggling with the webpage button presses (not sure if it's one or zero oriented).

Will look into it more later.

What I suspect is wrong here is that:

1. If you look there is only one call to serial to output from this code.
2. What you should see is what is in the buffer.
3. When you alter the form it fires a POST event.
4. That should cause the page to reload (with the same content).
5. During that post event parameters follow.
6. We both only see "HTTP".
7. However this is a POST so look at this link:
http://www.jmarshall.com/easy/http/#postmethod
(Link altered to something more related and friendly)
8. Therefore when the code reloads and tries to parse these parameters...it can not find what is not in the buffer.
9. Therefore the page simply reloads but does not change the pins (it thinks it's the first time you loaded it).
10. This *might* have worked for someone at some point but this is likely time sensitive.
11. The browser is doing all the work to display the HTML form.
12. When the browser toggles something it's just a silly drawing to the browser.
13. Even if this was a slider (it's a button) it would likely slide as you might expect.
14. Even if the browser does not successfully communicate the change it will tend to draw the changes.
15. HTTP is stateless so unless you put something more intelligent like Javascript in there you can't ask the browser after the fact what happened without another HTML form submission.
16. If your HTML forms never send valid data you are trapped in a vicious loop where things *appear* to be happening.

This is a typical problem for web applications of any sort.
Often form submissions recall the same code and that code needs to get parameters (either GET or POST).
If that code does not get parameters HTTP is stateless so it thinks you were *never there before*.

So since I am not the student here :)
Put a serial print statement *inside* the conditional that toggles the pin.
See if it ever prints.
You sort of did this already above just put *only* the print statement not any additional conditionals.

Then we can go from there.

BTW when was this book you have written? Look at the copyright date.
It's this book right: http://shop.oreilly.com/product/9780596802486.do

Whistles innocently:
https://bugzilla.mozilla.org/show_bug.cgi?id=260500

jwallace15
01-08-2013, 17:53
BTW when was this book you have written? Look at the copyright date.
It's this book right: http://shop.oreilly.com/product/9780596802486.do


No, it is the second edition; http://shop.oreilly.com/product/0636920022244.do

techhelpbb
01-08-2013, 17:58
No, it is the second edition

Try my suggestion above.

In the conditional already in the example code just try to print anything out the serial port.

Things change and when someone writes a *tiny* webserver they sometimes forget that they control the part they write. They do not control the browser part that is written by someone to whom they have no immediate contact.

So let's think about this:
What happens when the browser part does something different then it did before? How does the example written in a hard copy book evolve when the authors and editors of the book can't predict the future? It doesn't.

This code is obsolete (for people with current browsers) but it's actually not terribly hard to fix it.

So let's do this step by step. Start with my request above. Tell us if you ever see that line print.

jwallace15
01-08-2013, 18:27
So in the code line...


while(client.findUntil("PinD", "\n\r"))
{
int val = client.parseInt();
pinMode(8, OUTPUT);
digitalWrite(8, val);
}


Add...


while(client.findUntil("PinD", "\n\r"))
{
int val = client.parseInt();
pinMode(8, OUTPUT);
digitalWrite(8, val);
if(val == 1)
{
Serial.print("The LED is on")
}
else
{
Serial.print("The LED is off")
}
}


?

techhelpbb
01-08-2013, 18:42
Somewhere you've lost a line...I highlighted it red.
The line you want to add is shown in green.


if(strcmp(buffer,"POST ") == 0)
{
client.find("\n\r");
while(client.findUntil("PinD", "\n\r"))
{
int pin = client.parseInt();
int val = client.parseInt();
pinMode(pin, OUTPUT);
digitalWrite(pin, val);
Serial.println("I saw the POST and toggled the pin!")
}
}


Also I noticed you statically assigned the pin I think it best you start with the original unmodified code for this.
Just add the one green line to the original code.

Be back in 2 or so hours....gotta go to a MORT thing.....

jwallace15
01-08-2013, 19:37
Somewhere you've lost a line...I highlighted it red.
The line you want to add is shown in green.


if(strcmp(buffer,"POST ") == 0)
{
client.find("\n\r");
while(client.findUntil("PinD", "\n\r"))
{
int pin = client.parseInt();
int val = client.parseInt();
pinMode(pin, OUTPUT);
digitalWrite(pin, val);
Serial.println("I saw the POST and toggled the pin!")
}
}


Also I noticed you statically assigned the pin I think it best you start with the original unmodified code for this.
Just add the one green line to the original code.

Be back in 2 or so hours....gotta go to a MORT thing.....

Yeah, my bad. I modified the code either yesterday or the day before. I just hardcoded it so that it would digital write on pin 8 no matter what, so that if that was the problem.

Will do, and will post results.

techhelpbb
02-08-2013, 00:05
Make sure to put the semicolon at the end of the line I suggested you add.
Guess I nicked it off when I edited the color tags on my phone.

Something to think about as you work this out:


Press OFF button:

FireFox 19.02 Internet browser sends:
POST / HTTP/1.1
Host: 192.168.1.130
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:19.0) Gecko/20100101 Firefox/19.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.1.130/
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 7
pinD8=0

Arduino Replies:
HTTP/1.1 200 OK
Content-Type: text/html
HTML of web page follows.

Press ON button:

FireFox 19.02 Internet browser sends:
POST / HTTP/1.1
Host: 192.168.1.130
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:19.0) Gecko/20100101 Firefox/19.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.1.130/
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 7
pinD8=1

Arduino Replies:
HTTP/1.1 200 OK
Content-Type: text/html
HTML of webpage follows.


Captured with LiveHTTPHeaders Add-on for FireFox.
No sense in posting what the HTML looks like here.
It's in the code and major browsers will let you view that as source.

Take a good look at the code as supplied and picture what will happen when it reads that.

As of last night around midnight I had this code fixed and working as it was intended.
I just don't want to deprive anyone of the learning experience :)
If time is pressing let me know and I'll just send the fixed code to look at.

I wanted to address another statement previously made:

15 LEDs at 20mA each DC current limit.
Driven at 50% duty cycle PWM so you can 'dim' them.
Consume something like an average of 10mA.
If the PWM is sychronized to all 15 LEDs on actual outputs (so this assumes your Arduino has enough digital I/O for this).
Then that's 150mA.
If the PWM signals are 'out of phase' with each other then it's possible this could be as low as 75mA.
Let us assume the likely chance that it's 15 LEDs on 15 digial I/O at 75% duty cycle.
That would, at least to your eye, look like they are almost fully powered on.
So 15 LEDs are probably drawing close to 200mA out of the maximum typical drive of an Atmel AVR of 200mA.
Since R/C hobby servos are usually connected to another circuit or shield.
Since R/C hobby servos are often 6VDC for the motor which is a good reason for the additional circuit.
It's likely the R/C hobby servo control presents a simple 5V CMOS input to the Arduino.
Such an input draws a tiny current.
Usually around 0.1mA or even less.

So that means that you were hovering somewhere between 150mA and 201mA of total drive from the Atmel AVR with that setup.

So previously when it was suggested that an Arduino was able to power 15 LEDs and servos off the same board from a USB port that wasn't entirely a fair assesment of the actual total drive power being demanded of the Atmel AVR on the Arduino itself.

It seems unlikely that the servo power came from the USB port since they typically limit to 1A or even 500mA.

So again be very careful with this.

I can stack CMOS input shift registers on Arduino digital outputs.
Heck I can stack I2C/SPI port expanders and other Arduinos on the digital ouputs of a single Arduino.
So it is possible to have an enormous number of things controlled by a single Arduino.
*However* always consider just how much current as a whole that will demand of the Atmel AVR on the Arduino.
Device count alone can fool you easily.
It is the context that actually matters.

Also seeing as you've driven LEDs with PWM and know how to do that.
Did you know you can drive the opto-isolator LED with PWM?
The relay coil is really slow to respond.
So you can save digital I/O current by driving the LED in the opto-isolators with PWM.
Depends on how you do that.
You could drive half of the relays low.
Then the other half.
So you could reduce 160mA to drive that 8 relay board you have to something like 80mA.

jwallace15
06-08-2013, 14:41
Sorry it took so long, I've been too busy to toy with this issue.

I added the Serial.print function where you indicated

(if(strcmp(buffer,"POST ") == 0)
{
client.find("\n\r");
while(client.findUntil("PinD", "\n\r"))
{
int pin = client.parseInt();
int val = client.parseInt();
pinMode(pin, OUTPUT);
digitalWrite(pin, val);
Serial.println("I saw the POST and toggled the pin!")
}
}


It does not print "I saw the POST and toggled the pin!", it still prints the HTTP and favicon.i

Except it added one character;

HTTP
favicon.i¨

techhelpbb
06-08-2013, 14:47
It does not print "I saw the POST and toggled the pin!", it still prints the HTTP and favicon.i

Except it added one character;

HTTP
favicon.i¨


You would have gotten the extra character eventually it's a bit of junk from the fact that this code is parsing wrong.

You did not get the message because you never get to that part of the loop.

Look up at my last post.
It shows what my FireFox browser sends to the board.
Then look at the code you have.

Specifically look at the inner conditionals that mention POST.
Look before and look after that.

There are several things wrong there.

jwallace15
06-08-2013, 15:06
Look up at my last post.
It shows what my FireFox browser sends to the board.
Then look at the code you have.

Specifically look at the inner conditionals that mention POST.
Look before and look after that.

There are several things wrong there.

I'm not exactly sure what I'm looking for... Does it have to do with the way I used a " in the line

if(client.find("/"))


And in the next I used ' ?
Or how I added a space after POST in

if(strcmp(buffer,"POST ") == 0)


In that line should I change the 0 to a 1?

techhelpbb
06-08-2013, 15:10
Nope it's not a single versus double quotation issue.

The first thing a browser will send you after you click the button is the following text:
POST / HTTP/1.1

So remember the original code is trying to read what the browser sends and then act on that information. Plus the original code is obsolete.

So if you look for "/" first what will you find?
Now look at what it looks for next...

Remember each time the Atmel AVR MCU takes a character from the ethernet chip's buffer that character is no longer available in the ethernet chip to read again. So if you look for the "/" first. Will you ever find "POST"?

jwallace15
06-08-2013, 15:19
Wait, I think I'm understanding now. Are you saying change the order of the if statements? Take this one

if(client.find("/"))


And put it in the spot of this (and vice versa)?


if(strcmp(buffer,"POST ") == 0)

?
That way it looks for POST instead of the "/"?
Or add a new if statement for if(client.find"POST")?

techhelpbb
06-08-2013, 15:26
Do you really need to look for: /
Does your *non existent* file system have any subfolders or other pages?

Considering you know this is not going to be a full standards compliant webserver I submit to you that you do not need to look for anything other than POST.

The first time you load the page the browser will use GET anyway.

Now if you plan on actually parsing browser requests for several pages and returning error messages then yes at that point you should mind the: /

For now how about you just look for the "POST". It's handy the code example already shows you how.
Just get rid of the first conditional looking for the: /
Use the client.find as demonstrated in the example to look for: POST

Keep in mind that you'll loose that original serial debug when you do this because you should delete that as well.
So be prepared to not see the "HTTP" or the "favicon.i" in the serial monitor.
If you have not already: leave the serial debug line I offered above in your code.

Let us save 'strcmp' for discussions on buffer security issues. You do not need that for this purpose at all.

Also look at every occurance of 'PinD' you need them all to match when it comes to the case of the text.

jwallace15
06-08-2013, 17:47
I no longer see HTTP or favicon.i.

I commented out the line saying if(client.find"/").

Whenever I click a button on the webpage the LED still does not work. However, the serial monitor displays "POST" when I click either button, and then about a second later is displays "GET".

The "I saw the post and toggled the pin" still does not display though.

EDIT: I saw you said make sure the case of PinD matches everywhere and looked and saw it didn't everywhere. Now the debug line prints on the serial monitor (I saw the POST and toggled the pin!)

However, no LED.

ANOTHER EDIT: I forgot that I changed one of the lines to say;


client.println(" value='LOW'><input type='submit' value='On'/></form>");
client.println(" value='HIGH'><input type='submit' value='On'/></form>");


I changed it back to 0 and 1, and it finally worked!!!

techhelpbb
06-08-2013, 18:11
Fantastic

Post up your Arudino code because if you Google around you'll discover that this book and that example has had quite a few people scratching their heads.

Just remember: this is no Microsoft Internet Information Server or Apache web server. It is more like the old SitePlayer (only SitePlayer was a lot more polished):
http://www.netmedia.com/siteplayer/webserver/sp1.html

It has no SSL. It has no authentication as you are using it.
If the browsers change dramatically you will need to alter that code.
Make sure you test that with all the browsers you need to use it with.

jwallace15
06-08-2013, 18:31
Here is the final working code;


#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,1,130 };

const int MAX_PAGENAME_LEN = 8;
char buffer[MAX_PAGENAME_LEN+1];

EthernetServer server(80);

void setup()
{
Serial.begin(9600);
Ethernet.begin(mac, ip);
server.begin();
delay(2000);
}

void loop()
{
EthernetClient client = server.available();
if (client)
{
int type = 0;
while (client.connected())
{
if (client.available())
{
memset(buffer,0, sizeof(buffer));
//if(client.find("/"))
if(client.readBytesUntil('/', buffer,sizeof(buffer)))
{
Serial.println(buffer);
if(strcmp(buffer,"POST ") == 0)
{
client.find("\n\r");
while(client.findUntil("PinD", "\n\r"))
{
int pin = client.parseInt();
int val = client.parseInt();
pinMode(pin, OUTPUT);
digitalWrite(pin, val);
}
}
sendHeader(client,"Post example");
client.println("<h2>Click buttons to turn pin 8 on or off</h2>");
client.print(
"<form action='/' method='POST'><p><input type='hidden' name='PinD8'");
client.println(" value='0'><input type='submit' value='Off'/></form>");
client.print(
"<form action='/' method='POST'><p><input type='hidden' name='PinD8'");
client.println(" value='1'><input type='submit' value='On'/></form>");
client.println("</body></html>");
client.stop();
}
break;
}
}
delay(1);
client.stop();
}
}
void sendHeader(EthernetClient client, char *title)
{
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
client.print("<html><head><title>");
client.print(title);
client.println("</title><body>");
}

jwallace15
08-08-2013, 22:37
Alright, this thread will now derail from programming to electrical.

The relay board seems to not be functioning.

First I tried hooking up the output for a sole relay (with a transistor) on pin 8 to test it with the existing code posted above. No cigar. I flipped the direction of the transistor in hopes I placed it backwards. Nothing. (keep in mind the VCC and ground pins were indeed hooked up to the +5V and GND pins of the Arduino).

Then I tried hooking that relay's input pin directly to the Arduino's +5V pin (using the + on a breadboard). Nothing then, either.

I then proceeded to hook all of the inputs from the relay board to the +5V, and none of them worked.

(if needed, this is the link to the manufacturer's website and my product) (http://www.sainsmart.com/arduino-compatibles-1/relay/8-channel-dc-5v-relay-module-for-arduino-pic-arm-dsp-avr-msp430-ttl-logic.html)

techhelpbb
08-08-2013, 22:53
Then I tried hooking that relay's input pin directly to the Arduino's +5V pin (using the + on a breadboard). Nothing then, either.

I then proceeded to hook all of the inputs from the relay board to the +5V, and none of them worked.

(if needed, this is the link to the manufacturer's website and my product) (http://www.sainsmart.com/arduino-compatibles-1/relay/8-channel-dc-5v-relay-module-for-arduino-pic-arm-dsp-avr-msp430-ttl-logic.html)

System ground the input to turn it on. I will test in the morning.

Yes I quickly tested with DMM. Grounded input lights LED at input.
Testing with a 5V 3A supply reveals that ground on input energizes contact.
NPN transistor in photocoupler to NPN transistor on PCB with 500 Ohm resistor bias.

Input circuit is LED .... opto-isolator LED ... 1k resistor ... Vcc

I bought one cause I could :)

Watch the jumper in the lower left BTW.
JD-Vcc should be jumpered to Vcc.
Do not put the jumper between GND and Vcc (bad design makes you think that is a storage position).
I guess the plus side is that would be a wonderful place to put an emergency stop button.

Now that I actually have a unit to examine, all the numbers on the drawing and documentation at the Amazon link are wrong. There was no documentation with the board when I got it. The box contains no useful information.

R1, R3, R5, R7, R9, R11, (yes the next 2 are even I have no idea why), R12, R14 are all 1k Ohm on my board.
Make sure to measure yours to be sure.
That limits the current you must sink to turn on a relay to 2.5mA each.
So all 8 inputs activating relays will only sink 20mA.
They get away with this because of the amplifier at the output of the opto-isolator.
So this should operate just fine straight from the Arduino digital I/O pins.

With all the inconsistencies here be sure to check before you assume these boards are identical!

jwallace15
09-08-2013, 11:36
The resistors you mentioned were all about 990-995. Close enough.

I don't remember grounding the inputs when I tested it the first time. I will now add a 10K ohm resistor on all the inputs to ground.

(edit)

It's behaving very strangely. When I plugged it in, IN6 activated. All of the LED's on the board itself were lit, but IN6 fired. I went to post example and "turned the LED on". It turned off the IN2 (what pin 8 is hooked up to). Then I "turned the LED off and it fired IN2.

Oh, and the LED for IN1 no longer works. But I think I may have damaged it with a crowbar when I was trying to extract the nails holding it to my train table to bring it upstairs... :o but all of the other ones are intact. (Another Edit: actually I just looked at it again and how I extracted it, and I didn't use the crowbar on that nail, I pulled it off by accident.. But the LED looks flatter than the other 7 working ones.. not sure how it broke though)

techhelpbb
09-08-2013, 12:18
The resistors you mentioned were all about 990-995. Close enough.


+/-5% = 50 Ohms max from value of resistor for 1k Ohm resistor
Well within spec even if it was only 2%.


I don't remember grounding the inputs when I tested it the first time. I will now add a 10K ohm resistor on all the inputs to ground.


1. Take the relay board off the Arduino.
2. Provide the relay board 5V power.
3. Simply short any of the input pins to ground.

LED should light and relay should energize.


It's behaving very strangely. When I plugged it in, IN6 activated. All of the LED's on the board itself were lit, but IN6 fired. I went to post example and "turned the LED on". It turned off the IN2 (what pin 8 is hooked up to). Then I "turned the LED off and it fired IN2.

Oh, and the LED for IN1 no longer works. But I think I may have damaged it with a crowbar when I was trying to extract the nails holding it to my train table to bring it upstairs... :o but all of the other ones are intact. (Another Edit: actually I just looked at it again and how I extracted it, and I didn't use the crowbar on that nail, I pulled it off by accident.. But the LED looks flatter than the other 7 working ones.. not sure how it broke though)

This is not exactly a fine piece of engineering here LOL.
However I would advise not hitting it with a hammer - just yet :)

Follow my steps above.
Don't get ahead of yourself.
If the board is damaged you might need to do some repairs.

Once you get my suggestion above working...test all the relays.
Post back with the results.

jwallace15
09-08-2013, 12:26
All of them work when shorted to ground (did a continuity test just to double check). Except relay 1. But it isn't that big of a deal, I probably won't even need to use it. There's only about 4 things I want to control, my Dad just got the one with 8 relays just in case.

Now, should I just eliminate the 10K ohm resistors?

techhelpbb
09-08-2013, 12:29
All of them work when shorted to ground (did a continuity test just to double check). Except relay 1. But it isn't that big of a deal, I probably won't even need to use it. There's only about 4 things I want to control, my Dad just got the one with 8 relays just in case.

Now, should I just eliminate the 10K ohm resistors?

Here's what you should have:

>Vcc should be connected to a 5V power supply (not the Arduino power).
>Gnd should be connected to the same 5V power supply system ground and the Arduino ground.
>IN2-8 should be connected to whatever Arduino digital I/O you wish...directly.
>IN1 on your board is damaged do not connect it anywhere.
>You Arduino power input can be connected to the USB port for power or the relay board power supply (not the relay board but the same power source it gets power from), your choice.

Since the relay turns on when the digital I/O is driven to ground you probably want to reverse your code so 'On' is low and 'Off' is high.

jwallace15
09-08-2013, 12:35
For some reason IN6 is being written upon, but not entirely. The LED is lit, but the relay isn't thrown.

Edit: It isn't IN6, it's pin 4 on my arduino. It's producing about .18 to .2 volts.

Another Edit: Also, I added into the code on/off buttons for the 7 different relays. Now it can't process the request fast enough. In other words, I go to Post Example and don't get a response. The RX led on the ethernet shield blinks and the WLAN and Ethernet Port 1 LED's on my router/bridge blink (the ethernet shield is plugged into ethernet port 1). It doesn't work on Chrome or IE.

techhelpbb
09-08-2013, 12:57
For some reason IN6 is being written upon, but not entirely. The LED is lit, but the relay isn't thrown.

Edit: It isn't IN6, it's pin 4 on my arduino. It's producing about .18 to .2 volts.

Another Edit: Also, I added into the code on/off buttons for the 7 different relays. Now it can't process the request fast enough. In other words, I go to Post Example and don't get a response. The RX led on the ethernet shield blinks and the WLAN and Ethernet Port 1 LED's on my router/bridge blink (the ethernet shield is plugged into ethernet port 1). It doesn't work on Chrome or IE.

Start with what you know.
Then explore what you don't know.

Put the working example code you just had in your Arduino.
Then connect just one relay to the digital I/O pin 8.

Does that work?

jwallace15
09-08-2013, 13:08
Start with what you know.
Then explore what you don't know.

Put the working example code you just had in your Arduino.
Then connect just one relay to the digital I/O pin 8.

Does that work?

Yes, it works when I connect pin 8 to all of my relays.

techhelpbb
09-08-2013, 13:17
Yes, it works when I connect pin 8 to all of my relays.

I am curious if you mean that you connected pin 8 to all of your relays at the same time or just one at a time. However it doesn't really matter you could actually make that work with the boards you and I have.

The good news is that all except the first relay works and you can drive them properly.

The bad news is this is now a programming problem again :D
Post your altered code and let's see where the issue(s) are.

In the mean time, alter your working code to test each pin you want to use to drive relays one at a time. So change the 2 'PinD8' to for example 'PinD6'.

This will at least verify that there's no burnt out pins on your Arduino.
We know what the situation with the relay board is.

jwallace15
09-08-2013, 13:23
This is the altered code I wrote earlier that wouldn't load:


#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,1,130 };

const int MAX_PAGENAME_LEN = 8;
char buffer[MAX_PAGENAME_LEN+1];

EthernetServer server(80);

void setup()
{
Serial.begin(9600);
Ethernet.begin(mac, ip);
server.begin();
delay(2000);
}

void loop()
{
EthernetClient client = server.available();
if (client)
{
int type = 0;
while (client.connected())
{
if (client.available())
{
memset(buffer,0, sizeof(buffer));
//if(client.find("/"))
if(client.readBytesUntil('/', buffer,sizeof(buffer)))
{
Serial.println(buffer);
if(strcmp(buffer,"POST ") == 0)
{
client.find("\n\r");
while(client.findUntil("PinD", "\n\r"))
{
int pin = client.parseInt();
int val = client.parseInt();
pinMode(pin, OUTPUT);
digitalWrite(pin, val);
}
}
sendHeader(client,"Post example");
client.println("<h2>Click buttons to turn the relays on and off.</h2>");
client.print(
"<form action='/' method='POST'><p><input type='hidden' name='PinD9'");
client.println(" value='0'><input type='submit' value='Relay 2 on'/></form>");
client.print(
"<form action='/' method='POST'><p><input type='hidden' name='PinD9'");
client.println(" value='1'><input type='submit' value='Relay 2 off'/></form>");
client.print(
"<form action='/' method='POST'><p><input type='hidden' name='PinD8'");
client.println(" value='0'><input type='submit' value='Relay 3 on'/></form>");
client.print(
"<form action='/' method='POST'><p><input type='hidden' name='PinD8'");
client.println(" value='1'><input type='submit' value='Relay 3 off'/></form>");
client.print(
"<form action='/' method='POST'><p><input type='hidden' name='PinD7'");
client.println(" value='0'><input type='submit' value='Relay 4 on'/></form>");
client.print(
"<form action='/' method='POST'><p><input type='hidden' name='PinD7'");
client.println(" value='1'><input type='submit' value='Relay 4 off'/></form>");
client.print(
"<form action='/' method='POST'><p><input type='hidden' name='PinD6'");
client.println(" value='0'><input type='submit' value='Relay 5 on'/></form>");
client.print(
"<form action='/' method='POST'><p><input type='hidden' name='PinD6'");
client.println(" value='1'><input type='submit' value='Relay 5 off'/></form>");
client.print(
"<form action='/' method='POST'><p><input type='hidden' name='PinD5'");
client.println(" value='0'><input type='submit' value='Relay 6 on'/></form>");
client.print(
"<form action='/' method='POST'><p><input type='hidden' name='PinD5'");
client.println(" value='1'><input type='submit' value='Relay 6 off'/></form>");
client.print(
"<form action='/' method='POST'><p><input type='hidden' name='PinD3'");
client.println(" value='0'><input type='submit' value='Relay 7 on'/></form>");
client.print(
"<form action='/' method='POST'><p><input type='hidden' name='PinD3'");
client.println(" value='1'><input type='submit' value='Relay 7 off'/></form>");
client.print(
"<form action='/' method='POST'><p><input type='hidden' name='PinD2'");
client.println(" value='0'><input type='submit' value='Relay 8 on'/></form>");
client.print(
"<form action='/' method='POST'><p><input type='hidden' name='PinD2'");
client.println(" value='1'><input type='submit' value='Relay 8 off'/></form>");
client.println("</body></html>");
client.stop();
}
break;
}
}
delay(1);
client.stop();
}
}
void sendHeader(EthernetClient client, char *title)
{
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println();
client.print("<html><head><title>");
client.print(title);
client.println("</title><body>");
}


I will now test each pin like you said.

I tried deleting all of the lines except for one input/output line and it didn't load. Then I switched back to the original working code that I posted on page 3 and it doesn't work either.

I went into CMD and entered "ping 192.168.1.130" and the request timed out. None of the pings made it back to CMD.

techhelpbb
09-08-2013, 13:37
I tried deleting all of the lines except for one input/output line and it didn't load. Then I switched back to the original working code that I posted on page 3 and it doesn't work either.

I went into CMD and entered "ping 192.168.1.130" and the request timed out. None of the pings made it back to CMD.

Turn off the Arduino system.
Turn it back on.
Load the original working code.
Turn off the Arduino system.
Turn it back on.

Try that?

Also if you put an microSD card in the socket remove it.
Your example was written on an older shield that did not have the reader.
If you put a card in the reader it might lock the ethernet interface on you.

jwallace15
09-08-2013, 13:55
My ethernet shield is made by sainsmart as well, and the chip on it gets very hot, so I turned it off in hopes that it simply overheated.

Turning it back on now, along with the router/bridge.

Pinged it, and the Arduino replied with all 4 pings.

Now testing the outputs.

The issue with pin 4? When I tested it the LED was lit. Then I turned it on in post example and it lit and the relay fired. When I pressed off the voltage went to 0 instead of hovering around .19. Correction: It still does it.

techhelpbb
09-08-2013, 13:58
My ethernet shield is made by sainsmart as well, and the chip on it gets very hot, so I turned it off in hopes that it simply overheated.


Are you saying that pin 4 on your Arduino does or does not work?

Frankly I would avoid using pin 4.
That pin on the Arduino shield with the microSD card reader could shut down your ethernet interface.

jwallace15
09-08-2013, 14:09
All of the pins are fine except pin 4. Now for the code...

techhelpbb
09-08-2013, 14:18
All of the pins are fine except pin 4. Now for the code...

I just looked at the SainSmart Ethernet Shield schematic and compared it to the Arduino R3 Ethernet Shield schematic. Pin 4 (Pin 0 is the first) is the chip select for the microSD card on both schematics. It doesn't help that on the schematics they start numbering the pins at 1 but on the boards they start numbering the pins at 0. On a Seeed older revision ethernet shield without the microSD interface you can probably use pin 4. Also note that on the Arduino Ethernet Shield pin 4 is actually labeled on the silk screen as SDCS where as on the images of the SainSmart shield I found there is no label warning the end user.

Don't use pin 4 with either shield. You risk sending select to the microSD card and disabling your network interface.

Still the interface shouldn't get hot...maybe a bit warm...so let's continue.

jwallace15
09-08-2013, 14:21
Ok. Will not use pin 4.

I don't use a Micro SD card in the ethernet shield anyway.

Back to the programming. I don't see what is wrong with it, in the book it said adding another line with the same code (just a different D#) would work.

Edit: I think I know what I did wrong. I didn't copy a line saying "client.print" on accident.

Yes, that was the problem.

techhelpbb
09-08-2013, 14:28
Yes, that was the problem.

Sounds like you got it working.