AFsoftserial on a stripped down arduino

For other supported Arduino products from Adafruit: Shields, accessories, etc.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
hcgilje
 
Posts: 75
Joined: Fri Aug 15, 2008 8:51 am

AFsoftserial on a stripped down arduino

Post by hcgilje »

Hi,
I have a setup with arduino (code formatted for lilypad) running on a atmega168 using the internal oscillator of 8mhz, and running at 3.3volts.

it is sending serial commands to a xbee, which works fine. I would also like to monitor the atmega chip using AFsoftserial, but are having problems gettting anything but garble.

I have tried different pins, different cables etc, and I am pretty sure the hardware and electronics works fine.

I have run the exact same code on a arduino diecimila, and AFsoftserial works fine.

So, first of all, does AFsoftserial work with 8mhz setup? I believe I have seen posts where people are using lilypad and AFsoftserial so I would assume it would work?

Any obvious things I could be missing?

best,
hc

mtbf0
 
Posts: 1645
Joined: Sat Nov 10, 2007 12:59 am

Post by mtbf0 »

i took a look at the soft serial library and noticed this bit of code, which i'd guess is a timing delay. there is no similar conditional for f_cpu = 8MHz, so this may be your problem.

Code: Select all

#if (F_CPU == 16000000)
void whackDelay(uint16_t delay) { 
  uint8_t tmp=0;

  asm volatile("sbiw    %0, 0x01 \n\t"
	       "ldi %1, 0xFF \n\t"
	       "cpi %A0, 0xFF \n\t"
	       "cpc %B0, %1 \n\t"
	       "brne .-10 \n\t"
	       : "+r" (delay), "+a" (tmp)
	       : "0" (delay)
	       );
}
#endif
first of all, if this code compiles at all for you your board is not defined as a lilypad to the arduino environment, so i don't understand why your serial comms to the xbee is working.

second, i am not an avr assembler programmer, mostly because i'm too dim to figure out how the inline assembly embedding works in gcc.

but i'll take a crack at interpreting the snippet above.

Code: Select all

