UKHAS Wiki

UK High Altitude Society

User Tools

Site Tools


communication:avr

This is an old revision of the document!


AVR radio project (by Laurenceb)

This is designed for data downlink in flight, and based on rocketboys pulse shaping technique. The plan is to use the pwm output of an avr to modulate aradiometrix ntx2 module. This technique has previously been demonstrated to have a range in excess of 200Km using a pulse shaping modulation technique.

Hardware design

The nxt2 module has an enable pin, that can be used by the avr to save power whilst not transmitting

This apparently takes 3v logic levels, but there is nothing said about a TTL or 5v enable input, only that the voltage on any pin must not exceed vcc, so, for good measure theres a resistor between the avr and the EN pin. One nice feature of the nxt2 is the fact that there appears to be no schmitt trigger on the data input, allowing it to be driven with analogue signal levels. However, the behaviour when subjected to high frequency pwm input has not been examined, so filtering on the pwm will be needed, using an LCR or RC filter. At 300 baud downlink, the frequency of our desired modulation will be in the 150Hz or less range, whereas at 16Mhz clock, the pwm fundamental frequency is 62Khz, so filtering is a fairly easy job.

T1 and T2 are 20K and 40K trimpots respectively, C2 and C5 are 100nF, and R2 R5 are 1K. C4 and C5 should be 20pF other values are not critical

The pcb is designed to fit onto the bottom of an NTX2 module, with a board edge SMA connector from Johnson components (part no 142-0711-821) providing an easy to use antenna connection.

AVR code

The code has not been tested with anything other than an led as yet, the next aim is to try with a voltage controlled oscillator, and truetty. It will run on a mega48 at 16 or 20Mhz. The RBAUD, CBAUD and F_CPU constants, along with the target uc and all important settings are located at the top of the makefile. The lookup table is then generated by tabletool and stored in program space. You will need the procyon avrlib code timerx8.c, uart.c, and buffer.c to get this to work, but remember to edit the uart code correctly first - see here for more information on procyon

Main sourcecode

Note that this includes printf debug statements and has inverted enable pin output when debug is defined, to allow an led to go between B.1 and B.2

#include "Radiopulseshaper.h"
 
//#define RBAUD x - use the makefile for these
//#define CBAUD x
//#define pulse_res (F_CPU/256/RBAUD) //<--  RBAUD with clkdiv=1
 
 
#ifdef debug
int get_char0(FILE* stream)
{
 int c=-1;
 while(c==-1)
 {c=uartGetByte();} //getchar gets the stream, loop until we get something
 return (u08) c;
}
 
 
int put_char0(char c, FILE *stream)
{
   if(uartReadyTx || !uartBufferedTx ) //if buffer is empty or we arent buffered
   {uartSendByte(c);                  //sends directly to uart
	return 0;
   }
   else
   {
    //while(!bufferAddToEnd(Txbuff0,c));    //send the character to buffer
    if(uartAddToTxBuffer(c))
    {return 0;}
    else
    {return -1;}
   }
}
#endif
 
 
void overflow()
{
static u08 bufone;
timer1PWMASet(bufone);
timer1overflows++;
if(radioout)
 {
  if(position<pulse_res_minus2)
  {position++;}
 }
else
 {
  if(position)
  {position--;}
 }
bufone=pgm_read_byte(&sin_l[position]);
}
 
void send(unsigned char c)
{
 u08 n;
 radioout=0;                              //start bit
 timer1overflows=0;
 while(timer1overflows<pulse_res);
#ifdef debug
 printf("send\r\n");
#endif
 for(n=0;n<=7;n++)                        //byte
 {
  radioout=c&(1<<n);
  timer1overflows=0;
  while(timer1overflows<pulse_res){};
#ifdef debug
  printf("n= %d p= %d\r\n", (int) n, (int) position );
#endif
 }
 radioout=1;                              //stop bit
 timer1overflows=0;
 while(timer1overflows<pulse_res);
#ifdef debug
 printf("exit\r\n");
#endif
}
 
