Eduardo

Problem with LogicStart SPI ADC

Recommended Posts

Hi,

 

i have been working with the p1 500k board since last month with the help of Hamster's tutorial and some posts of the forum, where i have learned a lot that's why I thank all who contribute to the papilio project and hope I can also contribute myself in the future. But now I'm having trouble making the ADC of the logic starter megawing work, I tried directly with the code that Hamster gives in his tutorial and when I was trying to read 3.3V in the channel 0 of the ADC, what the LEDs show is "0b10101100" what confuses me because I thought i should see "0b11111111" as 3.3V is the maximum value that the 12 bit ADC can read.

 

So since i couldn't really understand if the code of the tutorial uses the 8 most significant bits of the 12 bit ADC output value to light up the LEDs, i thought that i should use the recommended code ( -- Normally you would grab "datain_shiftreg(10 downto 0) & adc_dout" for 12 bits) to output the 12 bits and then display that value on the Seven seg display in hex. Also I did it and now the displays show "0B72" with 3.3 V and "0037" with 0.0V, what just looks like the same problem before.

 

So my question is, how do I send the correct 12/8 bits output value of the ADC to the displays/Leds in the logic starter mega wing, what am i missing? Is it a problem with the hardware? Because i was trying it with an external 3.3V voltage source and a potentiometer, but then i used the 3.3V and 2.5V voltage lines of the logic starter megawing and just ended with the same results. I also saw in the datasheet of the ADC128S102 that i could use a 22ohm resistor and a 1nF capacitor, but I don't really think that will solve the problem.

 

 

The code that I'm using with the Leds is the following:

library IEEE;use IEEE.STD_LOGIC_1164.ALL;-- Uncomment the following library declaration if using-- arithmetic functions with Signed or Unsigned valuesuse IEEE.NUMERIC_STD.ALL;-- Uncomment the following library declaration if instantiating-- any Xilinx primitives in this code.--library UNISIM;--use UNISIM.VComponents.all;entity adc is	port	(	clk : IN std_logic;	-- user interface	switches : IN std_logic_vector(2 downto 0);	leds : OUT std_logic_vector(7 downto 0);	-- Signals to the ADC	ADC_CS_N : OUT std_logic;	ADC_SCLK : OUT std_logic;	ADC_DIN : OUT std_logic;	ADC_DOUT : IN std_logic	);end adc;architecture Behavioral of adc is	-- Counter - the lowest 6 bits are used to control signals to the ADC.	-- The rest are used to activate the ADC when 0	signal counter : std_logic_vector(22 downto 0) := (others =>'0');		-- shift registers to delay output signals	signal clk_shiftreg : std_logic_vector( 1 downto 0) := (others =>'0');	signal dataout_shiftreg : std_logic_vector( 2 downto 0) := (others =>'0');		-- shift register to collect incoming bits	signal datain_shiftreg : std_logic_vector(11 downto 0) := (others =>'0');		-- register to hold the current channel	signal channel_hold : std_logic_vector( 2 downto 0) := (others =>'0');		signal adc_active : std_logic;begin	-- set outgoing signals	ADC_DIN <= dataout_shiftreg(2);	ADC_SCLK <= clk_shiftreg(1);		with counter(22 downto 6) select adc_active <= '1' when "00000000000000000",						       '0' when others;		process (clk)	begin		if rising_edge(clk) then-- A small shift register delays the clk by one cycle (31.25ns) to ensure timings are   -met.			clk_shiftreg(1) <= clk_shiftreg(0);			-- Including adc_cs_n in a clocked process to ensure that it is adc_cs is implemented   -in a flipflop			ADC_CS_N <= not(adc_active);			if adc_active = '1' then				clk_shiftreg(0) <= counter(1);			else				clk_shiftreg(0) <= '1';			end if;		-- This controls where we send out the address to the ADC (bits 2,3 and 4 of the   -stream)-- we use a short shift register to ensure that the ADC_DOUT transistions are delayed-- 31 ns or so from the clk transitions			dataout_shiftreg(2 downto 1) <= dataout_shiftreg(1 downto 0);			if adc_active = '1' then				case counter(5 downto 2) is					when "0010" => dataout_shiftreg(0) <= channel_hold(2);					when "0011" => dataout_shiftreg(0) <= channel_hold(1);					when "0100" => dataout_shiftreg(0) <= channel_hold(0);					when others => dataout_shiftreg(0) <= '0';				end case;							-- As counter(2) is used used to generate sclk, this test ensures that we				-- capture bits right in the middle of the clock pulse				if counter(5 downto 0) = "000000" then					channel_hold <= switches;				end if;							if counter(1 downto 0) = "11" then					datain_shiftreg <= datain_shiftreg(10 downto 0) & ADC_DOUT;				end if;								-- When we have captured the last bit it is the time to update the output.				if counter(5 downto 0) = "111111" then					-- Normally you would grab "datain_shiftreg(10 downto 0) & adc_dout" for 12 bits					LEDs <= datain_shiftreg(10 downto 3) ;				end if;			else				dataout_shiftreg(0) <= '0';			end if;		counter <= STD_LOGIC_VECTOR(UNSIGNED(counter)+1);		end if;	end process;			end Behavioral;

