Skip navigation

Category Archives: Uncategorized

I just got in my new boards for the scoreboard project, and I was super excited to test out my plain old, unmodified toaster oven for some old fashioned reflow soldering. So I taped down the stencil and jig I had ordered from OSHStencils, and applied the solder paste to the board.

2015-04-03 21.32.22

One of my first concerns when settings up this first go at reflow soldering, was how expensive the solder paste was. Well, just as i had thought, it takes very little paste to cover all the little pads. I was concerned about waste, and while there was some paste left on the stencil and the spreader tool (a plastic card that also came with the OSHStencil order), I was able to collect most of the excess paste with the tool and place it back in the container. Since this was a large board, I started with a small gob of paste and worked the board in sections, alternating between thick spreading, and scraping it back up with the edge of the card.

2015-04-03 22.26.22

Placing the parts wasn’t too bad, I’d say it was easier than normal soldering with the 0603 resistors. I did expect the paste to be tackier, and while the parts did stick in place, it took very little effort to move them, so a stead hand is still needed to place and position. On the SOIC parts, the paste did seem to mingle between pads, but that wasn’t an issue at all. Once all the parts were down, it was into the oven.

2015-04-03 22.29.37

I tried to keep with the same methodology as the last post, although this time around I had black PCBs (since its an LED display, a dark background is preferred). While I’m only speculating, these boards reached much higher temperature much faster, I believe due to extra IR absorption. So this time I set the oven to 300F/150C on the convection setting (fan on). I let it heat until the thermostat clicked off, and waited until it clicked back on to turn the oven up to 400F/200C. This is were I was suprised. The black board started to flow as it approached this temperature setting, where the red board I had tested earlier flowed on its way to the 450F setting. Using a bright light, I was able to see the metallic shine of melted solder on all the joints. So once the thermostat clicked off, I shut the oven down and opened the door to let it cool. The board looked great, all the joints looked solid. There were a few were I could see that there possibly wasn’t enough paste on the pad, but the connections were still solid. The shift registers looked good, with no solder bridges.

2015-04-03 22.41.16

2015-04-03 22.41.07

2015-04-03 22.40.17

And the best part is, it worked!

2015-04-03 23.26.30

Even the digit chaining worked as expected.

2015-04-04 01.08.31

I think a proper diffusing sheet would make the final product very easy to read.

2015-04-03 23.25.51

And lastly, the Arduino code I used for the testing the digits.

/*
|***F***|
A       E
|***G***|
B       D
|***C***|

*/
const int D1 = 2;
const int CLK = 4;
const int STROBE = 3;

byte digitMap[10] =
{
	B11111100,
	B00011000,
	B01101110,
	B00111110,
	B10011010,
	B10110110,
	B11110110,
	B00011100,
	B11111110,
	B10011110
};


void setup()
{

	/* add setup code here */
	pinMode(D1, OUTPUT);
	pinMode(CLK, OUTPUT);
	pinMode(STROBE, OUTPUT);

	digitalWrite(STROBE, LOW);
	digitalWrite(CLK, LOW);
	digitalWrite(D1, LOW);


}

int state = HIGH;
int count = 0;
void loop()
{

	for (int i = 0; i < 100; i++)
	{
		byte Data2 = digitMap[i / 10];
		byte Data1 = digitMap[i % 10];

		//Write to display 
		for (int j = 0; j < 8; j++)
		{
			digitalWrite(CLK, LOW);
			digitalWrite(D1, Data1 & 0x01);
			Data1 = Data1 >> 1;
			digitalWrite(CLK, HIGH);
		}
		//Write to display 
		for (int j = 0; j < 8; j++)
		{
			digitalWrite(CLK, LOW);
			digitalWrite(D1, Data2 & 0x01);
			Data2 = Data2 >> 1;
			digitalWrite(CLK, HIGH);
		}
		delayMicroseconds(10);
		digitalWrite(STROBE, HIGH);
		digitalWrite(STROBE, LOW);

		delay(1000);
	}
}


Yeah I know, everyone is doing it. Reflow soldering with a standard counter-top toaster oven. While it’s not too exciting, I did want to document my successful test at using a cheapo oven I picked up at Goodwill for $10, completely unmodified. I had picked this up in preparation for some boards I’m going to make as part of my scoreboard project. While I was initially going to try to go for the ever popular reflow conversion, most of the modules out there for purchase seemed quite expensive ($60+, I’m cheap, I know). My own ballpark cost of making one myself came out to be $25-$30 (less if I skip the pesky mains isolated power supply for the micro). So while looking at the unit I had acquired, I figured it was at least work testing with built in front panel controls.