void tuneup()
{
 radioout=0;
 timer1overflows=0;
 while(timer1overflows<(unsigned int)(pulse_res));
#ifdef debug
 cbi(PORTB,2);                                                    // allow output to stabilise before turn on
#else 
 sbi(PORTB,2);
#endif
 while(timer1overflows<(unsigned int)(2*RBAUD*pulse_res));          // 2 second normally
 radioout=1;
 timer1overflows=0;
 while(timer1overflows<(unsigned int)(2*RBAUD*pulse_res));          //2 seconds with altered definition at top
}
 
int main()
{
int c;
u08 radio=1,lenght=0,nodata=0;
DDRB=0b00000110;
cbi(PORTB,2);                                  //note inverted enable pin
uartInit(); 
uartSetBaudRate(CBAUD);
#ifdef debug
FILE mystdio0 = FDEV_SETUP_STREAM(put_char0, get_char0, _FDEV_SETUP_RW);  //so we can printf to the radio
stdout = &mystdio0; //set our stdio out function
stdin = &mystdio0; // set our stdio in funciton 
#endif
sei();
timerInit();
timer1SetPrescaler(TIMER_CLK_DIV1);
timer1PWMInitICR(255);
timer1PWMAOn();
timerAttach(1,overflow);
tuneup();
#ifdef debug
printf("setup ok\r\n");
#endif
while(1)
{
 c=uartGetByte();
 if(c!=-1)                   //there was something in the buffer
 {
#ifdef debug  
  printf("Got %c\r\n",(char) c);
#endif
  if(lenght>120 || !radio)
  {
   radio=1;
   //cbi(PORTB,2);
   tuneup();
   lenght=0;
  }
#ifdef debug
  printf("sending now, lenght= %d\r\n",(int) lenght);
#endif
  send((unsigned char) c);
  lenght++;
  nodata=0;
 }
 else
 {
  radio=0;
#ifdef debug
  sbi(PORTB,2);
  printf("waiting...%d\r\n",(int) nodata);
#else
  cbi(PORTB,2);
#endif
  for(c=0;c<100;c++)
  {_delay_ms(5);}
  nodata++;
  if(nodata>20)
  {
   radio=1;
   //cbi(PORTB,2);
   tuneup();
   radio=0;
#ifdef debug
   sbi(PORTB,2);
#else
   cbi(PORTB,2);
#endif
   nodata=0;
  }
 }
}
return 0;
}

Header file

#include <avr/interrupt.h>
#include <stdio.h>
#include <avr/io.h>
#include <stdlib.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
 
 
#include "global.h"
#include "uart.h"
#include "buffer.h"
#include "avrlibtypes.h"
#include "avrlibdefs.h"
#include "timerx8.h"
#include "default\table.h"
 
#define pulse_res_minus2 pulse_res-2 
//#define debug                          //uncomment for debugging
 
 
void overflow(void);
void tuneup(void);
#ifdef debug
int put_char0(char c, FILE *stream);
int get_char0(FILE *stream); 
FILE mystdio0;
#endif
volatile unsigned int timer1overflows;
u08 radioout=1;
volatile int position;

Changes to uart.h

#ifndef UART_TX_BUFFER_SIZE
//! Number of bytes for uart transmit buffer.
/// Do not change this value in uart.h, but rather override
/// it with the desired value defined in your project's global.h
 #ifdef debug
  #define UART_TX_BUFFER_SIZE		0x00FF
 #else    
  #define UART_TX_BUFFER_SIZE		0x0000
 #endif
#endif

Change to uart.c

comment out line 244 as so

	//uartBufferedTx = FALSE;

Compile time code

Tabletool source

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
 