And the code I'm using fo the the seven seg display is:

library IEEE;use IEEE.STD_LOGIC_1164.ALL;-- Uncomment the following library declaration if using-- arithmetic functions with Signed or Unsigned valuesuse IEEE.NUMERIC_STD.ALL;-- Uncomment the following library declaration if instantiating-- any Xilinx primitives in this code.--library UNISIM;--use UNISIM.VComponents.all;entity adc is	port	(	clk : IN std_logic;	-- user interface	switches : IN std_logic_vector(2 downto 0);	anodes : OUT std_logic_vector(3 downto 0);	segments : OUT std_logic_vector(6 downto 0);	dp : OUT std_logic;	-- Signals to the ADC	ADC_CS_N : OUT std_logic;	ADC_SCLK : OUT std_logic;	ADC_DIN : OUT std_logic;	ADC_DOUT : IN std_logic	);end adc;architecture Behavioral of adc is	-- Counter - the lowest 6 bits are used to control signals to the ADC.	-- The rest are used to activate the ADC when 0	signal counter : std_logic_vector(22 downto 0) := (others =>'0');		-- shift registers to delay output signals	signal clk_shiftreg : std_logic_vector( 1 downto 0) := (others =>'0');	signal dataout_shiftreg : std_logic_vector( 2 downto 0) := (others =>'0');		-- shift register to collect incoming bits	signal datain_shiftreg : std_logic_vector(11 downto 0) := (others =>'0');		-- register to hold the current channel	signal channel_hold : std_logic_vector( 2 downto 0) := (others =>'0');		signal adc_active : std_logic;		signal sensor_value : std_logic_vector( 11 downto 0) := (others =>'0');		COMPONENT display4digits	PORT(		clk : IN std_logic;		digit0 : IN std_logic_vector(3 downto 0);		digit1 : IN std_logic_vector(3 downto 0);		digit2 : IN std_logic_vector(3 downto 0);		digit3 : IN std_logic_vector(3 downto 0);          		anodes : OUT std_logic_vector(3 downto 0);		sevenseg : OUT std_logic_vector(6 downto 0);		dp : OUT std_logic		);	END COMPONENT;begin	-- set outgoing signals	ADC_DIN <= dataout_shiftreg(2);	ADC_SCLK <= clk_shiftreg(1);		with counter(22 downto 6) select adc_active <= '1' when "00000000000000000",																  '0' when others;	Inst_display4digits: display4digits PORT MAP(		clk => clk,		digit0 => sensor_value(3 downto 0),		digit1 => sensor_value(7 downto 4),		digit2 => sensor_value(11 downto 8),		digit3 => "0000",		anodes => anodes,		sevenseg => segments,		dp => dp	);			process (clk)	begin		if rising_edge(clk) then			-- A small shift register delays the clk by one cycle (31.25ns) to ensure timings are   -met.			clk_shiftreg(1) <= clk_shiftreg(0);						-- Including adc_cs_n in a clocked process to ensure that it is adc_cs is implemented   -in a flipflop			ADC_CS_N <= not(adc_active);			if adc_active = '1' then				clk_shiftreg(0) <= counter(1);			else				clk_shiftreg(0) <= '1';			end if;					-- This controls where we send out the address to the ADC (bits 2,3 and 4 of the   -stream)			-- we use a short shift register to ensure that the ADC_DOUT transistions are delayed			-- 31 ns or so from the clk transitions			dataout_shiftreg(2 downto 1) <= dataout_shiftreg(1 downto 0);			if adc_active = '1' then				case counter(5 downto 2) is					when "0010" => dataout_shiftreg(0) <= channel_hold(2);					when "0011" => dataout_shiftreg(0) <= channel_hold(1);					when "0100" => dataout_shiftreg(0) <= channel_hold(0);					when others => dataout_shiftreg(0) <= '0';				end case;							-- As counter(2) is used used to generate sclk, this test ensures that we				-- capture bits right in the middle of the clock pulse				if counter(5 downto 0) = "000000" then					channel_hold <= switches;				end if;							if counter(1 downto 0) = "11" then					datain_shiftreg <= datain_shiftreg(10 downto 0) & ADC_DOUT;				end if;								-- When we have captured the last bit it is the time to update the output.				if counter(5 downto 0) = "111111" then					-- Normally you would grab "datain_shiftreg(10 downto 0) & adc_dout" for 12 bits					sensor_value <= datain_shiftreg(10 downto 0) & ADC_DOUT;				end if;			else				dataout_shiftreg(0) <= '0';			end if;		counter <= STD_LOGIC_VECTOR(UNSIGNED(counter)+1);		end if;	end process;			end Behavioral;

