500ns signal detection

Go To Last Post
33 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Freaks,

I'm designing a new project for the academy, which will be my first proper contribution. I've hit a snag though, and I'm looking for some advice.

My project requires me to detect a 500ns (minimum) signal via my 8535 running at 8Mhz, and perform an action based on that. I thought about hooking the signal to an external interrupt pin, and then use the rising edge interrupt to run my routine.

That's the easy part. What I need to now do is detect whether this signal is less than 500ns, and if so throw an error via an error LED. What's the best way to both do a task on the rising edge of an external interrupt, as well as measure the duration of the pulse?

I'm a C person, but text description or psudocode on what I need to do to solve this would be great.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Would it be koshier to:

* Enable INT0 to fire on rising edge
* Enable INT0

In the interrupt:
* When INT0 fires, check for the "Signal Recieved flag"
* IF flag 0, set the MCUSR register to fire the register again on falling edge
* Set a "Signal Recieved" flag
* Reset and start a timer
* Run associated routine
* ELSE
* Stop the timer
* Reset "Signal Recieved" flag
* Set INT0 to fire on the rising edge again
* Read timer to check signal duration

Sounds ok?

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The routine looks ok but I fear 500 ns is too tight. When running at 8MHz you only have 4 clock cycles before the signal changes. Before you leave the interrupt routine you'll have used more than 4 clock cycles, making it impossible to return to the routine again on the falling edge before the 500 ns has elapsed.

If you are only interested to know if the pulse is shorter than 500 ns maybe you can try to read the pin on the third clock cycle directly after the rising edge interrupt has occurred. I'm not sure how many clock cycles it takes to enter the interrupt routine after a rising edge has occurred though. Too many clock cycles might already have been spent before you even get to the routine.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hmm, scratch that idea then. I was going to make a virtual 44780 controller (LCD) so that you could display LCD text on your computer without changing your code (allows for logging too) as well as diagnostics to show errors in your routines. I could always just do the logging and display part, but...

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Dean,

Maybe it would possible to use the ICP pin?

Have a nice day

