Skip to content

Instantly share code, notes, and snippets.

@prostosergik
Last active May 4, 2019 20:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save prostosergik/3f32c56ecdf36d12505002c51eff77ae to your computer and use it in GitHub Desktop.
Save prostosergik/3f32c56ecdf36d12505002c51eff77ae to your computer and use it in GitHub Desktop.
TNE scooters controller via UART implementation
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "uart.h"
// #define DEBUG (1)
uint8_t calcCRC();
static int analog_read();
long map(long x, long in_min, long in_max, long out_min, long out_max);
// int mmap(int x);
uint8_t buffer[20] = {1, 20, 1, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, 0, 0, 5, 43}; //19 is CRC
int main(void)
{
int speed = 0;
_delay_ms(500);
int initSensor = analog_read();
_delay_ms(300);
DDRB &= ~_BV(PB4); // set data pin as INPUT
while (1) {
speed = map(analog_read(), initSensor, 850, 0, 5); // read analog value from sensor
// speed = analog_read();
// speed = mmap(analog_read());
#ifndef DEBUG
buffer[16] = speed;
buffer[19] = calcCRC();
for(int i=0; i<20;i++) {
uart_putc(buffer[i]);
}
#endif
#ifdef DEBUG
uart_putu(speed);
uart_putc('\n');
#endif
_delay_ms(28);
}
}
uint8_t calcCRC() {
uint8_t crc = 0;
for (int i = 0; i < 19; i++) {
crc ^= buffer[i];
}
return crc;
}
int analog_read()
{
uint8_t low, high;
ADMUX = _BV(MUX1); // ADC2
ADMUX &= ~_BV(REFS0); // explicit set VCC as reference voltage (5V)
ADCSRA |= _BV(ADEN); // Enable ADC
ADCSRA |= _BV(ADSC); // Run single conversion
while(bit_is_set(ADCSRA, ADSC)); // Wait conversion is done
// Read values
low = ADCL;
high = ADCH;
// combine the two bytes
return (high << 8) | low;
}
long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min + 1) / (in_max - in_min + 1) + out_min;
}
// int mmap(int x)
// {
// if(x <= 240) return 0U;
// if(x > 240 && x <= 380) return 1U;
// if(x > 380 && x <= 520) return 2U;
// if(x > 520 && x <= 660) return 3U;
// if(x > 660 && x <= 800) return 4U;
// if(x > 800) return 5U; else { return 0U; }
// }
MCU=attiny13
FUSE_L=0x6A
FUSE_H=0xFF
F_CPU=1200000
CC=avr-gcc
LD=avr-ld
OBJCOPY=avr-objcopy
SIZE=avr-size
AVRDUDE=avrdude
CFLAGS=-std=c99 -Wall -g -Os -mmcu=${MCU} -DF_CPU=${F_CPU} -I. -I.. -DUART_RX_ENABLED -DUART_TX_ENABLED -DUART_BAUDRATE=19200
TARGET=main
SRCS=main.c uart.c
all:
${CC} ${CFLAGS} -o ${TARGET}.o ${SRCS}
${LD} -o ${TARGET}.elf ${TARGET}.o
${OBJCOPY} -j .text -j .data -O ihex ${TARGET}.o ${TARGET}.hex
${SIZE} -C --mcu=${MCU} ${TARGET}.elf
${AVRDUDE} -p ${MCU} -c usbasp -U flash:w:${TARGET}.hex:i -F -P usb
$(AVRDUDE) -p ${MCU} -c usbasp -U hfuse:w:${FUSE_H}:m -U lfuse:w:${FUSE_L}:m
build:
${CC} ${CFLAGS} -o ${TARGET}.o ${SRCS}
${LD} -o ${TARGET}.elf ${TARGET}.o
${OBJCOPY} -j .text -j .data -O ihex ${TARGET}.o ${TARGET}.hex
${SIZE} -C --mcu=${MCU} ${TARGET}.elf
flash:
${AVRDUDE} -p ${MCU} -c usbasp -U flash:w:${TARGET}.hex:i -F -P usb
fuse:
$(AVRDUDE) -p ${MCU} -c usbasp -U hfuse:w:${FUSE_H}:m -U lfuse:w:${FUSE_L}:m
clean:
rm -f *.c~ *.o *.elf *.hex
/**
* Copyright (c) 2016, Łukasz Marcin Podkalicki <lpodkalicki@gmail.com>
* Software UART for ATtiny13
*/
#include <avr/interrupt.h>
#include "uart.h"
void
uart_putc(char c)
{
uint8_t sreg;
sreg = SREG;
cli();
PORTB |= 1 << UART_TX;
DDRB |= 1 << UART_TX;
__asm volatile(
" cbi %[uart_port], %[uart_pin] \n\t" // start bit
" in r0, %[uart_port] \n\t"
" ldi r30, 3 \n\t" // stop bit + idle state
" ldi r28, %[txdelay] \n\t"
"TxLoop: \n\t"
// 8 cycle loop + delay - total = 7 + 3*r22
" mov r29, r28 \n\t"
"TxDelay: \n\t"
// delay (3 cycle * delayCount) - 1
" dec r29 \n\t"
" brne TxDelay \n\t"
" bst %[ch], 0 \n\t"
" bld r0, %[uart_pin] \n\t"
" lsr r30 \n\t"
" ror %[ch] \n\t"
" out %[uart_port], r0 \n\t"
" brne TxLoop \n\t"
:
: [uart_port] "I" (_SFR_IO_ADDR(PORTB)),
[uart_pin] "I" (UART_TX),
[txdelay] "I" (TXDELAY),
[ch] "r" (c)
: "r0","r28","r29","r30"
);
SREG = sreg;
}
void uart_putu(uint16_t x)
{
char buff[8] = {0};
char *p = buff+6;
do { *(p--) = (x % 10) + '0'; x /= 10; } while(x);
uart_puts((const char *)(p+1));
}
void
uart_puts(const char *s)
{
while (*s) uart_putc(*(s++));
}
/**
* Copyright (c) 2016, Łukasz Marcin Podkalicki <lpodkalicki@gmail.com>
* Software UART for ATtiny13
*/
#ifndef _UART_H_
#define _UART_H_
#ifndef F_CPU
# define F_CPU (1200000UL) // 1.2 MHz
#endif /* !F_CPU */
# define UART_TX PB0 // Use PB0 as TX pin
# define UART_BAUDRATE (9600)
#define TXDELAY (int)(((F_CPU/UART_BAUDRATE)-7 +1.5)/3)
void uart_putc(char c);
void uart_putu(uint16_t x);
void uart_puts(const char *s);
#endif /* !_UART_H_ */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment