Yuri's first custom printed circuit board (an Arduino shield)

Homebrew Talk - Beer, Wine, Mead, & Cider Brewing Discussion Forum

Help Support Homebrew Talk - Beer, Wine, Mead, & Cider Brewing Discussion Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.
Joined
Jul 24, 2006
Messages
14,260
Reaction score
786
Location
Southwest
I wanted a compact solution to the breadboarded rat's nest that currently controls my rig (sorry, it was intentionally left out of the pictures in other threads). After seeing that Sparkfun's BatchPCB service was pretty cheap, I thought I'd try my hand at PCB design. I used the freeware version of Eagle and a template from Lady Ada. I ordered two Arduino shields and two accelerometer breakout boards (I got some sample accelerometer chips and want to see how they work). The designs were submitted on New Year's Day, and 3 weeks later, I received four of each board. BatchPCB sends extras if they are forced to run extra panels due to flaws. Sweet!

The good news is that the shields fit perfectly, and they all test good for continuity. The bad news is that my circuit design was slightly flawed. It's nothing that can't be overcome with a few solder bridges (visible on pins 1 and 2 of the SO-8 ICs) and a little creativity. My biggest mistake was isolating some of the ground plane pour from an actual connection to ground. I also wish that I'd provided some headers for PWM output. I've likely violated some design rules since I have no formal training in PCB design. Silly mistakes notwithstanding, I'm very happy with the results. I can read four separate thermocouples using SPI, and I have simple connections for all of the analog pins and a few digital pins.

Here's a pic of the results. I kept a few prototyping features on the board just in case I want to change the configuration later. A MAX6675 chip is missing - one of them tested bad.

octaviusshield.jpg
 
I think I like them a lot! As with any thermocouple system, they are highly susceptible to noise. I'm hoping that this board helps in that regard. They are slightly cheaper and theoretically more accurate than the popular AD595 chips. On Arduino, you will likely need to bit-bang the SPI interface if you want to use more than one MAX6675 on the same SPI bus (or delve into some really low level code that I have yet to get working correctly).
 
The total order cost (two Arduino shields, and two 1.5"x1" breakout boards, shipping included) was $52. Since I lucked out and got twice what I ordered, the cost per board was just over $12. In comparison, if I used a bigger manufacturer, the min order would've been roughly $100 for 10 identical boards. Admittedly, part of the reason I did this was simply curiosity.
 
Sweet. I design circuits for a living and support PCB designers through layout. I love it! I'm glad to see you had some fun and that they work as intended.
 
Admittedly, part of the reason I did this was simply curiosity.

Yeah, I understand that. The reason I asked the price is that you might have found a source to make these things dirt cheap without buying in bulk. If I could just send a design away and get a board back for ten bucks, I'd probably do it. Instead, I'll likely just wire wrap my boards since they will probably be one-of-a-kind. We did circuit board design and manufacturing in college so I have no curiosity there.
 
May be no one here wants to spend the time processing their own circuit boards, but here's a great link to a couple of videos that takes you from laying out the circuits to be laser copied to transferring the image to bare copper boards and then washing away everything but the traces with a home-made solution of hydrogen peroxide and muriatic acid. The coolest thing about the solution he makes is that it is cheap and re-usable.

http://www.getlofi.com/?p=1997
 
Nice job Yuri. I have been making boards for g-jobs on the PCB Router at work but you just can't beat a professionally etched and screened board.
 
If you're following my ridiculously boring Twitter page, it is now updated via the shield pictured above.

FWIW, the large negative volume numbers are a result of storing my volume sensor upside down, so it's measuring the distance to the ceiling rather than to the bottom of the kettle.
 
If I could just send a design away and get a board back for ten bucks, I'd probably do it.
They charge $2.50 per square inch plus about $15 per order for processing/shipping. So, to have them make a single Arduino shield would cost about $30. It takes 3 weeks to a month to get your order. Depending on the application, it may be worthwhile.
 
That's pretty badass dude...I ordered about $200 worth of stuff over the past few weeks, been doing a lot of playing with everything...I think I am almost ready to build my temperature controller
 
I've used pcbfabfexpress in the past and was happy with the price and turn time. I'll have to compare them to Sparks price next time.

On Arduino, you will likely need to bit-bang the SPI interface if you want to use more than one MAX6675 on the same SPI bus (or delve into some really low level code that I have yet to get working correctly).

I'm curious.
Are you trying to write an interrupt driven SPI interface or setup a chip select network in some existing library?
 
I used ExpressPCB back in my high-power rocketry days. They've got their own design / layout tool that works reasonably well for the novice circuit designer. Definitely looks like Spark's pricing is better for small runs though.
 
Are you trying to write an interrupt driven SPI interface or setup a chip select network in some existing library?
I'm just sampling SPI output once per loop iteration (about twice per second in this case). Since the SPI devices don't trigger any events and simply output data when selected, there is no need to attach an interrupt. Arduino's pins 10-13 are connected to a hardware SPI interface on the Atmega chip. It's apparently capable of extremely fast data rates. You can find a working library for it at the Arduino playground site. However, only pin 10 can be used for chip select, limiting the interface to a single device. I'm sampling four different devices in succession, and every time I tried modifying the library to use a different CS pin, the microcontroller stopped running the routine entirely. After a bit of Googling, I found that I'm not the only one to attempt a multi-device SPI network in this manner and fail miserably. So, I'm using a software based SPI interface. The data rate is much slower, but I don't really need a super fast transfer.

Here is my function for reading the 12 bit temperature value from a MAX6675 thermocouple amplifier. It's crude but effective.

