So, I'm making an own "UART" on Arduino Uno pin 7 and 8. I have USB to 3-pin TTL from my laptop to my Arduino to send the characters. I'm working on the receive functionality right now. I have a pin change interrupt running and when it is detected I enable the timer2 interrupt to receive the bits at 9600 baud. But for some reason I can't seem to receive the data I want.
My code:
When I send a character from putty on the COM port I do receive something but it has question marks and different characters(see attached image). Putty setting (for now) are: 9600 baud, 8 data bits, no parity, one stop bit, local echo force on.
I'm trying to receive the bits at 9600 baud but when I have that working I want to work on setting the baud to 3x9600 so I can sample 3 times per bit to get the correct bit. But I wanted to get an easier version with the interrupts working first.
Does anyone see what I'm doing wrong I have done a lot of research and trying but can't seem to get it right.
CrossRoads:
Wouldn't using one of the Software Serial librarys work better?
Yes, but i want to create my own just for learning. And I want to use to pin change interrupt in combination with the timer interrupt and not the delay like in the Software Serial library.
You seem to be enabling and cancelling the timer2 interrupt all over the place.
Don't do that, leave it enabled all the time - you will lose interrupts and get spurious ones doing this
sort of thing. The only thing you should do with enabling / disabling interrupts in code after setup() is
to use noInterrupts() and interrupts() around critical sections.
The way to inhibit interrupt processing once the code's running is to tell the ISR using a boolean
variable:
volatile bool enable = true ;
ISR (.....)
{
if (!enable)
return ;
..
..
}
Then the main program can control the ISR as it sees fit without risk of spurious or missed interrupts.
The noInterrupts()/interrupts() technique is guaranteed to queue pending interrupts without error, so
long as only one of each type is outstanding.
Disabling and re-enabling a particular interrupt is not guaranteed to do this at all, it all depends on
the particular interrupt in fact.
gcjr:
can you explain how your code is intended to work?
So, when I receive the start bit, pin 7 goes from high to low so the pin change interrupt is done. In the PC interrupt I turn on the timer interrupt to receive the bits at the 9600 baudrate I set. For every time the timer interrupt is done I shift the bit and check if the pin is High or low to check what the bit is. When I received all bits I add the corresponding character to the buffer.
When the PC interrupt is first done I disable it so i can receive the bits using the timer interrupt and the PC interrupt doesn't interfere.
casperm10:
So, when I receive the start bit, pin 7 goes from high to low so the pin change interrupt is done. In the PC interrupt I turn on the timer interrupt to receive the bits at the 9600 baudrate I set. For every time the timer interrupt is done I shift the bit and check if the pin is High or low to check what the bit is. When I received all bits I add the corresponding character to the buffer.
do you start sampling after 1.5 bit periods and then each bit period for the next 7 bits so that you sample in the middle of the bit period?
gcjr:
do you start sampling after 1.5 bit periods and then each bit period for the next 7 bits so that you sample in the middle of the bit period?
So, I fixed some bugs and started testing some more, and came to the conclusion that the Pin Change interrupt wasn't not called because I had the wrong PCint I used pcint0 instead of pcint2, because i used a different pin before to receive face palm.
I am receiving now, still question marks but it's about the timing now, like you said so, I will get going on that.
I've chnaged to code a bit to sample 3 times per bit. I think I did it correct but I'm stuck on a high pin. The digitalRead(rxPin) is always high when i check it, although the pin change interrupt does work so it has to change. So, I don't really now why it doesn't go low when a bit is low. The output of data is always just 11111111. Does anyone see something that I'm doing wrong especially with the pin not changing.
Code now:
i would capture a timestamp (micros()) as well as the the pin value. have a routine to dump the results after a sufficient # of sample (3 * 12 bits)
So, when i do this the first 9 bits are 1100 micros difference and after that it's around 160 micros difference. The pin is always high except for the first 2 these are sometime 0 but the first 4 have to be 0 because of the start bit. But the sampling times are off so wouldn't expect it from the pin read. I have no clue why the times are so different.
I have 28800 baudrate so, 28800 bits per second so 1 bit is ((1/28800)*1000000) = 35 right? But it's nowhere near. Is the receive code too long or something i have no idea.
I setup timer 2 on 9600 baud but when I start printing values like this, when recvIt ==9 the stop bit should be on the line so no more pin changes but it does pin change still after that, so the baud rate is of? But i set it correctly. For some reason the timing is of, I don't know why. Maybe something is interfering but I don't know.