UART, Bluetooth and someone who's new to all this

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

Hello!

 

So I have a project. It's nothing fancy and so far it's been easy to build both physically and in programming. However, I've reached a point where I'm going to need to use a bluetooth module with my project. I have a CC-41a (a HM-10 knock-off) which I've been able to use with my Arduino (that I use as a middle step before trying to make it work with the ATMega328p) just fine, successfully turning on and off a led with the help of my iPhone. So that's all nice.

 

With the Arduino everything was pretty straightforward: I used a software serial and set up which pin was RX and which pin was TX. I was ready to move on to the real deal and started searching the web for tutorials and information. I see myself as at least somewhat of a fast learner, as soon as I get a push in the right direction. But this time it's hard. I've spent hours trying to find something to give me a start, but I find nothing.

 

Right now all I want to do is setup the ATMega to send and receive serial transmissions through it's RX and TX pins to and from the Bluetooth module. That's all. But I can't find how to set it up. I've found Peter Fleury's uart library, but the documentation is hard for me to make anything of. 

 

So, to make sure I get to an actual question (and stop whining): If someone could explain to me just how to set up the initialising code with UART to my Bluetooth module with a baud rate of 9600, I would be immensely happy. If I could get some example code as well, that would be even more awesome.

 

Thanks, Christian

 

PS The picture just shows my setup for trying to make the UART and Bluetooth work

Attachment(s): 

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

The things to do is always take it one step at a time.

 

You have two distinct things:

 

  1. Using the UART;
  2. Using the BT module.

 

So take one at a time.

 

I'd suggest starting with the UART - there are plenty of tutorials for that.

 

Then try working with the BT module connected to a PC terminal program.

 

Then, once you know how to use the UART, and you know how to use the BT module, you can bring the two together.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here are a couple tutorials on using the AVR USART: Link1 and Link2

 

From the photo attached to post#1, you don't have a crystal attached to the uC.

 

The uC comes from the factory with the internal 8MHz RC oscillator enabled and the divide-by-eight (CKDIV8) fuse programmed, so the CPU is running at 1MHz.

 

With the CPU running at 1MHz, to set USART to 9600 baud you need to set U2X0 to 1 in register UCSR0A and UBRR0 to 12.  See Table 20-4 in ATmega328P datasheet.

 

You typically need to calibrate the RC Oscillator to use the USART.  See this post from clawson: Link

 

Edit: corrected links.

 

 

Last Edited: Thu. Dec 29, 2016 - 09:59 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Two things I see in your bread board pic that needs to change before you will have successful usart comms,

1) No power bypass caps (0.1uf) on both pair of power pins

2) No xtal, a known and stable clock source is needed for usart comms, the internal RC is not stable/accurate enough to use for beginners!

 

Why do beginners think they can just drop a chip on a bread board and it will work? Why not use a proven piece of h/w like an arduino pro-mini or nano which already has the basic needed h/w?

 

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274

 

 

 

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

@Jim, you might be a little harsh on beginners. None of us as beginners knew all/any of the shortcuts to success until we learned by bitter experience or by having someone further down the experience path point them out to us.

 

@Christian, Jim's "suggestion" to use an Arduino pro-mini or Nano is one that is meant to skip some of life's (sometimes bitter) lessons. Of course if you wish to have a hardware view of the world, using a breadboard and discovering the important subtleties of supporting components can be a worthwhile experience. If you are more interested in the software side of things, you can quickly jump to that area of learning by using cheap, well tested hardware modules such as the Arduino units that skip the hardware lessons. When you run into problems, help is more easily provided if we all share the same hardware knowledge... and components. Most of us have several Arduinos sitting around just waiting to test ideas.

 

And Christian.. welcome to AVRFreaks.

 

Cheers,

 

Ross

 

Ross McKenzie ValuSoft Melbourne Australia

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

ki0bk wrote:
Why do beginners think they can just drop a chip on a bread board and it will work?

Who ate your bowl of sunshine this morning, Thundercloud? 

 

I think Joey Morin's signature best explains your frustration:

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

 

 

JIm

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

Hello again everyone! 

 

I heeded your advice and read up some more. I've now gotten an (albeit a small one) understanding of UART and how to code it.

 

Now, I have a new problem. It doesn't really have to be a problem, but I'm thinking that I might save some work.

 