sbiw    %0, 0x01           - subtracts 1 from delay
ldi %1, 0xFF               - loads -1 to temp
cpi %A0, 0xFF              - compare low order byte of delay to -1
cpc %B0, %1                - compare high order byte of dela to temp, (with carry)
brne .-10                    - repeat if not equal
: "+r" (delay), "+a" (temp) - this tells us the first param is delay and the second is temp
: "0" (delay)               - this tells us that delay will not survive
changing the subtrahend, (wow, never thought i'd use that word again), of the sbiw instruction to 0x02 should make this work at 8MHz but, alas, only if delay is odd. i'll have to do a little research into how the avr processor flags work before i can give you an actually useful answer.

User avatar
hcgilje
 
Posts: 75
Joined: Fri Aug 15, 2008 8:51 am

Post by hcgilje »

hi,
thanks for taking the time to look into it!
I am no assembly programmer myself, so not sure if I will be able to resolve this on my own if it is a programming issue in the AFsoftserial code.

maybe I was a bit unclear in my post, I am using the hardware serial for communicating with the xbee, not the AFsoftserial.

I verify my arduino sketches as lilypad, and then upload without a bootloader from terminal with the aspusb programmer I have, this works fine.

hc

mtbf0
 
Posts: 1645
Joined: Sat Nov 10, 2007 12:59 am

Post by mtbf0 »

hcgilje wrote: maybe I was a bit unclear in my post, I am using the hardware serial for communicating with the xbee, not the AFsoftserial
no, that was clear. what i meant was that the AFsoftserial code should fail to compile if the arduino environment knows that you're using a lilypad, because the symbol F_CPU would then be set to 8000000 causing the conditional to evaluate false and keeping the whackdelay function from compiling. maybe i didn't look at enough of the code.

this looks like a fun problem, (i.e. i don't have to get anything to compile or run), so i'll be happy to waste a little more time on it.

User avatar
hcgilje
 
Posts: 75
Joined: Fri Aug 15, 2008 8:51 am

Post by hcgilje »

mtbf0 wrote:this looks like a fun problem, (i.e. i don't have to get anything to compile or run), so i'll be happy to waste a little more time on it.
much appreciated!
I just hope its not something really simple not related to code, but I am 97% sure I haven´t done anything really stupid.

btw, the arduino circuit will be the brain of my wind-up birds, a network of mechanical woodpeckers, some photos here:
http://flickr.com/photos/hcgilje/sets/7 ... 588267198/

hc

mtbf0
 
Posts: 1645
Joined: Sat Nov 10, 2007 12:59 am

Post by mtbf0 »

this is a pretty stupid idea, but since the afsoftserial stuff is hardcoded for a 16MHz clock and you're running at 8MHz so everything takes twice as long, you might get away with selecting a baud rate twice what you are really aiming for. so if you want 9600 baud, try

Code: Select all

mysoftserial.begin(19200);
i don't really understand why there isn't a linear relationship between baud rate and _bitdelay

User avatar
hcgilje
 
Posts: 75
Joined: Fri Aug 15, 2008 8:51 am

Post by hcgilje »

:D
your stupid idea works!
thanks!

hc

mtbf0
 
Posts: 1645
Joined: Sat Nov 10, 2007 12:59 am

Post by mtbf0 »

hcgilje wrote::D
your stupid idea works!
cool. stupid rules!

i now understand why the relationship between baud rate and _bitdelay is non linear.

ideally, _bitdelay = (F_CPU + (BAUD / 2)) / BAUD

the (BAUD / 2) term takes care of rounding, so _bitdelay is the number of clock cycles per second divided by the number of bits transmitted per second. unfortunately, there is a rather large chunk of code involved in processing the bits as they pass through. one must also account for the number of clock cycles used in each pass through the wait loop. in the case of AFSoftserial this looks to be either 5 or 6. 6, i think.

so the real world _bitdelay will be the (ideal_bitdelay - some_number_of_cycles_to_process_each_bit) / wait_loop_length.

so it should be possible to work backwards from AFSoftserial to calculate the constant that is subtracted from the ideal _bitdelay and recalculate the whole mess for an 8MHz clock.

maybe when i get home.

what i still don't understand is how you got the hardware serial port to work and the AFSoftserial to compile at the same time. for the hardware serial to work you would have had to have F_CPU defined as 8000000 which would have caused the conditional compilation of whackDelay to not take place, which in turn should have caused all kind of nastiness when it came time to link.

oh, well.

User avatar
jsc
 
Posts: 13
Joined: Wed Nov 05, 2008 1:58 pm

Re: AFsoftserial on a stripped down arduino

Post by jsc »

I've been trying to make sense of the assembly delay loop. From my reading of the data sheet, it should take up delay * 7 + 6 clock cycles:

sbiw takes 2; ldi, cpi, and cpc take 1, brne takes 2 when the branch is taken and 1 when not.
The loop runs delay+1 times through, since it counts down from delay to -1.

This confuses me, because then the calculations of the bit delays for various baud rates don't come out exactly right. For example, at 9600 baud, the bit delay is given as 113:

1 / ((113 * 7 + 6) / 16000000 * 2) = 10038 baud, slightly faster than it should be.

How were these numbers calculated? And is my calculation correct?

User avatar
manu12
 
Posts: 9
Joined: Tue Apr 16, 2013 8:52 am

Re:

Post by manu12 »

mtbf0 wrote:i took a look at the soft serial library and noticed this bit of code, which i'd guess is a timing delay. there is no similar conditional for f_cpu = 8MHz, so this may be your problem.
...
but i'll take a crack at interpreting the snippet above.

Code: Select all

sbiw    %0, 0x01           - subtracts 1 from delay
ldi %1, 0xFF               - loads -1 to temp
cpi %A0, 0xFF              - compare low order byte of delay to -1
cpc %B0, %1                - compare high order byte of dela to temp, (with carry)
brne .-10                    - repeat if not equal
: "+r" (delay), "+a" (temp) - this tells us the first param is delay and the second is temp
: "0" (delay)               - this tells us that delay will not survive
Thank you for this explanation! I was stuck asking myself if is AFsoftserial/newsoftserial is using one of the 3 timers of the ATmega328. In the end, it seems it doesn't.

User avatar
johnoh
 
Posts: 2
Joined: Mon Sep 17, 2012 4:30 am

Re: AFsoftserial on a stripped down arduino

Post by johnoh »

Hi manu12,

Did you get any values together for 8MHz operation? The technique of using 19k2 for a 9k6 on a 8MHz works a treat but I would like to tidy it up somewhat.

User avatar
manu12
 
Posts: 9
Joined: Tue Apr 16, 2013 8:52 am

Re: AFsoftserial on a stripped down arduino

Post by manu12 »

JohnOH wrote:Hi manu12,

Did you get any values together for 8MHz operation? The technique of using 19k2 for a 9k6 on a 8MHz works a treat but I would like to tidy it up somewhat.
Hello,
I didn't try this by myself.
Maybe it could do the trick if you select an 8MHz board in the Arduino IDE (Arduino Pro or Pro Mini (3.3V, 8MHz) w/ ATmega328)?

User avatar
johnoh
 
Posts: 2
Joined: Mon Sep 17, 2012 4:30 am

Re: AFsoftserial on a stripped down arduino

Post by johnoh »

Thanks, I have it working fine. I would however like to have it set up correctly to avoid confusion in the code.

Locked
Please be positive and constructive with your questions and comments.

Return to “Other Arduino products from Adafruit”