int main(int argc, char *argv[])
{
  long F_CPU=(long) atoi(argv[argc-3]);
  int RBAUD=(int) atoi(argv[argc-2]);
  int CBAUD=(int) atoi(argv[argc-1]);   
  int pulse_res=(F_CPU/256/RBAUD); 
  float c;
  FILE *fone;
  printf("Tabletool by Laurenceb\n configuring radio to use:\n //F_CPU=%d\n //RBAUD=%d\n //CBAUD=%d\n //pulse_res=%d\n",F_CPU,RBAUD,CBAUD,pulse_res);
  fone = fopen("table.h","w+");
  fprintf(fone,"//Lookup table \n// F_CPU=%d\n// RBAUD=%d\n// pulse_res=%d\n",F_CPU,RBAUD,pulse_res);
  fprintf(fone,"#define pulse_res %d\n",pulse_res);
  fprintf(fone,"const uint8_t sin_l[%d] PROGMEM={",pulse_res);
  for(c=0;c<pulse_res;c++)
  {
   fprintf(fone,"%.0f,", 255.0*(1.0-cos(M_PI*c/pulse_res))/2.0);
  }
  fprintf(fone,"};\n");
  fclose(fone);
  //system("PAUSE");	
  return 0;
}

Makefile

###############################################################################
# Makefile for the project Radiopulseshaper
###############################################################################

## General Flags - change F_CPU and RBAUD to suit your project
## Begin user editable section
PROJECT = Radiopulseshaper
MCU = atmega168
TARGET = Radiopulseshaper.elf
CC = avr-gcc.exe
F_CPU=16000000UL
RBAUD=300
CBAUD=4800
## programmer configuration
programmer=avrdude 
programmerinstallation=$(path)
programmerarguments=-p m168 -b 19200 -c avr911 -e -P com7 -U flash:w:./Radiopulseshaper.hex:i -v
## For other programmers change the -c flag and the -P flag
## End user editable section

## Options common to compile, link and assembly rules
COMMON = -mmcu=$(MCU)

## Compile options common for all C compilation units.
CFLAGS = $(COMMON)
CFLAGS += -Wall -gdwarf-2               -DF_CPU=${F_CPU} -DRBAUD=${RBAUD} -DCBAUD=${CBAUD} -Os -funsigned-char -funsigned-bitfields
CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d 

## Assembly specific flags
ASMFLAGS = $(COMMON)
ASMFLAGS += $(CFLAGS)
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2

## Linker flags
LDFLAGS = $(COMMON)
LDFLAGS +=  -Wl,-Map=radio.map


## Intel Hex file production flags
HEX_FLASH_FLAGS = -R .eeprom

HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings


## Libraries
LIBS = -lc -lm -lprintf_flt -lprintf_min -lscanf_flt -lscanf_min 

## Objects that must be built in order to link
OBJECTS = Radiopulseshaper.o buffer.o timerx8.o uart.o 

## Objects explicitly added by the user
LINKONLYOBJECTS = 

## Build
all: $(TARGET) Radiopulseshaper.hex Radiopulseshaper.eep Radiopulseshaper.lss size
	${programmerinstallation}${programmer}${programmerarguments}
     

## Header production code
table.h:
	tabletool ${F_CPU} ${RBAUD} ${CBAUD}


## Compile
Radiopulseshaper.o: ../Radiopulseshaper.c table.h
	$(CC) $(INCLUDES) $(CFLAGS) -c  $<

buffer.o: ../buffer.c
	$(CC) $(INCLUDES) $(CFLAGS) -c  $<

timerx8.o: ../timerx8.c
	$(CC) $(INCLUDES) $(CFLAGS) -c  $<

uart.o: ../uart.c
	$(CC) $(INCLUDES) $(CFLAGS) -c  $<

##Link
$(TARGET): $(OBJECTS)
	 $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)

%.hex: $(TARGET)
	avr-objcopy -O ihex $(HEX_FLASH_FLAGS)  $< $@

%.eep: $(TARGET)
	-avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0

%.lss: $(TARGET)
	avr-objdump -h -S $< > $@

size: ${TARGET}
	@echo
	@avr-size -C --mcu=${MCU} ${TARGET}

## Clean target
.PHONY: clean
clean:
	-rm -rf $(OBJECTS) Radiopulseshaper.elf dep/* Radiopulseshaper.hex Radiopulseshaper.eep Radiopulseshaper.lss Radiopulseshaper.map table.h


## Other dependencies
-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)
communication/avr.1198536451.txt.gz ยท Last modified: 2008/07/19 23:30 (external edit)

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki