how to use AD convertion in Atmega 1281 - c

hi guys im trying alot to make ADC as an input pin in my Atmega1281 controller but no success
all i want is to control a micro servo with a potentiometer
here is my code please assist me with this it wont work on my controller
#define F_CPU 16000000 //16MHz
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
//#include <stdio.h>
//#include "uart/uart.h"
#define PWM_PRESCALLER 64
#define ICR_MAX (long double)F_CPU/PWM_PRESCALLER/50
#define OCR_MIN ICR_MAX/20
#define OCR_MAX ICR_MAX/10
//char uart_s[150];
volatile unsigned long adc_val=0;
volatile unsigned long counter=0;
unsigned long curr_adc=0;
ISR (ADC_vect)
{
adc_val += ADC;
counter++;
}
int main(void)
{
//uart_init(uart_calc_ubrr(F_CPU));
DDRB |= (1<<DDB1);
ICR1 = ICR_MAX;
OCR1A = OCR_MIN;
TCCR1A = (1 << COM1A1) | (1<<WGM11);
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS11) | (1<<CS10);
ADMUX = (1 << REFS0);
ADCSRA = (1 << ADEN)|(1 << ADFR)|(1 << ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
sei();
ADCSRA |= (1<<ADSC);
while(1)
{
if(counter >= 500)
{
cli();
unsigned long round_val = round(adc_val / counter);
adc_val=0;
counter=0;
if(abs(round_val - curr_adc) > 1)
{
curr_adc = round_val;
}
long double ocr = OCR_MIN + ((long double)curr_adc * (OCR_MAX - OCR_MIN)/1024);
/*sprintf(uart_s, "ADC = %8lu, OCR = %f, rounded = %d\r\n", curr_adc, ocr, (int)round(ocr));
uart_send_string((unsigned char*) uart_s);*/
OCR1A = (int)round(ocr);
//_delay_ms(100);
sei();
}
}
}

Related

AVR ATmega328p and MCP3201 issue

