Sloppy I'm sure, but ALMOST working!

So, I have been going through as many tutorials as I can manage in the free time I can scrounge up, and I have hit a small roadblock in my progress.

The IDE is having problems with my shiftout lines, and I am not sure how to fix it.

If you are curious- this program listens to packets sent over wifi from my iPad, reads them, then runs specific pumps to dispense booze. At least, that's what I WANT to happen. All the communication stuff works fine... until I try to send out data through a couple shift registers...

Any suggestions?

Here is the code:

#include <SPI.h>         // for Arduino later than ver 0018
#include <EthernetUdp.h>   // UDP library from bjoern@cs.stanford.edu
#include <Ethernet.h>

                       
//////////  NETWORK INFO  ////////////////

byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0xDB, 0x50 };  //Set your Ethernet Shield's MAC address here - make sure you replace the ZZs with your shield's values!
byte ip[] = { 192, 168, 1, 5 };    // Set your shield's desired IP address here - check your network for configuration detail
unsigned int localPort = 7777;      // local port to listen on (set this the same as Port # on Ardumote Params Screen)
IPAddress iPhoneIP(192, 168, 2, 3);  //Set the iPhone/iPod/iPad's IP address to send messages back to Ardumote...
unsigned int iPhonePort = 7777;      //Set the Port # of the message table you configured in Ardumote (default is 7777)...


///////// Pin Assignments /////////////////


int data = 2;     //Begin Shift register integers
int clock = 3;
int latch = 4;
int ledState = 0;
const int ON = HIGH;
const int OFF = LOW;   //end shift register integers

//begin drink integers

byte vodka1st = 0x1;
byte vodka2nd = 0x0;
byte rumlt1st = 0x2;
byte rumlt2nd = 0x0;
byte tequila1st = 0x4;
byte tequila2nd = 0x0;
byte whiskey1st = 0x8;
byte whiskey2nd = 0x0;
byte gin1st = 0x10;
byte gin2nd = 0x0;
byte amarretto1st = 0x20;
byte amarretto2nd = 0x0;
byte tripsec1st = 0x40;
byte tripsec2nd = 0x0;
byte kahlua1st = 0x80;
byte kahlua2nd = 0x0;
byte midouri1st = 0x0;
byte midouri2nd = 0x1;
byte brandy1st = 0x0;
byte brandy2nd = 0x2;
byte vermouth1st = 0x0;
byte vermouth2nd = 0x4;
byte cran1st = 0x0;
byte cran2nd = 0x8;
byte sour1st = 0x0;
byte sour2nd = 0x10;
byte cola1st = 0x0;
byte cola2nd = 0x20;
byte tonic1st = 0x0;
byte tonic2nd = 0x40;
byte grenad1st = 0x0;
byte granad2nd = 0x80;
byte orange1st = 0;
byte orange2nd = 0;
byte pine1st = 0;
byte pine2nd = 0;
byte syrup1st = 0;
byte syrup2nd = 0;
byte rumdk1st = 0;
byte rumdk2nd = 0;
byte sprite1st = 0;
byte sprite2nd = 0;
byte ginger1st = 0;
byte ginger2nd = 0;
byte water1st = 0;
byte water2nd = 0;
byte motorsoff = 0x0;




///////////////// UDP Variables  ////////////////// 