Pippo

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not sure. Even though i've been user AVRs for almost two years now, i've never been very adventurous in the features i've used (basically just timers and EEPROM as far as special functions go) and so i've decided to give it my all and really make somthing worth while. I did a test of a state machine with my Simple Simon game (i've written plenty of demo AVR apps but I wanted to try a practical example) which worked, so that's why i'm doing this.

I checked the datasheet (8535), but it isn't clear on what the ICP actually does. It's rigged to the timer as far as I can tell - does it cause the timer to count as long as the pin is held high? If so, that would make life a lot simpler for me...

Edit: Disregard this, found the relevant datasheet paragraph.
Edit2: Looks like that won't help; I need a way to record both the start and end pulse times - that will only give me the start time.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Obsolete code removed for clarity and space

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

Last Edited: Fri. Nov 11, 2005 - 11:42 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

thenuts concerns about 500ns beeing too short are valid I am afraid. It simply takes to long to enter the interrupt routine(s). With ICP you can get an accurate timing for one flank but not measure the pulse length. But it seems to me this is an almost perfect application for the Noise Canceler available with ICP. It samples for four cycles, exactly what you need. Maybe you can connect as you suggest and check in INT0 if you also got an ICP, if you did the pulse > 500ns, if not it was shorter. Probably best to just manually check the interrupt flag ICF1.

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I havn't got the circuit made up yet, so everything thus far is purely guesswork and theory. I've implemented your noise canceller idea, is the following code correct for that?

// INCLUDES:
#include 
#include 

// DEFINES:
#define RS          _BV(0)
#define E           _BV(1)
#define RW          _BV(2)
#define STATPORT    PORTA
#define DATAPORT    PORTB
#define CONTROLPORT PORTD

#define M_EightBit  0
#define M_FourBit   1

#define S_UNINIT    0b00000011
#define S_OK        0b00000010
#define S_ERR       0b00000001

#define STATMASK    0b00000011

#define YES 1
#define NO  0

#define I_InitDone  3

// MESSAGE DEFINES:
#define LCDM_ERR     "\255ERR"
#define LCDM_Clear   "\255CLS"
#define LCDM_Goto    "\255GOTO"
#define LCDM_Display "\255DISP"
#define LCDM_Cursor  "\255CURS"
#define LCDM_Blink   "\255BLNK"

#define LCDNL        "\r\n"

// MESSAGE NOS:
#define ERR_Init 0x80
#define ERR_Icmd 0x01
#define ERR_Irs  0x02
#define ERR_Irw  0x04
#define ERR_Itme 0x08
#define ERR_Cesp 0x01

// MACROS:
#define SetStatus(P, M) P     = ((P & ~(STATMASK)) | M)

// PROTOTYPES:
void ProcessCommand(void);
static inline void UART_InitUART(void);
void SendError(unsigned char ErrBits, unsigned char Ebyte);
void UART_TransmitString(char *ptr);
void UART_TransmitByte(unsigned char data);

// GLOBALS:
unsigned char Mode        = M_EightBit;
unsigned char DataNibble  = 0;
unsigned char StopOnError = YES;
unsigned char Initialised = 0;
unsigned char Busy        = NO;

// MAIN ROUTINES:
int main(void)
{
	UART_InitUART();

	STATPORT    = STATMASK;	// Set status port LEDs to Outputs
	CONTROLPORT = 0x00;		// Set control port to inputs
	DATAPORT    = 0x00;		// Set data port to inputs

	UART_TransmitString(LCDM_Clear);	// Send the CLEAR command
	UART_TransmitString(LCDNL);			// Send CRLF

	UART_TransmitString(LCDM_Goto);		// Send the GOTO command
	UART_TransmitByte(1);				// Line 1
	UART_TransmitByte(1);				// Col  1
	UART_TransmitString(LCDNL);			// Send CRLF

	SetStatus(STATPORT, S_UNINIT); // Show the "Unitialised" status onto the status LEDs

	GIMSK |= (INT0 | TICIE1);	// Enable external interrupt 0 (PD2) and ICP1 (PD6)
	MCUCR |= ISC11;				// Set INT0 to fire on the falling edge
	TCCR0 |= CS00;				// Start timer 1 at full clock speed
//	TIMSK |= TICIE1;			// Enable ICP interrupt
	TCCR1B |= ICNC1;			// Enable ICP noise canceler (four samples are taken and compared)

	return 0;	
}

void ProcessCommand(void)
{
	char DataByte = DATAPORT;

	if(Mode == M_FourBit)	// 4-bit mode is selected
	{
		if(!(DataNibble))	// No data nibble has been loaded
		{
			DataNibble = (DATAPORT & 0xF0); // Record the data nibble
			return;	// Exit the function (cannot process until the other nibble is sent)
		}
		else	// First data nibble has been loaded
		{
			DataByte   = (DataNibble << 4) & (DATAPORT & 0xF0); // Join the nibbbles into a byte
			DataNibble = 0; // Clear the data nibble
		}
	}

	// Note: at this point "DataByte" is equal to the whole command

	if(Initialised != I_InitDone) 	// LCD not yet fully initialised
	{
		if(CONTROLPORT & RS) // RS pin enabled when it shouldn't be
			SendError((ERR_Init | ERR_Irs), Initialised);
			
		if(CONTROLPORT & RW) // RW pin enabled when it shouldn't be
			SendError((ERR_Init | ERR_Irw), Initialised);

		switch(Initialised)
		{
			case 1:
				if(Mode == M_FourBit) // Four-bit mode calls this part twice by design,
					break;	// Exit the procedure if it's the second time
				
				if(!(DataByte & _BV(5)))
					SendError((ERR_Init | ERR_Icmd), Initialised);
				
				if(!(DataByte & _BV(4)))
				{
					Mode = M_FourBit;
				}
				else
				{
					Initialised++;
				}
			case 3:
				if((DataByte & 0xF0) | !(DataByte & _BV(3)))
					SendError((ERR_Init | ERR_Icmd), Initialised);
				
				UART_TransmitString(LCDM_Blink);		// Send the BLINK command
				UART_TransmitByte(DataByte & _BV(0));	// Send the blink flag
				UART_TransmitString(LCDNL);				// Send CRLF

				UART_TransmitString(LCDM_Cursor);		// Send the CURS command
				UART_TransmitByte(DataByte & _BV(1));	// Send the blink flag
				UART_TransmitString(LCDNL);				// Send CRLF

				UART_TransmitString(LCDM_Display);		// Send the DISP command
				UART_TransmitByte(DataByte & _BV(2));	// Send the blink flag
				UART_TransmitString(LCDNL);				// Send CRLF

				SetStatus(STATPORT, S_OK); 				// Show the "OK" status onto the status LEDs
		}

		Initialised++;
	}
	else	// LCD has been initialised, process command
	{
		if(CONTROLPORT & RS)
		{
			if(CONTROLPORT & RW) // RS + RW = Read data from RAM command
			{


			}
			else // RS only = Write data to RAM command
			{

			}

			return; // Finished processing the command
		}
		else if(CONTROLPORT & RW) // RW only = Read busy flag and address
		{


			return; // Finished processing the command
		}
	}
}

void SendError(unsigned char ErrBits, unsigned char Ebyte)
{
	SetStatus(STATPORT, S_ERR);

	UART_TransmitString(LCDM_ERR);
	UART_TransmitByte(ErrBits);
	UART_TransmitByte(Ebyte);
	UART_TransmitString(LCDNL);			// Send CRLF

	if(StopOnError == YES)
		while(1) {}
}

SIGNAL(SIG_INTERRUPT0)
{
	if(ICR1)
	{
		ICR1 = 0; // Reset ICP register
	}
	else
	{
		SendError((ERR_Cesp), 0);
	}

	ProcessCommand();
}

// UART ROUTINES:
static inline void UART_InitUART(void)
{
	UBRR = 51;			// Set the baud rate (9600 @ 8MHz)
	UCR = (1<<TXEN);	// Enable UART transmitter
}

void UART_TransmitString(char *ptr)
{
  while (*ptr != 0x00)	// While character is not a null terminator (end of string char)
     UART_TransmitByte(*ptr++);	// Keep writing chars from memory until a "\0" terminator is found
}

void UART_TransmitByte(unsigned char data)
{
	while ( !(USR & (1<<UDRE)) );	// Loop until UART is ready to transmit
	UDR = data; 	// Send byte
}

Kudos for all the help. I can't believe i've been so slack in learning the interesting features that make AVRs so great for so long :(.
- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What's the rush :D Looks to me like you need a lot of _BV or (1<<...) here

   GIMSK |= (INT0 | TICIE1);   // Enable external interrupt 0 (PD2) and ICP1 (PD6) 
   MCUCR |= ISC11;            // Set INT0 to fire on the falling edge 
   TCCR0 |= CS00;            // Start timer 1 at full clock speed 
//   TIMSK |= TICIE1;         // Enable ICP interrupt 
   TCCR1B |= ICNC1;         // Enable ICP noise canceler 

Also TICIE1 is not in GIMSK (and should not need to be enbled which is why you commented out the TIMSK |= TICIE1 line). Disclaimer: I have never done ICP without actually having the interrupt also but I think it should work.

The checking in SIG_INTERRUPT0 looks ok but I guess you will have to test.

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lajon wrote:
What's the rush :D Looks to me like you need a lot of _BV or (1<<...) here

   GIMSK |= (INT0 | TICIE1);   // Enable external interrupt 0 (PD2) and ICP1 (PD6) 
   MCUCR |= ISC11;            // Set INT0 to fire on the falling edge 
   TCCR0 |= CS00;            // Start timer 1 at full clock speed 
//   TIMSK |= TICIE1;         // Enable ICP interrupt 
   TCCR1B |= ICNC1;         // Enable ICP noise canceler 

Also TICIE1 is not in GIMSK (and should not need to be enbled which is why you commented out the TIMSK |= TICIE1 line). Disclaimer: I have never done ICP without actually having the interrupt also but I think it should work.

The checking in SIG_INTERRUPT0 looks ok but I guess you will have to test.

/Lars

Rush is because i'm tired and I have a need to finish things NOW :D.

Oh yes, *hit self on head* I forgot the _BV's. I assure you i'm not totally incompetent...

I guess I'll have to knock up the hardware this weekend and give it a go. Incidentally, do you think this would be an interesting academy project? Being able to log/view the LCD on your computer, and find LCD routine faults?

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Interresting project yes. I am just not sure you will be able to make something that reacts like a 44780 as far as timing goes. It is supposed to have the same timing as a 44780 right?
There can be a lot of LCD commands comming in during the time it takes you to pass just one of them on with the UART. Or am I missing something?

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

8 MHz equates to 125 ns.

1/8,000,000 = 0.000,000,125

You require 500 ns detection.

500 ns / 125 ns = 4.

Thats only four clock cycles.

You might be better off using a "Hardware" pulse discriminator, using a re-triggerable one shot.

The re-triggerable one-shot can be set up such that, as long as the inconing pulse is greater then 125 ns, the Q NOT output stays low. If the incoming pulse drops below 125 ns, the one shot times out, causing Q NOT to go high. Q NOT would be used to generate the intrrupt.

You can look at the 74HC4538, or equivelent. This is a dual re-triggerable, monostable multivibrator. On page 5-543 of the Motorola High-Speed CMOS Logic Data book has an RC timing chart shows that it can work down to 500 ns.

A more reliable addition would be to have Q NOT set a hardware latch, utilizing a 74HC74A Dual 'D' Flip-Flop with Set and Reset inputs. The one shot sets the latch upon fault detection, the latch then generates the intrrupt. This would gaurantee that the microcontroller would detect the fault condition. Once the microcontroller enters the ISR, it acknowledges the external hardware intrrupt by resetting the 74HD74A latch.

This is an older technology device and there are probably other devices that will serve the purposs more fully.

Easy fix! One or two chips, one capacitor, and one resistor, solves ALL of your problems.

I opt for the reliability over parts count.

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And if parts count is an issue, then I guess a resistor and a capacitor combined with the AVR's analog comparator could be an option.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Svuppe,

Concering your last post...

Svuppe wrote:
And if parts count is an issue, then I guess a resistor and a capacitor combined with the AVR's analog comparator could be an option.

Could you elabrate in more detail.

How will that perform the required pulse width descrimination? The analog comparator suill relies in the Uc clock.

If you are just thinking if a clasic R/C filter, how would that translate to timing accuracy?

Your idea is intregueing, though.

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It was just a quick thought:
Using the R/C filter to generate the 500ns delay, and use the analog comparator to detect if the 500ns was reached. Also the unfiltered signal should go to an interrupt pin to detect the shorter pulses.

But as this was only a quick thought, I completely missed the "shorter than 125ns" argument :oops:
I stand corrected.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think i'll put this into the "good idea, but..." catagory. Looks like I'm going to have to figure out a new interesting project to occupy my time while i'm supposed to be studying...

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I only have a Mega64 datasheet with me, so I don't know if this applies to the Mega8. I think that's what the OP said he was using.

If the OP has any intention of using the analog comparator, the ADC is taken "Off Line" during it's use, so that might not be a very good thing.

Also, when using the timer/counter/ capture mode, the analog comparator uses the digidal filter of the timer/counter, which is Uc clock driven. Though, I don't know that this is true for every analog comparator usage. Pulses less then the time it takes to propagate through the digidal filter will be lost. If the pulse were longer, you could read the timer/counter on the first edge, and compare the first reading with the timer/counter upon arrival of the second pulse edge, provided the pulse repetition rate allowed enough time in between pulses.

I just don't see how the four clock cycle requirement can be overcome, without external hardware support.

Now, a 20 HMz ATTiny2313 has a 50 ns clock cycle time. So, 500 ns / 50 ns = 10 clock cycles. I still don't know if this will enough clocks to catch the pulse loss.

Capturing an intrrupt directly will be fast, but can the required code be executed within the pulse width period, or even before the arrival of the next scheduled pulse?

So say:

The first pulse edge arrives and generates an intrrupt. The intrrupt reads the timer/counter value. The intrrupt returns. The second pulse edge arrives, generating a second intrrupt. The timer/counter is again read. The second timer/counter value is then subtracted from the first and you get the time of the pulse width.

The question is, can you enter the ISR, read the timer/counter, check which edge is active, store the value in the proper location, and return from the intrrupt before the second pulse edge arrives?

Then, can you process the fault handler and act on it's findings, before the next scheduled pulse arrives?

It still sounds like a hardware support solution is the best solution.

By the way, what is the pulse repetition rate?

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It seems to me that if you want to know if the pulse is still there after 4 clock cycles, then you will need to assume that your interrupt is tripped immediately (this does not always happen) then allow 2 cycles (IIRC) to get into the ISR, do one misc instruction, and then read the pin again. If it's not still high, your pulse was too short. (I'm not sure if you need one other instruction, none, or two - check the data sheet for the exact timings.)

If you don't need to push any registers onto the stack, you could make the timing deadline. You may need several destroyable registers to copy the I/O port's register to...like this:

ISR_Pinchage: ;; Not the right name
in PINB, R20 ;; destroy the contents of R20
in PINB, R21 ;; destroy the contents of R21
in PINB, R22 ;; destroy the contents of R22
;; now, check to see how long the pulse was,
;; or if it's still going on after a few cycles to
;; start the ISR plus 3 cycles of reading the pins.

Once you get the timing right, you could only overwrite a single register.

Andy Out!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I found the verbage and table shown below in the Atmega8535 datasheet.

It might help.

So you want a 500 ns descrimination window, INT2 requires 50 ns to gaurantee the intrrupt gets processed.

That gives you 10 clock cycles to act on the other edge, provided the pulse width is greater then 50 ns.

Consider this:

There is a: (50 / 500) * 100 = 10% probability that you won't catch a pulse. If you can gaurantee that the deffective pulse is at least greater then 50 ns, you will be able to detect it., but you won't be able to measure it.

But simply detecting the puls isn't an assurance that it meets the 500 ns pulse width requirement.

You will have to look at both edges and determine its width.

One approach might be to use INT2 to detect the first pulse edge. Then using your R/C - analog comparator idea, detect the other edge using the analog comparator, because it responds slower. Once the R/C values are established, if you see both, INT2 and the analog intrrupt, your pulse has met the 500 ns pulse width requirements. If you only see the INT2 intrrupt, the pulse width didn't meet the minimum requirements. You will probably need a diode, cathode to the signal source, across the resistor. This will help the R/C network to discharge quickly when the pulse terminates.

The important thing to realize here is, that for any pulse width less then 50 ns, you get no detection at all of the deffective pulse. I don't know how important this is to your application. You have to decide that...

Ok, thats my fifty cents worth!!!

Hope it helps.

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Again, I think it's just best (for me at least) to bin this idea and start afresh on a new project that won't kill my developing brain cells. If anyone has any suggestions (yes, i've seen the Cornwell page) feel free. Similarly, if anyone wants to continue or make this project go ahead.

Microcarl: you are a god amognst men.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

abcminiuser,

Quote:
Microcarl: you are a god amognst men.

Maybe to the cavemen a million years ago but, today I'm just a geek...

This was a good question, with a tough answer. It will take a bit of effort to work out.

Don't give up! You aren't really losing brain cells! In fact, you are accquiring them and, that's always a painful process. Now your hair, that might be another issue!

I'm currently setting up a new notebook. Once I get all of the files transfered and am able to communicate with my STK500, I think I will give this a try. If/when that happens, I'll share the information with you.

The difference between a nerd and a geek: A nerd only thinks about doing something, a geek actually gets it done!

They call me "Technoid" at work. I wonder why?

Thanks! I'm flattered...

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Microcarl,

The obvious fact that this would not work with any great speed and thus would be 8-ways from useless, I guess a pulse stretching hardware solution could be implemented? I've seen simple circuits designed to stretch logic pulses out so that you can view them on a LED. In any case, I can't really see the point of an application that would delay what is being shown by a significant amount (RS-232 delay). That, and i'd have to implement a buffer to bufer the incomming data while the previous data was being sent.

Having said that, this could still be usefull as a LCD debugging system instead, but i've lost the incentive to write it (guess i'm just a nerd then :)). In any case any problems with your LCD routines would be obvious in the simulator.