Right now my LCD goes into pins D0 and D1, which are also my RX and TX. As soon as I initialise my UART, everything I try to put on my LCD is scrambled. Now I could just loosen the two cables and solder them to two other pins (which I will if there's no easy answer to this). But I wonder if there's a way I can use the same pins, but "shut down" the UART as soon as it isn't used.

 

What's your idea?

 

Thanks, Christian

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

The UART in most AVR takes control of the TXD pin when you set the TXEN bit and takes control of the RXD pin when you set the RXEN bit. If you want to relinquish its control then clear those bits.

 

However it's not exactly a great design to have both LCD and comms on the same pins in the first place. Why not move the LCD to some other port (in most LCD code it's just a define at the top of some configuring header file).

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

clawson wrote:

The UART in most AVR takes control of the TXD pin when you set the TXEN bit and takes control of the RXD pin when you set the RXEN bit. If you want to relinquish its control then clear those bits.

 

However it's not exactly a great design to have both LCD and comms on the same pins in the first place. Why not move the LCD to some other port (in most LCD code it's just a define at the top of some configuring header file).

 

Thanks for the answer! So it is possible - but as you say - impractical. Then I'll just let those two LCD pins use two other digital pins on the ATmega.

 

I guess I was hoping to get off easy.. :-)

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

Naccache wrote:
Right now my LCD goes into pins D0 and D1, which are also my RX and TX. ...  I wonder if there's a way I can use the same pins, but "shut down" the UART as soon as it isn't used.

Yes - it's called Multiplexing.

 

But you would need some extra signal to control whether your D0 and D1 are going to the LCD or the serial port.

 

So you are really only "saving" one pin - but adding a whole bunch of extra complexity to manage it.

 

And it means you have to be absolutely sure that you will never, ever want to use them both at the same time - a limitation that will almost certainly come back to bite you (Murphy's Law).

 

So, while it is possible - it is generally best avoided!

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Naccache wrote:
I guess I was hoping to get off easy.. :-)
"Easy" is moving the LCD to other pins.

 

What this highlights is a common theme here on Freaks. Folks are so keen to get something going/working that they just whack it onto the nearby pins and start typing some C into their editor. Neither is a great idea. All projects benefit form a design phase where you take stock of what it is you ultimately want to achieve and consider things like memoery budgets, time budgets and pin budgets. Does the micro you plan to use have enough memory? Will there be enough CPU time to do everything that is required? What will be connected to which pins and so on? The latter should be easy. If your design is going to use an SPI device, an I2C device, a UART connection and 8 port pins then obviously, because in most AVR, the pin assignment for peripherals is fixed you already know which pins the SPI and I2C and UART are on. So you sketch out a simple system diagram on a piece of paper (or get fancy and do it in CAD if you want) and show the AVr with it's 8/14/20/28/40/+ pins and then the devices attached to things like SPI, I2C, etc and finally it will be obvious which port(s) have the remaining 8 (or however many) pins that you can use for the non-fixed pin assignments.

 

Same goes for the software design. Don't just start at line one in your C editor and type "int main(void) {" and then a whole bunch of lines after that. Take a step back and think about the software design. Presumably the UART, I2C and SPI are going to have UART_init(), SPI_init() and I2C_init() then, ongoing you are going to need "get data" and "put data" routines for each (though some may be unidirectional). So plan those out too. In fact you may find it easiest to put all the UART code in a uart.c and have calls like uart_init(), uart_getchar(), uart_putchar() and then more complex functions built on those.

 

A bit of upfront planning pays off massively in the final implementation.

Last Edited: Fri. Jan 27, 2017 - 12:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Naccache wrote:
I guess I was hoping to get off easy.. :-)
"Easy" is moving the LCD to other pins.

 

Yeah, I did that and now the LCD prints correctly both before and after the UART has been initialised.

 

Now, when I use the arduino setup, where I have the bluetooth adapter in the arduino. I use 9600 baud and I can communicate fine through the serial monitor. I connect with my iPhone to the bluetooth adapter as well and then the bluetooth adapter works as a bridge. Anything I write in the serial monitor on the computer shows up on my computer screen and the other way around. 

 

Now I've connected everything to my arduino and I'm using Fleurys uart library. Now I'm trying both to receive data as well as sending it. For example, I use this:

 

#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include "lcd.h"
#include "uart.h"


int main (void)
{	
	lcd_init(LCD_DISP_ON);
	lcd_gotoxy(0,0);	
	lcd_puts("Test");
	
	
	uart_init(UART_BAUD_SELECT(9600, F_CPU));
	sei();	
	
	lcd_puts("Test");
	
	DDRB = 0b00000100;
	
	uart_puts("TESTTEST");
	uart_putc("TESTTEST");
	uart_puts_p("TESTTEST");
	
	int r = 0;
	int c;
	while (r<1){
		c = uart_getc();
		while (c & UART_NO_DATA){
			c = uart_getc();
		}
		lcd_clrscr();
		lcd_puts("Signal arrived");
	}
	
	return(0);
}