I have a problem with SPI Interface in ATmega328p. I wrote a code that can SPI communicate with MCP3201(analog to digital converter), but I received the wrong value from MCP3201. The value should be between 600 - 700, but I get 2.
I use MCP9700(temperature sensor) to received voltage value and convert with ADC with MCP3201. I read the MCP3201' data sheet. It needs to remove trash bit. I wrote the code to show you below.
Can you check my code and schematic?
main.c
#define F_CPU 8000000L
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include <string.h>
#define CS PB2
#define CS_DDR DDB2
#define MOSI DDB3
#define CLK DDB5
void USART_Init(unsigned int ubrr) {
UBRR0 = ubrr;
UCSR0B |= (1 << RXEN0) | (1 << TXEN0);
UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00);
}
void USART_Transmit( unsigned char data ) {
while ( !( UCSR0A & (1 << UDRE0)) );
UDR0 = data;
}
void print(unsigned char *buffer) {
for(int i=0; buffer[i] != 0; i++){
USART_Transmit(buffer[i]);
}
}
void SPI_Init()
{
/* set MOSI CLK CS as Output*/
DDRB |= (1 << CS_DDR) | (1 << CLK) | (1 << MOSI);
// Chip select high
PORTB |= (1 << CS);
// Chip select low
PORTB &= ~(1 << CS);
/* Enable SPI, Master mode, clk/16 */
SPCR |= (1 << SPE) | (1 << MSTR) | (1 << SPR0);
}
uint16_t SPI_READ()
{
uint8_t rx_byte;
uint16_t rx_12bits;
PORTB &= ~(1 << CS); // Chip select low
SPDR = 0xFF; // put dummy byte in SPDR
while(!(SPSR & (1<<SPIF))); // wait for SPIF high
rx_byte = SPDR & 0b00111111; // copy SPDR out
rx_12bits = rx_byte << 7;
SPDR = 0xFF; // put dummy byte in SPDR
while(!(SPSR & (1<<SPIF))); // wait for SPIF high
rx_byte = SPDR >>= 1; // copy SPDR out
rx_12bits |= rx_byte; // Concat bit
PORTB |= (1 << CS); // Chip select high
return rx_12bits;
}
int main(void) {
USART_Init(53);
SPI_Init();
uint16_t sensor;
// uint16_t temp;
unsigned char text[] = "Temperature = ";
unsigned char buffer[10];
while (1) {
sensor = SPI_READ(); // Read data from sensor
// temp = (((sensor/4096.0) * 5) - 0.5) * 100 ;
sprintf(buffer,"%u",sensor ); // convert to string test with raw data
strcat(buffer, " °C\n");
print(text);
print(buffer);
_delay_ms(1000);
}
}
schematic
EDIT 1:
#define F_CPU 8000000L
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define CS PB2
#define CS_DDR DDB2
#define MOSI DDB3
#define CLK DDB5
void USART_Init(unsigned int ubrr) {
UBRR0 = ubrr;
UCSR0B |= (1 << RXEN0) | (1 << TXEN0);
UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00);
}
void USART_Transmit( unsigned char data ) {
while ( !( UCSR0A & (1 << UDRE0)) );
UDR0 = data;
}
void print(unsigned char *buffer) {
for(int i=0; buffer[i] != 0; i++){
USART_Transmit(buffer[i]);
}
}
void SPI_Init()
{
/* set MOSI CLK CS as Output*/
DDRB |= (1 << CS_DDR) | (1 << CLK) | (1 << MOSI);
// Chip select high
PORTB |= (1 << CS);
// Chip select low
PORTB &= ~(1 << CS);
/* Enable SPI, Master mode, clk/16 */
SPCR |= (1 << SPE) | (1 << MSTR) | (1 << SPR0);
}
uint16_t SPI_READ()
{
uint16_t high_byte;
uint16_t low_byte;
uint16_t out_12bits;
PORTB &= ~(1 << CS); // Chip select low
SPDR = 0xFF; // put dummy byte in SPDR
while(!(SPSR & (1<<SPIF))); // wait for SPIF high
/*xx0[B11][B10][B9][B8][B7]*/
high_byte = SPDR; // copy SPDR out
SPDR = 0xFF; // put dummy byte in SPDR
while(!(SPSR & (1<<SPIF))); // wait for SPIF high
/*[B6][B5][B4][B3][B2][B1][B0][B1]*/
low_byte = SPDR; // copy SPDR out
/*xx0[B11][B10][B9][B8][B7] 0 0 0 0 0 0 0 0 */
/* OR */
/*000 0 0 0 0 0 [B6][B5][B4][B3][B2][B1][B0][B1]*/
/*---------------------------------------------------------*/
/*xx0[B11][B10][B9][B8][B7][B6][B5][B4][B3][B2][B1][B0][B1]*/
out_12bits = (high_byte << 8) | low_byte; // Concatenate bit
/*[B11][B10][B9][B8][B7][B6][B5][B4][B3][B2][B1][B0][B1]000*/
out_12bits <<= 3; // Shift left 3
/*0000[B11][B10][B9][B8][B7][B6][B5][B4][B3][B2][B1][B0]*/
out_12bits >>= 4; // Shift right 4
PORTB |= (1 << CS); // Chip select high
return out_12bits;
}
int main(void) {
USART_Init(53); // SPI intial
SPI_Init(); // USART initial
uint16_t sensor;
float temp;
unsigned char text[] = "Temperature = ";
unsigned char buffer[10];
while (1) {
sensor = SPI_READ(); // Read data from sensor
temp = (((sensor/4096.0) * 5.0) - 0.5) * 100.0 ; // Convert Analog value to temperature
dtostrf(temp, 3, 2, buffer); // Convert Float to string
strcat(buffer, " °C\n"); // Concatenate unit
print(text); // Print First Text
print(buffer); // Print temperature and unit
_delay_ms(1000);
}
}
Actually i do not have the chance to test the code, but maybe this helps:
#define F_CPU 8000000L
#define BAUD 9600UL // Used within setbaud.h
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>
#include <util/setbaud.h>
#define CS PB2
#define MOSI PB3
#define MISO PB4
#define CLK PB5
void uart_init() {
#if USE_2X // Defined within setbaud.h
UCSRA |= (1<<U2X); // Setup 8 samples/bit
#else
UCSRA &= ~(1<<U2X); // Setup 16 samples/bit
#endif
UBRR0 = UBRRH_VALUE; // Defined within setbaud.h
UCSR0B |= (1<<RXEN0) | (1<<TXEN0);
UCSR0C |= (1<<UCSZ01) | (1<<UCSZ00);
}
void uart_transmit(unsigned char data ) {
while (!(UCSR0A & (1<<UDRE0)));
UDR0 = data;
}
void print(unsigned char *buffer) {
for(unsigned int i=0; buffer[i] != 0; i++){
uart_transmit(buffer[i]);
}
}
void spi_init()
{
// Set MISO and Chip Select as Input
DDRB &= ~((1<<CS) | (1<<MISO));
// Set pullup resistors for MISO and Chip Select
PORTB |= (1<<CS) | (1<<MISO);
// SPI
// - Mode: Master
// - Prescaler: 16
SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0);
// Setup SCK, MOSI and SS as output
// PORT configuration gets overwritten from SPI controller
DDRB &= (1<<CLK) | (1<<MOSI) | (1<<CS);
}
void spi_select()
{
DDRB &= ~(1<<CS);
}
void spi_deselect()
{
DDRB |= (1<<CS);
}
unsigned char spi_read()
{
SPDR = 0xFF; // Write data into the SPI Data Register and initiate a transmission
// Wait until transmission is Complete
while(!(SPSR & (1<<SPIF)))
asm volatile("NOP");
return SPDR
}
unsigned int mcp3201_data()
{
spi_select();
unsigned char high_data = spi_read();
unsigned char low_data = spi_read();
spi_deselect();
// +-------------------------------+-------------------------------+
// | HIGH | LOW |
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
// | - | - | - | - | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? | ? |
// +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
//
// Value between 0 to (2^12 - 1) = 0 to 4095
return (((high_data & 0x0F)<<8) | low_data);
}
int main(void) {
uart_init();
spi_init();
const unsigned char text[] = "Temperature = ";
unsigned char buffer[100];
while (1)
{
unsigned int mv; = ((mcp3201_data * 5000)>>12); // Analog Voltage in mV
double temp = mv; // Calculate your temperature
dtostrf(temp, 3, 2, buffer); // Convert Float to string
strcat(buffer, " °C\n"); // Concatenate unit
print(text); // Print First Text
print(buffer); // Print temperature and unit
_delay_ms(1000);
}
}
Indeed i have not calculated the temperature. Thats your turn...