And don't put yourself down; you're right up there with EW, theushc et. al.
- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

abcminiuser,

Gee, I really didn't have it in mind to discourage your idea. And I realize that you are not implying that, in any way. I feel a little bad because I have discouraged you from trying your idea. It did raise some very interesting questions.

I have my STK500 up and running now. I will be looking at a way to first, obsurve a 50 ns pulse.

I have a Tektronix TDS2012 100 MHz digital storage Oscilloscope and a 60 MHz B&K analog Oscilloscope. I don't know yet if I can reliably detect a pulse that small with either of them. Actually, I'm hoping I can at least see a 5 ns pulse with the TDS2012.

I plan on breadborading (I doubt it will be on a Proto-board) a pulse generator with, hopefully, an adjustable 5 - 1000 ns pulse width to use for a test signal.

Once I determine my capabilities for a test signal, I am going to try the idea in softwareon a Mega64. I think it is a real possibility, down to the 50 ns limit.

I apologise if I discouraged you in any way. One thing I have learned about learning. The real education comes with failure. Knowing what you can and can not do is extreemly important to success.

Someone once said "A failure is mearly one step closer to a successful outcome - if the individual perserveres!"

I have a lot of failed attempts! I like to call them experiments...

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Microcarl, you of course did nothing to discourage me. Actually, it's leading me on a more interesting tangent, extreamly short pulse measurement. That might be an interesting task to tackle somtime. Right now i'm looking for an interesting project to force me to finally learn the few AVR internals i've been avoiding; PWM and the comparitor. If I can get ahold of a RGB LED (quite expensive here, AU$4 per LED is damn steep!) I might try a RS-232 PWM mixing system. If you have any ideas, do share.