// buffers for receiving and sending data
char packBuff[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,

/////////////////////////////////////////////////



EthernetUDP Udp;

void setup()  {
  //start the Ethernet and UDP:
  Ethernet.begin(mac,ip);
  Udp.begin(localPort);  // Setup UDP on port defined earlier
  Serial.begin(9600);    // Start serial com @ 9600 bps (baud)
    
    //  set pins for shift register
  pinMode(data, OUTPUT);  //begin shift register pinmodes
  pinMode(clock, OUTPUT);
  pinMode(clock, OUTPUT);  //end shift register pinmodes
  
}

void loop()  {
  //int pwmVal;  //integer holding the PWM values for later use NOT NEEDED!!
               //  the following looks for a packet and then reads it and prints it after subtracting 8
  int packetSize = Udp.parsePacket();  //  note that this includes the UDP header
  if(packetSize)  {               //if a packet is there...
    packetSize = packetSize - 8;  //subtract the 8 byte header
    Serial.print("Packet size: ");
    Serial.println(packetSize);  //  ... and then print it to the monitor
    
              //  the following will read the packet into packetBuffer and get the senders IP addr and port number
    Udp.read(packBuff,UDP_TX_PACKET_MAX_SIZE);
    Serial.println("Message: ");
    Serial.println(packBuff);

//////////////////////// PWM Assignments DELETED! /////////////////////////////////////  
  

if (packBuff[0]== 'G' && packBuff[1]=='B' && packBuff[2]=='D' && packBuff[3]=='L');
{
  digitalWrite(latch, 0);
  shiftOut(data, clock, vodka1st);  // it has a big problem with all my shiftout lines
  shiftOut(data, clock, vodka2nd);
  digitalWrite(latch, 1);
  delay(3000);
  digitalWrite(latch, 0);
  shiftOut(data, clock, motorsoff);
  shiftOut(data, clock, motorsoff);
  digitalWrite(latch, 1);
  
      Udp.beginPacket(iPhoneIP,iPhonePort);
      Udp.write("Vodka poured");    // Send Message back to iPhone
      Udp.endPacket();
    }
  }

delay(20);
}
void updateLEDs(int value)
{
  digitalWrite(latch, LOW);               // set latch low
  shiftOut(data, clock, MSBFIRST, value);
  digitalWrite(latch, HIGH);              //  reset latch back to high
}

Please don't blast me too bad... I'm doing my best!

EDIT: The IDE lists "/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/Arduino.h: In function 'void loop()':
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/Arduino.h:111: error: too few arguments to function 'void shiftOut(uint8_t, uint8_t, uint8_t, uint8_t)'
barbotgroundup:122: error: at this point in file
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/Arduino.h:111: error: too few arguments to function 'void shiftOut(uint8_t, uint8_t, uint8_t, uint8_t)'
barbotgroundup:123: error: at this point in file
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/Arduino.h:111: error: too few arguments to function 'void shiftOut(uint8_t, uint8_t, uint8_t, uint8_t)'
barbotgroundup:127: error: at this point in file
/Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/cores/arduino/Arduino.h:111: error: too few arguments to function 'void shiftOut(uint8_t, uint8_t, uint8_t, uint8_t)'
barbotgroundup:128: error: at this point in file "

as the errors. Ew, right?

This is the expected format:

shiftOut(data, clock, MSBFIRST, value);

You have
shiftOut(data, clock, vodka1st);

Notice what's missing? Easy to fix anyway.

Vodka ... problems.

I see the problem here. :wink:

You could use SPI.transfer to quickly shift out 8 bits.

SPI.transfer() is my preferred choice.
Building up some of my 12-shift register boards to drive 5x20 LED display. All LEDs current-sunk individually for max brightness - no multiplexing!

SPI.transfer is something I am not yet familiar with...

but MSBFIRST - Oh yeah! I forgot all about that!

Thanks for the help guys! (I'll have to read up on SPI.transfer soon!)

Hey, one more question:

Why does my shift register seem to light up four LEDs on my second shift register whenever no input is coming in? When the iPad sends "GBDL" the single LED lights (which corresponds to where the pump's transistor will sit), but after that code runs, the four other LEDs relight... and I don't know why. I thought the code lines

byte motorsoff = 0x0;

and

  digitalWrite(latch, 0);
  shiftOut(data, clock, MSBFIRST, motorsoff);
  shiftOut(data, clock, MSBFIRST, motorsoff);
  digitalWrite(latch, 1);

would've shut all the shift register pins to 0? I wonder why it's not?

Jim_Socks:
Why does my shift register seem to light up four LEDs on my second shift register whenever no input is coming in?

Decoupling capacitors?

I am using two daisy chained 74HC595 shift registers, with a 0.1uF cap at both of their latch pins (I read somewhere that that will even out "jitter", but I have tried it with and without them and haven't noticed a difference...)

For now what I've done is use another two arduino pins to control the "Output Enable" pins on the registers, so that they aren't able to put out any power when they aren't receiving instructions from the iPad.

byte vodka1st = 0x1;
byte vodka2nd = 0x0;
byte motorsoff = 0x0;
if (packBuff[0]== 'G' && packBuff[1]=='B' && packBuff[2]=='D' && packBuff[3]=='L');
{
  digitalWrite(OE2, LOW);  //enable the second shift register to output power
  digitalWrite(latch, 0);
  shiftOut(data, clock,MSBFIRST, vodka1st);  // it seems to not care what HEX code I use here- it just lights the same damn LED no matter what.  WTF?
  shiftOut(data, clock, MSBFIRST, vodka2nd);
  digitalWrite(latch, 1);
  delay(3000);
  digitalWrite(latch, 0);
  shiftOut(data, clock, MSBFIRST, motorsoff);  //  while I THOUGHT this would take all outputs to zero... it doesn't for some reason, so it's useless.  
  shiftOut(data, clock, MSBFIRST, motorsoff);  //  WHY isn't the arduino understanding my HEX values!?
  digitalWrite(latch, 1);
  digitalWrite(OE2, HIGH);  //  un-enable the second shift register to output power

  
  
  
      Udp.beginPacket(iPhoneIP,iPhonePort);
      Udp.write("Vodka poured");    // Send Message back to iPhone
      Udp.endPacket();
    }
  }

...So I still have bugs to work out. Additionally, I haven't gotten rid of the problem of arbitrary LEDs lighting when the program is idle... I have just masked it by turning off the output enable. If I pull the jumper to OE, making it LOW again- all those arbitrary LEDs just light back up.

This has ALSO created a new issue:
All 8 LEDs on the second shift register are receiving a TINY bit of power when the program is idle- even with the Output Enable turned off! They all glow ever-so-slightly. The 1st shift register does not have this, and is set up the same way. I am scratching my head on this one. (I do notice that when I get my fingers near the second shift register, it sometimes makes the lights flicker due to my bodies electro-magnetic field or whatever it's called, but I think these things are un-related)

EDIT: pasted wrong code section. Fixed now.

DO NOT PUT CAPS ON SIGNAL PINS!! That will only end up damaging Arduino output pins.

The only cap should be a 0.1uF cap from the 5v pin to Gnd.

OutputEnable Low turns ON the output drivers. Driving it High turns OFF the output drivers.

Do you have MasterClear connected to +5V?

If anything, I woulld do this:
OE, HIGH - turn off output drive
Latchpin, LOW
Shiftout()
shiftout()
Latchpin, HIGH
OE, LOW - turn on output drive

If waving your fingers around makes stuff happen, then you have unconnected control signals. Get them connected.

Jim_Socks:
This has ALSO created a new issue:
All 8 LEDs on the second shift register are receiving a TINY bit of power when the program is idle- even with the Output Enable turned off! They all glow ever-so-slightly. The 1st shift register does not have this, and is set up the same way.

I'd like to see your wiring. None of this should happen.

I have four shift registers set up here, and things don't go wrong. Note however the decoupling caps (blue) on the Vcc to Gnd spots next to each chip.

Hmm,

if you don't mind Sir- can you explain the aforementioned (and pictured) blue capacitors used for "decoupling"?

What does it actually do? (so I can apply the knowledge usefully)

Where in the chain do they need to sit? (it's difficult to see in your photo... kinda)

What size caps are OK to use for this purpose? (just some good useable gee-whiz info for me)

Sorry for being so dumb on the subject!

This explains the theory:

http://www.thebox.myzen.co.uk/Tutorial/De-coupling.html

The caps were between the +5V (Vcc) and Gnd, and installed in multiple places. Really they should be near the power-in (+5V) of each chip which is more-or-less where I have them. They smooth out any spikes introduced by chip operation which might cause it or other chips to malfunction.

As for the value, I am using 0.1 uF which appears to be what is generally used in these cases.

Sorry it is taking me so long to reply- I just got back from a business trip. I read up from the link you posted about the caps, and followed your guidance about where to place them. They are now just before each register between positive and negative.

Here are a couple pictures of my wiring:

and

It's not as easy to see as yours by any means...

I have Master Reclear sent to pins 3 and 2 of the arduino for each chip
I have Output Enable sent to pins 9 and 10 of the arduino for each chip
I have the latch on 8, data on 11, and clock on 12

I have no un-connected leads anywhere... Yet even with Output enable set HIGH a teeeny amount of power is hitting the second register's LEDs... they glow ever-so-slightly. The only time I can get them to stop glowing is when I send them a command like "light LED 12 for three seconds!" then they all stop glowing, LED 12 lights up bright, and after three seconds when it shuts off they all begin to slightly glow again. Very frustrating... and I cannot figure out the cause!

Let me know if you would like to see an up-to-date version of my code.

Please help if you are able :slight_smile:

Yes let's see the latest code.

On the Uno, the ethernet sheild uses pins 10,11,12 for SPI communication between the Ethernet chip and the arduino which means you won't be able to use your shift registers at the same time as the ethernet sheild unless you change which pins you are using (e.g. 5,6,7 rather than 10,11,12).

Tom:

OOOooooOOOHHhhHH! Holy cow that could be the source of all my issues! I'll change them right away and see what happens!

Nick:

here is the lastest code (well, before I change these pin assignments anyway):

#include <SPI.h> // for Arduino later than ver 0018
#include <EthernetUdp.h> // UDP library from bjoern@cs.stanford.edu
#include <Ethernet.h>

////////// NETWORK INFO ////////////////

byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0xDB, 0x50 }; //Set your Ethernet Shield's MAC address here - make sure you replace the ZZs with your shield's values!
byte ip[] = { 192, 168, 1, 5 }; // Set your shield's desired IP address here - check your network for configuration detail
unsigned int localPort = 7777; // local port to listen on (set this the same as Port # on Ardumote Params Screen)
IPAddress iPhoneIP(192, 168, 2, 3); //Set the iPhone/iPod/iPad's IP address to send messages back to Ardumote...
unsigned int iPhonePort = 7777; //Set the Port # of the message table you configured in Ardumote (default is 7777)...

///////// Pin Assignments /////////////////

int data = 11; //Begin Shift register integers
int clock = 12;
int latch = 8;
int ledState = 0;
int OE1 = 9;
int OE2 = 10;
int MR1 = 3;
int MR2 = 2;
const int ON = HIGH;
const int OFF = LOW; //end shift register integers

//begin drink integers

byte vodka1st = 0x1;
byte vodka2nd = 0x8;
byte motorsoff = 0x0;

///////////////// UDP Variables //////////////////

// buffers for receiving and sending data
char packBuff[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,

/////////////////////////////////////////////////

EthernetUDP Udp;

void setup() {
//start the Ethernet and UDP:
Ethernet.begin(mac,ip);
Udp.begin(localPort); // Setup UDP on port defined earlier
Serial.begin(9600); // Start serial com @ 9600 bps (baud)

// set pins for shift register
pinMode(data, OUTPUT); //begin shift register pinmodes
pinMode(clock, OUTPUT);
pinMode(latch, OUTPUT);
pinMode(OE1, OUTPUT);
pinMode(OE2, OUTPUT);
pinMode(MR1, OUTPUT);
pinMode(MR2, OUTPUT);//end shift register pinmodes

digitalWrite(OE1, LOW);
digitalWrite(OE2, LOW);
digitalWrite(MR1, HIGH);
digitalWrite(MR2, HIGH);

digitalWrite(latch, 0);
shiftOut(data, clock, MSBFIRST, motorsoff); // while I THOUGHT this would take all outputs to zero... it doesn't for some reason, so it's useless.
shiftOut(data, clock, MSBFIRST, motorsoff); // WHY isn't the arduino understanding my HEX values!?
digitalWrite(latch, 1);
digitalWrite(OE1, HIGH);
digitalWrite(OE2, HIGH);

}

void loop() {
//int pwmVal; //integer holding the PWM values for later use NOT NEEDED!!
// the following looks for a packet and then reads it and prints it after subtracting 8
int packetSize = Udp.parsePacket(); // note that this includes the UDP header
if(packetSize) { //if a packet is there...
packetSize = packetSize - 8; //subtract the 8 byte header
Serial.print("Packet size: ");
Serial.println(packetSize); // ... and then print it to the monitor

// the following will read the packet into packetBuffer and get the senders IP addr and port number
Udp.read(packBuff,UDP_TX_PACKET_MAX_SIZE);
Serial.println("Message: ");
Serial.println(packBuff);

//////////////////////// PWM Assignments DELETED! /////////////////////////////////////

if (packBuff[0]== 'G' && packBuff[1]=='B' && packBuff[2]=='D' && packBuff[3]=='L'); // If the message sent from my iphone = "GBDL", then run the following script, which should pour vodka for 3 seconds. NOTE: I am using LEDs as proof of concept right now- later these will be relays.
{
digitalWrite(MR2, HIGH);
digitalWrite(OE2, LOW); //enable the second shift register to output power
digitalWrite(latch, 0);
shiftOut(data, clock,MSBFIRST, vodka1st); // it seems to not care what HEX code I use here- it just lights the same damn LED no matter what. WTF?
shiftOut(data, clock, MSBFIRST, vodka2nd);
digitalWrite(latch, 1);
delay(3000);
digitalWrite(latch, 0);
shiftOut(data, clock, MSBFIRST, motorsoff); // while I THOUGHT this would take all outputs to zero... it doesn't for some reason, so it's useless.
shiftOut(data, clock, MSBFIRST, motorsoff); // WHY isn't the arduino understanding my HEX values!?
digitalWrite(latch, 1);
digitalWrite(OE2, HIGH); // un-enable the second shift register to output power
digitalWrite(MR2, LOW);
digitalWrite(MR2, HIGH);

Udp.beginPacket(iPhoneIP,iPhonePort);
Udp.write("Vodka poured"); // Send Message back to iPhone
Udp.endPacket();
}
}

delay(20);
}

Tom you hit the nail right on the head! NO more slightly lit LEDs for apparently no reason, NO more flickering, NO more arbitrary LEDs lighting!

Woo- HOO!

I completely didn't realize the shield used those pins! THANKS SO MUCH! Mystery problem #25- SOLVED!

Now on to mystery problem # 26:

My goal here is to get the arduino to read a packet of information from my iphone, and take action based on what it reads. In my code as it stands right NOW, I want it to read the packet, and if it reads "GBLD" I want it to pour my three second glass of vodka. If it DOESNT read "GBLD" I don't want it to do anything at all. I thought my code had this down... but apparently not. The arduino pours the vodka upon seeing ANY packet of information, not matter what it says! Any ideas?

Here is the specific area of code:

void loop() {

// the following looks for a packet and then reads it and prints it after subtracting 8
int packetSize = Udp.parsePacket(); // note that this includes the UDP header
if(packetSize) { //if a packet is there...
packetSize = packetSize - 8; //subtract the 8 byte header
Serial.print("Packet size: ");
Serial.println(packetSize); // ... and then print it to the monitor

// the following will read the packet into packetBuffer and get the senders IP addr and port number
Udp.read(packBuff,UDP_TX_PACKET_MAX_SIZE);
Serial.println("Message: ");
Serial.println(packBuff);

if (packBuff[0]== 'G' && packBuff[1]=='B' && packBuff[2]=='D' && packBuff[3]=='L'); // If the message sent from my iphone = "GBDL", then run the following script, which should pour vodka for 3 seconds. NOTE: I am using LEDs as proof of concept right now- later these will be relays.
{
digitalWrite(MR2, HIGH);
digitalWrite(OE2, LOW); //enable the second shift register to output power
digitalWrite(latch, 0);
shiftOut(data, clock,MSBFIRST, vodka1st);
shiftOut(data, clock, MSBFIRST, vodka2nd);
digitalWrite(latch, 1);
delay(3000);
digitalWrite(latch, 0);
shiftOut(data, clock, MSBFIRST, motorsoff);
shiftOut(data, clock, MSBFIRST, motorsoff);
digitalWrite(latch, 1);
digitalWrite(OE2, HIGH); // un-enable the second shift register to output power
digitalWrite(MR2, LOW);
digitalWrite(MR2, HIGH);

Udp.beginPacket(iPhoneIP,iPhonePort);
Udp.write("Vodka poured"); // Send Message back to iPhone
Udp.endPacket();
}
}

delay(20);
}

Jim_Socks:
Tom you hit the nail right on the head! NO more slightly lit LEDs for apparently no reason, NO more flickering, NO more arbitrary LEDs lighting!

Woo- HOO!

I completely didn't realize the shield used those pins! THANKS SO MUCH! Mystery problem #25- SOLVED!

Glad to hear it. The ethernet sheild uses the ISP programming header to maximise compatibility, as on boards such as the Mega the SPI pins are in a different location (digital 50-52). However it just so happens that on the Uno, the ISP header connects to digital pins 11 through 13. The ethernet sheild also uses pin 10 for the SS pin.

Jim_Socks:
...
In my code as it stands right NOW, I want it to read the packet, and if it reads "GBLD" I want it to pour my three second glass of vodka. If it DOESNT read "GBLD" I don't want it to do anything at all. I thought my code had this down... but apparently not. The arduino pours the vodka upon seeing ANY packet of information, not matter what it says! Any ideas?

Here is the specific area of code:

void loop() {

if (packBuff[0]== 'G' && packBuff[1]=='B' && packBuff[2]=='D' && packBuff[3]=='L'); // If the message sent from my iphone = "GBDL", then run the following script, which should pour vodka for 3 seconds. NOTE: I am using LEDs as proof of concept right now- later these will be relays.
{
...
}

The problem is the semicolon. Also, you will find that you are looking for "GBDL", not "GBLD", you'd better double check which you really want...

Cheers,
John

Tom:
Thanks again- I was BAFLED by this for so long!

Johncc:
I would've never guessed it was the semicolon (i'm just THAT noobish to this stuff I suppose) - but that was EXACTLY it! I chopped out the semicolon and blamo! It works like a charm now! The packet letters mixup was just a typo I made when typing my post, as soon as that semicolon was gone everything was right in the world. Thanks so much for your help!

To all:
I have to say- I am constantly impressed with this forum of folks. Time after time, and solution after solution. Thanks again to all! I am sure you haven't heard the last of me... this project is about to get BIG. I am betting it will soon require more code than the arduino memory can handle... so I bet I will soon be trying to use the cardslot on the ethernet shield to store some of it- with all the headaches that is likely to bring I'm sure I'll be back!

THANKS SO MUCH!