blinking a led using timer 1 overflow interrupt in atmega328p

I'm trying to blink a led using ISR for 3seconds, here atmega328p is used. I'm trying to create a 1second delay in isr using TIMER1(16 BIT) and then loop that for 3seconds. LED is connected to PD7, I don't know why it is not blinking, can anyone point out the mistake. I'm using simulIDE, here is the circuit,timer_circuit
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define SET_BIT(PORT,BIT) PORT |= (1<<BIT)
#define CLR_BIT(PORT,BIT) PORT &= ~(1<<BIT)
unsigned int count = 0;
void timer()
{
TCCR1A = 0x00; // Normal mode of operation
TCNT1 = 0xC2F8; // decimal value is 49912
TCCR1B |= ((1 << CS10) | (1 << CS12));
TCCR1B &= ~(1 << CS11); //1024 prescaler
sei(); // Global interrupt
}
int main(void)
{
SET_BIT(DDRD,PD7);
timer();
while(1)
{
TIMSK1 |= TOIE1;
if(count>=3)
{
SET_BIT(PORTD,PD7);
count=0;
}
}
;
return 0;
}
ISR(TIMER1_OVF_vect)
{
count++;
}
This code never turn off the LED ... once the bit is set your code never clear it ... try to toggle the bit instead of set it
#define toggle_BIT(PORT,BIT) PORT ^= (1<<BIT) //this will flip the bit
...
if(count>=3)
{
toggle_BIT(PORTD,PD7);
count=0;
TCNT1 = 0xC2F8; // reset counter
}
update
use volatile access modifier before count variable to tell the compiler that you will Chang it from ISR to make sure that count variable will not delete in optimization
when you set TCCR1B you have to set other bits to zero to operate in normal mode
Recalculate value TCNT1 for 8 MHz which is internal default frequency
full code
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define toggle_BIT(PORT,BIT) PORT ^= (1<<BIT) //this will flip the bit
#define SET_BIT(PORT,BIT) PORT |= (1<<BIT)
#define CLR_BIT(PORT,BIT) PORT &= ~(1<<BIT)
volatile unsigned int count = 0;
void timer()
{
TCCR1A = 0x00; // Normal mode of operation
TCNT1 = 64754; // over flow after 1 sec calculated at 8 MHZ
TCCR1B = ((1 << CS10) | (1 << CS12)); //1024 prescaler
TIMSK1 |= 1<<TOIE1; // Enable timer1 overflow interrupt
sei(); // Global interrupt
}
int main(void)
{
SET_BIT(DDRD,PD7);
timer();
while(1)
{
if(count>=3)
{
toggle_BIT(PORTD,PD7);
count=0;
}
}
return 0;
}
ISR(TIMER1_OVF_vect)
{
count++;
TCNT1 = 64754; // reset to over flow after 1 sec calculated at 8 MHZ
}