Yes, I like experiments. Rarely do I actually do somthing practical with them - hence the reason I finally made a state-machine with a purpose, my Simple Simon Academy project. Incidentally, perhaps I should use PWM with that and add sound....

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

abcminiuser,

Quote:
AU$4 per LED is damn steep!) I might try a RS-232 PWM mixing system.

I have been wanting to play with the Tri-Color LED's too! But like you, I can't justify their cost.

I checked out the TDS2012 scope. It looks like I can measure into the down to 5 ns per centimeter. So, that part is good. The pulse generator that I have will only adjust down to a 200 ns pulse. I'll have to do something about that.

I haven't done anything with PWM on the AVR yet. Though, I have done a good anount with intrrupts using timers for background delay tasks. I designed and successfully implimented a PWM servo motor controller system for my table-top mill using the MC68HC11. I plan on converting the MC68HC11 based servo control system over to the AVR, at some point in time.

I'm pretty adept with RS232, and the FTDI232BM. But, don't know a whole lot about audio. Back in the early 1980's, I designed a six channel analog audio equalizer but, don't remember too much about it. What you don't use, you lose!!!

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually, my dad wants to build an XY router table too - he's bought the constant current supplies for the motors. He now wants me to (eventually) make the controller, which WILL be an interesting task, Two stepper motors, and system for both storing and reading the commands - should be quite an interesting project.