So the particular oven I picked up was a Black & Decker Toast-R-Oven 1500W, model TRO4075. Part of the reason I choose this oven over a $5 unit that was also for sale was that this one can the ‘Convection Bake’ feature, which means it includes an air circulation fan on the inside. From what I have read previously about reflowing, this can be extremely helpful for even heating and preventing hot spots.

2015-03-15 11.50.09
Oven Markings.

2015-03-15 11.50.33
Knobs.

Also looking at the front panel controls, it also already had its own temperature control and timer. Before the first test, I already knew the temp control wasn’t going to be very accurate, and the timer knob resolution not really useful as the first official marking (after light and dark toast) was 10 minutes. So for the first test I simply placed a board in the oven, set the temp to the 400F/200C mark, selected convection bake, and set the timer for dark toast.

The board I used was a 10cm square board that is almost the same board that I’m going to be assembling. The board is a double digit, seven segment LED numerical display. Foolishly I hit order to quickly on the first set, and being the amateur I am, wired the three LEDs of each segment in parallel instead of series. I only noticed after I tried doing the calculations for the resistor value and power ratings did I notice that I messed it up. While technically these boards would still work, having the LEDs in parallel can lead to current imbalance that can shorted the life of the individual LEDs as well as use 3x the power of the series configuration. The only major difference in the new boards, and I’m hoping this doesn’t have to big of an effect on the infrared heating, is that the test board was DirtyPCBs.com’s default red, and my new boards are coming in with the black solder mask. My other realization was that bright red would make a terrible background for a LED display, especially with red LEDs.

Anyways, back to the test. It was clear that the oven heats up pretty fast, probably faster than the recommended profile from the solder paste I’m planning to use. It wasn’t long before the existing solder on the pre-tinned pads began to wet. Now, I don’t have a thermocouple to measure the board temp with, so I only had my trusty el-cheapo infrared thermometer. Once the ovens own thermostat clicked the elements off, I measured the board at about 221C. Just over the melt line of the profile, but I do not have reason to suspect that the measurement was accurate by any means. I let it cook for a bit untill the timer clicked off and pulled it out of the oven after a short cool down. At first inspection all went well, no burn marks, scorching or other visible damage to the PCB. The only thing I had noticed was a bit of upward warping while the board was at peak temperature. On this board I had most of the wiring on the top layer and bottom layer is almost solid copper, so I’m guessing its a bit of thermal expansion of the bottom side that cause this. Not a big deal, it only appeared to be about a 2mm deflection at the one corner.

2015-03-14 18.56.57

For the next test, I just wanted to see how some of my extra 0603 resistors would handle it. I didn’t break out the stencil yet, so I just dabbed some paste on 8 footprints spread about the board. Pretty ugly, but the resistors stuck to it.

2015-03-14 19.04.02

2015-03-14 19.11.03

In this test, I tried to follow a bit of a profile to keep the board from heating too fast. I started by setting the temp to the 300F/150C mark, then waited for the thermostat to click the elements off. I waited a few seconds, then crept the temp up the the 400F/200C mark again. I did the same by waiting for the thermostat to click off in the toaster. While this is enough melt the solder, the profile called for a peak temp of around 230-249, so for the final bit I set the temp on the toaster to its max setting, 450F/230C. After the thermostat clicked off again, I shut it down and took another temperature measurement of about 235C. I waited about 20 seconds and then removed the board from the oven to cool quickly. The results where not that bad, other than the slightly excessive amount of paste that was put down for the pads. Again no board scorching, discoloration, bubbling, or other faults. The resistors looked as though they survived as well, all measuring close to the promised 1K Ohms.

2015-03-14 19.22.43

2015-03-14 19.21.55

Now as soon as my new boards get here, I’m going to be ready to try out my stencil and push a few boards through.

A long time ago I picked up an old LCD module (this one, if its still there). Now the trouble with this module is that it does not have a built in controller. It’s more like a TV or monitor in that it needs to constantly be fed a signal containing the image data to display. Now a standard micro controller might have trouble doing this on its own, it would either require a bit of external circuitry, or have to dedicate the majority of it’s processing time to updating the display. This is a surplus part, and the datasheet provided is poorly xeroxed and lacking specific implementation details. However it is a nice monochrome display at 640×480 and well worth the price of $5.50, if you can get it to work. Luckily for me, I found one other person on the whole internet who managed to get this same display working, and remnants of his work for the MIT Model Railroad club were found here, http://www.nyx.net/~jpurbric/lcd/. Now he managed to implement this using a PIC micro, some discrete logic and some external memories. My plan is to first attempt to drive this from my Papilio board. I had a good start since this other project made really nice timing diagram to follow for the display.