I compiles and runs. But nothing shows up on my cell phone serial monitor. When I enter anything at all in the cell phone serial monitor I can see that the LCD screen looses a small amount of voltage and the contrast changes. So it is receiving *something*. 

 

But if I try to print "c" on the LCD screen nothing shows up. What am I missing?

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

Naccache wrote:
What am I missing?
Don't try to make everything work all at once. Concentrate on one module - LCD perhaps or UART? Then work on just making sure that one part of it works for all its supposed to do. You need to treat each module as a well tested "black box". So you work in uart_*() until you know they all work in all circumstances then after that it's just a "black box" you can trust. Same goes for LCD.

 

If you just put it all together, switch on and it "doesn't work" you may otherwise have no idea in what area the fault lies.

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

clawson wrote:

Naccache wrote:
What am I missing?
Don't try to make everything work all at once. Concentrate on one module - LCD perhaps or UART? Then work on just making sure that one part of it works for all its supposed to do. You need to treat each module as a well tested "black box". So you work in uart_*() until you know they all work in all circumstances then after that it's just a "black box" you can trust. Same goes for LCD.

 

If you just put it all together, switch on and it "doesn't work" you may otherwise have no idea in what area the fault lies.

 

Maybe I wasn't clear: The LCD works fine on it's own. I can print to it and use Fleury's lcd-library without any trouble. But it's the UART that's not giving me the results I'm expecting. For example, if I use lcd_puts("Test"); into the code, it prints just fine. But I try to get something from or to the bluetooth, it gives me nothing.

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

So that just says that something like the UART baud rate is wrong then doesn't it? The way you can test that is to test each end against a different diagnostic device (ie a PC). Forget the Bluetooth and, instead, just connect the AVR to a PC using a USB-TTL cable and standard terminal software on the PC. Now try two way transmission. Does that work? If it does then you can be confident in the AVR end of things and the fault must lie in the phone+Bluetooth or the Bluetooth+AVR part of the equation. If it doesn't (my guess) then it's probably the AVR serial that is at fault and (as it says somewhere) 99.9% of the time it's because the AVR is not running at the speed the programmer believes and has programmed for.

 

I'm looking at the picture in post#1. Maybe it's hidden but where is the 16MHz crystal in that? I rather suspect you are just using a 328 "as it comes" and that means CKDIV8 programmed and CKSEL set to use the intRC. There'd be several potential issues with that. The intRC is not very accurate. The CKDIV8 means 1MHz not 8MHz. 9600 baud has a 7% error on 1MHz. If the code is written to do 9600 on 16MHz the UBRR value is wrong for 1MHz anyway.

 

To make your home brew as close as possible to an Arduino I'd just splash the entire 10 cents on a 16MHz crystal and two capacitors then I'd use your ISP programmer to remove CKDIV8 and to set CKSEL to enable the use of the cystal. Now Serial code from Arduino will just work identically on this stand alone as it is all going at the same speed.

 

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

Fair enough, I guess I'll have to go get the capacitors and a crystal. That does suck though, I was hoping to get this up and going by this evening.

 

Well, maybe next week. Big thanks for the advice!

 

 

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

You can try to only change CKDIV8 (if you haven't already). That will switch the 328 from 1MHz(ish) to 8Mhz(ish). Usually you'll be lucky and that will be "close enough". 9600 *is* technically possible on 8Mhz but obviously:

#define F_CPU 1000000UL

needs to change so that what is calculated here:

	uart_init(UART_BAUD_SELECT(9600, F_CPU));

changes too to reflect the fact that it's 9600 on 8MHz.

 

While this may work the "best" solution for UART comms is quartz so I'd still press ahead with the idea of getting a 16Mhz crystal and a couple of capacitors.

 

If you really wanted to stick with 1MHz (because you don't fancy reprogramming fuses) then you may be able to make that work too as you could tune out the 7% error that 9600 on 1MHz usually has by adjusting OSCCAL so that the chip is running at something slightly off from 1MHz. You may  need a bit of experimentation (a for() loop can help with this) to find the optimum OSCCAL value to use in this case.

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

9600baud@1mhz should be doable with "double speed"? There is macro to calculate the values for that in the fluery's code.

 

 

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

Wow, you're right. I just added _DOUBLE_SPEED and now it works fine. Big thanks!

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

Even if you now got it to work for testing, you should still get the crystal for reliable operation.

 

 

Ps. Take a look at this at somepoint to get all functionality from your Bluetooth modules. https://forum.arduino.cc/index.p...