I've yet to find anything interesting to do with the comparitor or PWM which is one of the reasons I never used it. Actually, i'm quite suprised that noone has used a frequency-to-voltage chip yet to convert a single PWM pin into a D/A converter...

Audio's interesting, but seems rather difficult. As far as I can tell, I generate a 5Khz (example) square wave with PWM, and chuck that into an adio amp and a speaker - but I need to go over the datasheets for the 8535 now and find out how to control the PWM. Links welcome :P.

Good luck with your tangent. Let me know how it goes.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

abcminiuser,

I've changed the following because it was a pile of flatulence...

I'v thought about using the analog comparator to create a "Tracking" Analog to Digitad Converter (ADC). In a tracking ADC, the result is pretty much always, +/- one step from the final bit of converstion.

But I think with a "Tracking" ADC, the resolution can get pretty good. It wouldn't be too difficult to do an ADC out to 16 bits, or more. The issues there lie more with the fact that two I/O portd would be required to get 16 bit resolution and, the PCB layout and understanding how to deal with very low noise levels in the surrounding circuitry - and, two I/O ports for the R2R resistor network...

I did a 10 bit successive approximation ADC back in the early 1980's, uning a MC6002 microprocessor, an MC6820 PIO, a DAC1000, and an LM339 comparator, because there were no 10 bit ADC's back then.