First in implementing the VHDL, I defined as many constant values as I could think up. Using the timing diagram and the datasheet, I setup some time period and count constants.

--Timing Constants 
--Time constant integers in nanoseconds
constant CLK_PERIOD : integer := 31; -- approximate/rounded off
constant XSCL_PERIOD : integer := 166 ;

--FRAME CONSTANTS 	
constant WIDTH : integer := 640;
constant HEIGHT : integer := 480;
constant XPULSES : integer := WIDTH / 4;
constant YPULSES : integer := 242;

The timings I defined at the minimums defined in the datasheet. The nice part about utilizing constants like this, is that I can adjust these later and the whole design should adjust. The CLK_PERIOD constant is the main clock period, so it will be used to keep track of elapsed time. The XSCL_PERIOD is the minimum period of the XSCL pulse or “X Shift Clock”. Looking at the timing diagram it seems that the data is read in on the negative edge of this signal. At first I thought of several other timing constants, but as I worked out the design, they didn’t prove to be necessary. The other constants are pretty obvious, the HEIGHT and WIDTH of the screen in pixels, and the number of YPULSES and XPULSES to be sent in each frame of the signal. If you notice these numbers don’t match up to the size of the display. This display is organized as two screens, an upper and lower half. It’s also 1 bit per pixel. So, of the 8 bit data bus, 4 bits go to the top and 4 go to the bottom. So it only needs to write 160 times for each line to get 640 pixels and it will write 242 lines. Yeah, there are 2 extra lines in the signal but the don’t make it to the display. And now for a couple signals to get started with.

 --Timing signals
signal XSCL_TIME : integer range 0 to (XSCL_PERIOD + CLK_PERIOD) := 0;

--count signals 
signal XSCL_CNT : integer range 0 to 160 := 0;
signal YSCL_CNT : integer range 0 to 242 := 0;

The first is my main time delay count. XSCL_TIME will just add on the clock period each time through the main process to make sure we don’t violate our minimum time for the signal. Its defined as a range from zero to XSCL_PERIOD + CLK_PERIOD because I wanted to be sure that whatever size value it ends up being has enough room exceed the XSCL_PERIOD by one clock cycles worth. The XSCL_CNT and YSCL_CNT are regular increment counters to keep track of where we are in the signal and be the main drivers of the state machine.

signal STARTED : STD_LOGIC := '0';

The STARTED signal is just a flag that’s used to have the signal go through as start up process. After the start up, STARTED is set to 1 and stays there.

--Output Signals 
signal LP_YSCL : STD_LOGIC := '0';
signal XSCL : STD_LOGIC := '0';
signal UD : STD_LOGIC_VECTOR(3 downto 0) := "0000";
signal LD : STD_LOGIC_VECTOR(3 downto 0) := "0000";
signal DIN : STD_LOGIC := '0';