I also tried "sensor_value <= datain_shiftreg(11 downto 0);" instead of "sensor_value <= datain_shiftreg(10 downto 0) & ADC_DOUT;" what I thought was the correct code to use but it just gave me "05A6" with 3.3 V and "000B" with 0.0V.

 

 

Sorry if this question has been asked before but I just couldn't find anything in the forum.

 

Thanks in advance,

 

Eduardo

Share this post


Link to post
Share on other sites

I'm still not able to understand how this code is supposed to work, i would really appreciate some help around here. By the way, when i´m supposed to be reading an adc value, the leds don´t remain stable, they keep changing every time. I also tried the "ZPUino Test Code for the LogicStart MegaWing" in order to see if the  ADC128S102 is working as it should, but the bit file didn´t work, i couldn´t see anything clear in my monitor, does anyone knows if that bit file is working?

Share this post


Link to post
Share on other sites

If I use the following line: "LEDs <= datain_shiftreg(7 downto 0) ;" am i supposed to be printing the first 8 bits of the adc?

Share this post


Link to post
Share on other sites

Hi Eduardo,

 

Can you run a "clean up project files" and email me a zip of your project at hamster@snap.net.nz ? I'll have a look over it for you over the weekend.

 

Mike

Share this post


Link to post
Share on other sites

Hi Eduardo,

 

After checking your code I think we have both missed that the ADC's VA (Analog/reference voltage) is connected to 5.0V... and 5.0V does read about x0FE0.

 

I've sent you the test bench I used to verify that the ADC was correctly capturing the data. If you initialise "counter" in your ADC to something like  "11111111111100000000000"  you will only have to simulate 64us or so before the ADC conversion will begin.

Share this post


Link to post
Share on other sites

Thanks a lot Mike, you saved my day. I should have checked out how the ADC is connected in the Logic Start Mega Wing, but I really thought the reference voltage was 3.3V because of what you say in your book about connecting the ADC to 5V. But anyway the upadate you did to my display4digit module really improve how the 7segment displays show the value the ADC reads, now I am able to read a stable value (without burning my eyes haha).

Share this post


Link to post
Share on other sites

Hie I am curious to know why do you access the control register from 10 and not 11 looking at the way you did it. "datain_shiftreg(10 downto 0) & ADC_DOUT"

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now