II've got to go to bed. I guess down under, it never gets dark, eh? Actually, I wish a lot of you guys were in the same time zone. It would be easier.

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

Last Edited: Sun. Nov 13, 2005 - 02:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Indeed it would be. It's 5:46PM here - but on weekends (day off school tomorrow) I stay up until crazy times - like ~2AM.

Hmmm, interesting comparitor idea. The PWM isn't a real analogue voltage per se (you of course know that) but a F/V chip *would* produce a true analogue voltage as far as I can tell. We should start writing down interesting experiments here and try the best of them.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

miniCabuser, I don't want to be discouraging, but I can't see that it makes much sense to use a F to V converter on a PWM output - the frequency generally stays the same, it's the duty cycle that changes.

Four legs good, two legs bad, three legs stable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John,

Quote:
miniCabuser, I don't want to be discouraging, but I can't see that it makes much sense to use a F to V converter on a PWM output - the frequency generally stays the same, it's the duty cycle that changes.

True statement!

But, he could toggle the timer compare output at 50% and change the period. Thie issue here is that the duty cycle is fixed and the period changes. At the lower output voltages, it would exibit a fair amount of output ripple at the lower frequencies.

But using PWM to charge a R/C network, the period is fixed and the duty cycle changes, providing a conversion voltage with less ripple throughtout the operating range.

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

miniCabuser

I originally thought that was a typo. *sigh*

but I can't see that it makes much sense to use a F to V converter on a PWM output - the frequency generally stays the same, it's the duty cycle that changes.

Hits self on head. Of course, why didn't I think of that :S.

- Dean :twisted:

Make Atmel Studio better with my free extensions. Open source and feedback welcome!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Old post, I know, but I can't help thinking of ways to solve difficult problems...

If the minimum pulse width isn't an issue (i.e., we meet the 50ns pulse minimum), we'll be inside of an interrupt routine. We only have 4 cycles to determine if a pulse is less then 500ns, so instead of trying a bunch of logic with each cycle, let's leave the logic until the end. Sample the port pin 4 times, once on each cycle, and store each result into a separate variable (don't know much about the AVR architecture yet, so if single-cycle adds are available, use those). If the signal is less than 500ns, the last variable will still be a zero (or in the case of adding, less than 4), and you can set a flag. It's a handful of instructions, and therefore perfect for an interrupt routine.

Just an option to think about...