These are the various output signals, three timing signals and the data signals. For now we will just be sending test pattern on the data. Now for the main process. I think its well commented so I won’t give a line by line explaination. It’s basically a simple state machine, using the current state of the output signals, the XSCL_CNT/YSCL_CNT, and XSCL_TIME signals to track where it is in the process. It follows right along with the timing diagram. Remember that in the process, signals are not updated until after the process.

	--Process Definition
	main: process(clk)
   begin
		-- triggers action on rising edge of clock signal
     if rising_edge(clk) then
	    --increment counter, using time type
		 XSCL_TIME <= XSCL_TIME + CLK_PERIOD;
		 
		 
		 if STARTED='0' then
		   --initial state
			--first part of timing diagram, on LP pulse, and a up/down on XSCL
			if LP_YSCL = '0' then 
				--set signals
				LP_YSCL <= '1';
				XSCL <= '1';
				--reset times
				XSCL_TIME <=0;
			elsif LP_YSCL = '1' and 
						XSCL = '1' AND
						XSCL_TIME > (XSCL_PERIOD/2) then 
				--set signal
				XSCL <= '0';
			elsif LP_YSCL = '1' AND
						XSCL = '0' AND 
						XSCL_TIME > XSCL_PERIOD THEN 
				--clear started flag
				STARTED <= '1';
				--reset timer
				XSCL_TIME <= 0;
			end if;
		else
			--after started
			if LP_YSCL = '0' and
				XSCL = '0' and 
				XSCL_CNT = 0 THEN
				--occurs at the end of a row, timing specs say LP_YSCL must go to zero before XSCL goes high
				--Raise XSCL to HI			
				XSCL <= '1';
				--reset pulse timer 
				XSCL_TIME <= 0;
				
				--update X count 
				XSCL_CNT <= XSCL_CNT + 1;
			elsif LP_YSCL = '1' and 
			--first step, LP is H, XSCL is L, XSCL_CNT is 0
				XSCL = '0' AND
				XSCL_CNT = 0 THEN 
				
				--drop LP, Raise XSCL, load data
				LP_YSCL <= '0';
				XSCL <= '1';
				
				--temp data 
				UD <= "0101";
				LD <= "0101";
				
				--reset timer
				XSCL_TIME <= 0;
				
				--if first row, raise frame pulse
				if YSCL_CNT = 0 then 
					DIN <= '0';
				end if;
			elsif XSCL = '1' AND 
					XSCL_TIME > (XSCL_PERIOD/2) THEN
				--drop xscl to L
				XSCL <= '0';
				
			elsif XSCL = '0' AND 
					XSCL_TIME > XSCL_PERIOD THEN
								
				
				--load new data
				--TODO
				
				--IF at last pulse raise LP to hi
				if XSCL_CNT = XPULSES - 2 then -- use pulses-2 to compensate for cnt not updated yet and zero based index.
					--last X pulse, raise LP
					LP_YSCL <= '1'; 
					--update X count 
					XSCL_CNT <= XSCL_CNT + 1;
					
					--Raise XSCL to HI			
					XSCL <= '1';
					--reset pulse timer 
					XSCL_TIME <= 0;
					
				elsif XSCL_CNT = XPULSES - 1 THEN 
				   --new line, drop LP
					LP_YSCL <= '0';
					--reset XSCL_CNT
					XSCL_CNT <= 0;
					
					if YSCL_CNT = YPULSES - 1 then 
						-- this was the last pulse, go back to zero
						YSCL_CNT <= 0;
					else						
						--increment Y count
						YSCL_CNT <= YSCL_CNT + 1;
					end if;
					
				else					
					--Raise XSCL to HI			
					XSCL <= '1';
					--reset pulse timer 
					XSCL_TIME <= 0;
					--update X count 
					XSCL_CNT <= XSCL_CNT + 1;
				end if;
				
			end if;	
			
			--if on first line, first x, raise frame pulse
			if LP_YSCL = '0' AND 
				XSCL = '1' AND
				XSCL_CNT = 0 and 
				YSCL_CNT = 0 then 
				--raise frame pulse
				DIN <= '1';
			elsif LP_YSCL = '0' AND 
					XSCL = '1' AND 
					XSCL_CNT = 0 AND 
					YSCL_CNT = 1 then 
				--shut down frame pulse 
				DIN <= '0';
			end if;
				
		 end if; --started
		 		
     end if; --clk	 
 	  
   end process;

And the most important part, mapping the signals to the output pin.

	A(0) <= LP_YSCL;
	A(1) <= XSCL;
	A(5 downto 2) <= UD;
	A(9 downto 6) <= LD;
	A(10) <= DIN;

I currently don’t have it setup to connect the display to the FPGA board just yet. I need to wire that up with a 3.3 to 5 logic conversion, since the Spartan3 is a 3.3V part. And looking at the datasheet the minimum “1” voltage is .8*VDD and the minimum VDD is 4.75V. Assuming a 5V supply, I need at least 4V to drive these signals. However, I really should verify the output of this before I go through the trouble of hooking it up anyways. Thankfully, the Xilinx tools come with a simulator that can be used to verify your design.

SimulateDesign

If you click on your source file in the design explore on the left, select Simulation up top, and the right click on ‘Simulate Behavioral Model’ and select ‘Run’, you should be see the ISim window open up. For me, the first thing I had to do was setup the clock. Oddly, it runs the simulation first with the clock just set as ‘Undefined’. Under the simulation menu, click ‘Restart’ to clear out the current simulation. Right click on the ‘clk’ signal, and select ‘Force Clock’.

ForceClockRightClick

Then you enter the parameters for your clock signal. I really wasn’t sure of the meaning of ‘Leading Edge Value’ and ‘Trailing Edge Value’ so I entered 1 and 0 respectively as they are required fields. Then I just set the clock period of 31.25ns.

DefineClock

Once you’ve done that, can run that for the amount of time you want to see. These commands should be on the toolbar at the top of the window.

RunForTime

Each time you click on the ‘Run for Time Specified’ button, it will add to the simulation, so you can verify the signal a few blocks at a time.

LCDSimulation

Looks good so far. Hopefully soon I can get it wired up and see if it actually works.