ISR(TIMERn_OVF_vect) interrupt not work Atmega 2560

i have a problem whith ISR() - this function is not work. I use Atmel Studio 7, USBASP programmer, AVRDude_Prog 3.3 and RobotDyn board with Atmega 2560(Robotdyn Mega +WiFi R3 ATmega2560+ESP8266).
I want read signal from HC-SR04 sensor for mesurment distance. I read datasheet about Atmega 2560 and settings of my timers counters: start from 0 counter up to 4th counter.I tried set up each one setting of interrupts and it's not help me(
I use LEDs on PORTA for find problem with counters, interrupts and settings. But now i don't have any result.
And this simple code for enable LED, when ISR(TIMER0_OVF_vect) launch not work too, but i copy this from youtube video for test(https://youtu.be/vl5H_Q1slYY?t=1531).
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define LED1 0
#define LED2 1
int main(void)
{
TCCR0B = (1<<CS00) | (1 << CS02); //8Mhz/1024/255
TIMSK0 = (1<<TOIE0);
DDRA = 0xff;
PORTA = 0b00000100;
sei();
while(1)
{
}
}
ISR(TIMER0_OVF_vect)
{
PORTA ^= (1<<LED1);
}
#define F_CPU 16000000UL
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/io.h>
#include <stdio.h>
#define SREG _SFR_IO8(0x3f)
unsigned char OVF_counter, zamer_1, zamer_T, zamer_t, duty;
unsigned long t, T, T1, f, num;
unsigned int rising_1, rising_2, falling;
ISR(TIMER4_OVF_vect)
{
PORTA = 0b00001111;
}
ISR(TIMER0_OVF_vect)
{
PORTA = 0b00000011;
}
ISR(TIMER4_CAPT_vect)
{
}
void init_timer (void)
{
TIMSK4 |= (1 << ICIE4)|(1 << TOIE4);
TCCR4B |= (1 << ICNC4)|(1 << CS42);
TIFR4 |= (1 << TOV4);
TCCR0B = (1 << CS01);
TIFR0 |= (1 << TOV0);
SREG = 0b10000000;
SREG = 0x80;
}
void capture (void)
{
PORTB = 0b00001000;
_delay_ms(10);
PORTB = 0x00;
rising_1 = ICR4;
T=TCNT4;
TCCR4B &= ~(1 << ICES4);
falling = ICR4;
T1=TCNT4;
TCCR4B |= (1 << ICES4);
t = falling - rising_1 ;
}
int main(void)
{
SREG = 0x80;
DDRL = 0x00;
DDRB = 0xff;
DDRA = 0xff;
init_timer();
while (1)
{
capture();
if(t >= 1000000)
{
PORTA = 0b00000000;
}
if(t >= 100000)
{
PORTA = 0b00000111;
}
else if(t >= 1)
{
PORTA = 0b00000011;
}
else if(t >= 0)
{
PORTA = 0b00000001;
}
else
{
PORTA = 0b00001111;
num=0;
}
}
}

AVR USART communication

I am implementing USART communication on an AVR micro-controller. Below is my code. At the moment, I can send a character, send a string and receive a character. I have a method to receive a string.
The method is called char* receive_string() and returns the address of the string that I am receiving. This is the 55 element char array to hold the string, char string[55]. However, for example, when I send the word hello to the micro-controller, this method returns only the first character h. What is it that I am doing wrong?
#include <avr/io.h>
#include <util/delay.h>
#include <string.h>
#include <avr/interrupt.h>
// macro definition
#define bit(n) (1 << n) // bit
#define sbit(v, n) v |= (1 << n) // set bit
#define cbit(v, n) v &= !(1 << n) // clear bit
#ifndef F_CPU
#define F_CPU 16000000
#endif
#define BAUD 9600 // baud rate
#define M_UBRR ((F_CPU/16/BAUD)-1) //contents of UBRRnH and UBRRnL registers
// function prototypes
void usart_init();
void send_char(char);
void send_string(char*);
char receive_char();
char* receive_string();
char string[55];
int main() {
usart_init();
char* msg = receive_string();
sei();
while (1) {
send_string(msg);
_delay_ms(1000);
}
return 0;
}
void usart_init() {
UBRR0H = (M_UBRR >> 8); // setting baud rate
UBRR0L = M_UBRR;
UCSR0B = (1 << TXEN0) | (1 << RXEN0) | (1 << RXCIE0); // enable transmitter and receiver
UCSR0C = (1 << USBS0); // 2 stop bit
UCSR0C = (1 << UCSZ00) | (1 << UCSZ01);
}
void send_char(char byte) {
while (!(UCSR0A & (1 << UDRE0))); // wait until the register is empty
UDR0 = byte; // put a char in the UDR0 register
}
void send_string(char* string) {
int i;
int len = strlen(string);
for (i = 0; i < len; i++) {
send_char(string[i]);
}
}
char receive_char() {
while (!(UCSR0A & (1 << RXC0))); // wait until all data in receive buffer is read
return UDR0;
}
char* receive_string() {
char x;
int len = strlen(string);
int i = 0;
while (i < len) {
x = receive_char();
string[i++] = x;
}
string[len] = '\0';
return (string);
}
strlen(string) in your code does not make sense. How can you get the length of a string that has not been sent yet?
Change that to len = 55 or len = sizeof(string).
In C, strlen counts the number of characters before finding the zero terminator.

Atmega16 USART initialization

I can't for the life of me find why this code is not working to send a byte to my computer terminal window. It receives and works fine when I omit that line though. Receiving and sending also work seperately. Please note that this is over rs485 so I must disable TXEN if I want anything received to make it through the line driver ic.
#define F_CPU 7800000UL // 7.8 MHz
#include <avr/io.h>
//#include <util/delay.h>
#include <avr/interrupt.h>
#include <math.h>
#define USART_BAUDRATE 57600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
volatile unsigned int value = 0;
volatile int recievearray[4] = {0,0,0,0};
volatile int x=0;
void USART_Init(void)
{
DDRD = 0x7E; //you have to assign TXEN as output for some reason
//PORTD = 0xFF;
UCSRB = 0;
//Put the upper part of the baud number here (bits 8 to 11)
UBRRH = (unsigned char) (BAUD_PRESCALE >> 8);
//Put the remaining part of the baud number here
UBRRL = (unsigned char) BAUD_PRESCALE;
//PORTD = 2;
// ASYNCRONOUS
UCSRC = (0 << UMSEL);
//Enable the receiver and transmitter
UCSRB = (1 << RXEN) | (1 << TXEN) | (0 << UCSZ2) | (1<<RXCIE);
//Set 1 stop bits and data bit length is 8-bit
UCSRC = (1 << URSEL) | (0 << USBS) | (3 << UCSZ0);
//no parity
UCSRC |= (0 << UPM1);
UCSRC |= (0 << UPM0);
}
void USART_SendByte(uint8_t u8Data)
{
UCSRB = (1 << TXEN) | (1<<TXCIE);
// Wait until last byte has been transmitted
while((UCSRA &(1<<UDRE))==0);
UDR = u8Data;
UCSRB = (0 << TXEN) | (0<<TXCIE);
}
void Led_init(void){
DDRC = 0xFF;
}
ISR(USART_RXC_vect)
{
//PORTC = 0xFF;
while((UCSRA &(1<<RXC)) == 0);
value = UDR;
if (x < 4)
{
recievearray[x++] = value;
}
else
{
x = 0;
recievearray[x++] = value;
PORTC = 0x00;
}
}
int main(void)
{
USART_Init();
sei();
Led_init();
//PORTC = 0xFF;
for(;;)
{
if (recievearray[0] + recievearray[1] + recievearray[2] + recievearray[3] > 100)
{
PORTC = 0xFF;
USART_SendByte(value);
}
//_delay_ms(1000);
}
}

Resources