Code:
// bit bang SPI to read MAX6675
// hardware SPI doesn't work because CS is not pin 10
// returns raw 12 bit data
// negative return values indicate lack of thermocouple input
int readTemp(int pinCS, int pinMISO, int pinSCK) {
  int val = 0;
  pinMode(pinCS, OUTPUT);
  pinMode(pinMISO, INPUT);
  pinMode(pinSCK, OUTPUT);
  
  // set the clock low and select the chip
  digitalWrite(pinSCK, LOW);
  digitalWrite(pinCS, LOW);
  
  // cycle the clock once to shift the meaningless sign bit out
  digitalWrite(pinSCK, HIGH);
  digitalWrite(pinSCK, LOW);
    
  // read the 12 significant bits
  for (int i = 0; i <= 11; i++) {
    val = val << 1;
    val = val + digitalRead(pinMISO);
    digitalWrite(pinSCK, HIGH);
    digitalWrite(pinSCK, LOW);
  }
  
  // if the error bit is HIGH, no thermocouple is attached
  // return a negative number (values below freezing are not possible)
  if (digitalRead(pinMISO) == 1) {
    val = -75;
  }

  // deselect the chip
  digitalWrite(pinCS, HIGH);

  // return 12 bit value
  return val;
}
 
Gotcha.
The advantage of using a timer interrupt to do bit bang spi comms is you can set the interrupt timer to the length of your clock pulse. In the interrupt service routing you make a state machine so that every time it the interrupt occurs it does ONE clock cycle (up or down) and what ever associated instruction for that clock state, set/clear cs, read data line etc etc. Once the cycle is complete you move the value to a global variable that can be accessed any where in the code.
You could also make a class for it, when you create the class you install the interrupt, and then get the data via a get member.

This way you aren't wasting processor time on delays (though I don't see any in your code) and the data is constantly being updated in the background on a regular basis. Something I picked up writing firmware for SCADA equipment.

As for why moving pin 10 doesn't work? I haven't looked at the avr spec sheet yet but that may be a discrete/physical driver that does not rely on code to perform the SPI function. In that case the pin may be electrically dedicated to that function. Would have to look at the data sheets to tell for sure.

You could try this, and it is what I was thinking of doing.
Put an 8 bit serial to parallel spi shift register on the end of the SPI bus.
run the SI,SO,and SCK pins to all of your SPI devices. Run the CS pin to the shift register, and then run the shift registers outputs to the CS of the other devices.
Using the spi, set the SR outputs to turn on the appropriate device, read it, change the SR, read the next one, etc etc.
There will need to be some circuitry to disable the CS lines to the rest of the devices's CS on the other side of the shift register so that when writing to the SR nothing will think it is selected. and vice versa for the SR.
It will have your SPI bus because every other spi instruction is sent to the SR, so I don't know how much time it will save you. Sounds like a bit of work, that is for sure.

I do have a bit bang SPI class library I wrote if you want it. It makes initialization and data retrieval a bit cleaner Not sure when I will get around to writing the interrupt service routine methods though, but it works.

On a similar but different topic, I've been playing with a bunch of op-amps this weekend and have managed to read an RTD down to 0.05F resolution from 0-220F. Why you would need it? I dunno but it was good challenge ;)
 
Yuri, I was doing some testing last night and noticed that my a2d routines were BALLS SLOW! I was really disappointed with the AVR and thought it may have something to do with the Arduino API layer.

Some one has found by writing directly to the port registers they had a 10x speed improvement over the digwrite (and I imagine read too...)!
http://www.instructables.com/id/Arduino-is-Slow-and-how-to-fix-it/

I am really tempted to ditch the arduino environment and just use the regular avr compiler and programmer.
 
CodeRage, I've read the same info about speed improvements. So far, I have no need for speedy, real-time style processing. The Arduino IDE makes things super simple. If I were attempting to design a more complex controller (electronic engine management, for example), I'd likely take a more pure approach to AVR microprocessing.
 
CodeRage, I've read the same info about speed improvements. So far, I have no need for speedy, real-time style processing. The Arduino IDE makes things super simple. If I were attempting to design a more complex controller (electronic engine management, for example), I'd likely take a more pure approach to AVR microprocessing.

Sorry guy, looks like you may have taken offense. I wasn't knocking your work by any means. This kind of stuff is in my roots as an EE and I guess that is why I expect more performance from the device. I had unintentionally assumed that others would have the same expectations from the same experience. Thats all.

Not many people can/want to just pic the stuff up and dive through spec sheets, etc etc. So to make anything work really is an accomplishment. If I alluded to something different it wasn't intentional.
:mug:

tbh, the arduino IDE isn't that far removed from directly programming the device. I was surprised, I expected it to be scripted using an on chip interpreter. Regardless, you're a bit twiddler now ;)
 
There's absolutely no need to follow my Twitter page. My script simply posts a few bits of pertinent data every 15 minutes. Mostly, I get to monitor the temperature in my brew hut from anywhere, anytime. It's not particularly interesting if you're not me.
 
Hey Yuri, and any one else for that matter.

I know your current application doesn't need high speed data collection. I did and figured I would share a pin and spibus class with y'all.

Just copy the folder to /arduino/hardware/libraries . There is an example too. You want hurt my feelings if you change the library folder name either :D

At this time it doesnt support SPI data transmission, only receiving. It does however allow you to identify the SPI pins and clock timing, then add up to 8 devices and their cs pins.

Hope it's useful.

View attachment CodeRage.zip
 
Back
Top