How do I produce a sawtooth waveform using c language? - c

This is my program with regards to DAC using PIC18F97J60. I am new to this and already struggling alot so please do not judge me.
#include <P18F97J60.h>
//#include <delays.h>
//#include "delays.c"
void SPI1init(void);
void SPI1out(char Code);
void SPI1init(void)
{
SSP1CON1 = 0b00100010; // Enable SPI, CKP=0, Master, Fosc/64
SSP1STATbits.CKE = 1; // CKE=1, (rising edge for shift register)
TRISCbits.TRISC3 = 0; // RC3 is SCk
TRISCbits.TRISC5 = 0; // RC5 is SDO
SPI1out(0x00);
}
void SPI1out(char Code)
{
SSP1BUF = Code; // Transmit
while(SSP1STATbits.BF==0); // Wait for END (Receipt Buffer Full)
Code = SSP1BUF; // Just read to clear BF
}
Diagram for the circuit: https://ibb.co/M1cChNB
Question of the assignment: https://ibb.co/rwz3kwP

Related

uart between atmega328p (C) and Feather m0 (Arduino) receive

I want to send data from my ac/gy via atmega328p to a feather m0 module. The atmega is programmed in C using the following github code: https://github.com/YifanJiangPolyU/MPU6050
And the Arduino code for receiving data within the LoRa module is shown below:
void do_send(osjob_t* j){
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
} else {
// Prepare upstream data transmission at the next possible time.
byte strArray[30];
int i = 0;
if(Serial1.available()>0) {
while (Serial1.available()>0){
strArray[i] = Serial1.read();
i++;
}
// send the 6 bytes payload to LoRaWAN port 7 --> now port 1
LMIC_setTxData2(1, strArray, sizeof(strArray), 1);
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on by making the voltage HIGH //optional: for confirmation
}
}
}
// Next TX is scheduled after TX_COMPLETE event.
//delay(60000);
void loop() {
os_runloop_once();
}
However, I can't seem to receive anything and can't send a "char array" to the gateway using the LMIC function apparently, so trying to receiving data within a byte array instead. Any help or tips regarding this is greatly appreciated. I'll also include the main.c code for the atmega328P down here below:
#define F_CPU 16000000UL
#define BAUD 9600
#include <inttypes.h>
#include <avr/sfr_defs.h>
#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
#include <util/setbaud.h>
#include <avr/interrupt.h>
#include <math.h>
#include "mpu6050.h"
#include "mpu6050_reg.h"
#include "i2c.h"
#include "uart.h"
void timer_setup();
void get_time(double* dt);
volatile double count;
const double unit_t = 8/16000000;
int main(void){
sei();
uart_init();
i2c_init();
DDRB |= _BV(5);
uint8_t ret;
int16_t accel_buff[3], gyro_buff[3];
double accelX, accelY, accelZ;
double gyroX, gyroY, gyroZ;
double biasX, biasY;
double phi_accel, theta_accel;
double phi_innov, theta_innov;
double phi_est, theta_est;
double phi_prev, theta_prev;
double dt;
char s[30];
// initialize & test MPU5060 availability
ret = i2c_start(MPU6050_ADDRESS+I2C_WRITE);
if(~ret){
PORTB |= _BV(5);
_delay_ms(200);
PORTB &= ~(_BV(5));
}
mpu6050_init();
timer_setup();
// find gyro bias
biasX = 0;
biasY = 0;
uint8_t i;
for(i=0; i<20; i++){
mpu6050_read_gyro_ALL(gyro_buff);
biasX += gyro_buff[0];
biasY += gyro_buff[1];
}
biasX = biasX/20*(3.14159/180)/1000/32768;
biasY = biasY/20*(3.14159/180)/1000/32768;
// initialization for Kalman filter
double P = 0.0;
double Q = 0.001;
double R = 0.03;
double Pp, K;
mpu6050_read_accel_ALL(accel_buff);
phi_prev = atan2(accelY, accelZ); // row
theta_prev = atan2(-accelX, sqrt(accelY*accelY+accelZ*accelZ)); // pitch
for(;;){
get_time(&dt);
mpu6050_read_accel_ALL(accel_buff);
mpu6050_read_gyro_ALL(gyro_buff);
// acceleration (m/s^2)
accelX = accel_buff[0]*9.8*2/32768;
accelY = accel_buff[1]*9.8*2/32768;
accelZ = accel_buff[2]*9.8*2/32768;
// gyro rate (rad/s)
gyroX = gyro_buff[0]*(3.14159/180)/1000/32768;
gyroY = gyro_buff[1]*(3.14159/180)/1000/32768;
gyroZ = gyro_buff[2]*(3.14159/180)/1000/32768;
// estimation
phi_est = phi_prev + dt*(gyroX - biasX);
theta_est = theta_prev + dt*(gyroY - biasY);
Pp = P+Q;
// innovation
phi_accel = atan2(accelY, accelZ); // row
phi_innov = phi_accel - phi_est;
theta_accel = atan2(-accelX, sqrt(accelY*accelY+accelZ*accelZ)); // pitch
theta_innov = theta_accel - theta_est;
// Kalman gain
K = Pp/(Pp+R);
// correction
phi_prev = phi_prev + K*phi_innov;
theta_prev = theta_prev + K*theta_innov;
P = (1-K)*Pp;
uart_putchar('\n');
_delay_ms(10);
uart_putdouble(phi_prev); //phi, row
uart_putdouble(theta_prev); //theta, pitch
uart_putdouble(dt);
//_delay_ms(10);
}
}//end of main
void timer_setup(){
TCCR1A = 0x00;
TIMSK1 |= _BV(TOIE1);
TCCR1B |= _BV(CS11);
TCCR1B &= ~( _BV(CS12) | _BV(CS10)); // prescaler=8
}
void get_time(double * dt){
cli();
uint8_t l = TCNT1L;
uint8_t h = TCNT1H;
uint16_t step = h<<8 | l;
*dt = (double)step*5e-7 + count*0.032768;
count = 0;
sei();
}
// timer 1 overflow interrupt handler
SIGNAL(TIMER1_OVF_vect){
count += 1;
}
Connect the board to the PC and check in the Arduino IDE Serial Monitor if you can get or send data.
If your serial communication doesn't work, you can check if you are past a point in execution by turning on the led on the board. Most development boards have at least 1, and with Arduino is just a matter of setting the pin as output and digitalWrite(LED_BUILTIN, 0) in setup, then digitalWrite(LED_BUILTIN, 1) at the point you want to check.
If your atmega328p is on an arduino board (e.g. uno, nano etc) you should check in the same way for it, too. Both the serial and past-the-point verification.
I'd to that, then rely on the serial for debugging for a while.
I'm curious, do you think the condition "if(Serial1.available()>0)" is true?

How do i fetch data from UDRn on Mega2560?

Noob question:
I'm trying to learn about UART on an ARDUINO. I wrote some very simple code and for some reason, i can't make the receive() function work. I don't think it fetches the data from the UDR register. I'm using a small OLED display and i want to print the received data to it. No data is being printed to the display, when i run the code.
I connected the ports TX1 and RX1 with a wire on the board.
I tried finding youtube videos and have been reading alot. Appearently not enough.
Any ARDUINO expert who knows what to do?
#include <avr/io.h>
#include "ssd1306.h"
#include "I2C.h"
#include <stdio.h>
#include <util/delay.h>
void initOLED();
void initUART1();
void receive();
void transmit();
int main(void)
{
I2C_Init();
initOLED(); //initialiaze OLED
while (1)
{
transmit();
receive();
}
}
void initOLED()
{
I2C_Init();
InitializeDisplay();
clear_display();
}
void initUART1(void)
{
DDRD = 0x08; //TXD1 set to output
UBRR1L = 51; //Baudrate 19200
UBRR1H = 0; //upper four bits of baudrate
UCSR1A = 0x02; //Double speed mode
UCSR1B = 0x18; //Enable receive and transmit
UCSR1C = 0x06; //1 stop bit, 8-bit, no parity
}
void transmit()
{
char b = 'a';
while(!(UCSR1A & (1<<UDRE1))); //wait for an empty UDR register
UDR1 = b; //load character in register
}
void receive()
{
int Y = 0; //Y coordinate for cursor on the display
char d;
while(!(UCSR1A & (1<<RXC1))); //wait for unread data in the receive buffer
d = UDR1; //set UDR register in character d
sendCharXY(d, 1, Y); //send character to display
}
It looks like you never call initUART1().

Can someone explain what does the interrupt "Trap" do in the micro controller

I am using stm8l - discovery board and I am curious about the functionality of trap in the micro controller. My program stops instead of running continously in the while loop, Is the functionality of trap interrupt that if it occurs, it does not execute (similar to reset)?
#include <iostm8l.h>
#include <stdio.h>
#include <stdint.h>
void Cus_delay(uint32_t ntime)
{
while(ntime!=0)
{
ntime--;
}
}
main()
{
CLK_DIVR = 0x00; // Set the frequency to 16Mhz
PC_DDR = 0x80; // direction output for led
PC_CR1 = 0x80; // fast push pull mode
int a = 10;
while(1)
{
Cus_delay(400000);
Cus_delay(400000);
PC_ODR ^= 0x80;
a = a/0;
}
}

Read a txt file from PC using UART - Atmega32A

I am a beginner in microprocessor programming. I created an array and sent datas using UART. I want to read a text file and create this array using datas in the text file with the simplest way possible. Any suggestion to proceed? Thanks in advance.
#include <avr/io.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define F_CPU 8000000UL // Clock freq
char flag = 0;
void usart_init(void){
UCSRA = 0x02;
UCSRB = 0x98; // Enable transmitter Enable receiver Enable Interrupt
UCSRC = (1<<UCSZ1) | (1<<UCSZ0); // set as 8 bit data, no parity bit and 1 stop bit.
UBRRH = 0x00;
UBRRL = 109;
}
int main(void){
usart_init();
while(1){
unsigned char array[5]={0x44,0xAA,0x33,0xBB,0x55};
for (int i=0;i<5;i++){
UDR = array[i];
UDR = 0xFF;
_delay_ms(100);
}
sei();
if(flag == 1)
{
flag = 0;
UCSRB = 0x98;
}
}
}
ISR(USART_RXC_vect){
UCSRB = (0<<RXEN)|(0<<TXEN)|(0<<RXCIE);
flag = 1;
}
You are working with a microcontroller so you can't handle a file directly. You had to code every value (copy & paste) in your source code.
unsigned char const array[5]={0x44,0xAA,0x33,0xBB,0x55};
You had to do this even for a large array.

Converting 0-5v analog to a rotary encoder equivalent

I'm currently working on a robot as an intern and must choose replacement drivers for the motors. The position information of the axis are given by analog pot. I do have 3 drivers by technosoft that needs a rotary encoder (quadrature) information to do their regulation job.
I was thinking about converting this analog signal into the right quadrature signal to make it work.
The way I designed it is a pic18 sampling the pot value at 150hz, subtracting the previous value to the current one to have an idea (a kind of derivation) of the speed. It generates an absolute value of the speed and a direction signal whose regulate the rate of change of a state machine with the 4 states of the quadrature encoder. I finally send these signals to the 2 outputs.
My questions are the following.
Is it feasible. Or is there a clever way of doing so ? Or even a dedicated chip that can do the job? I searched the web to find someone who would have already done something similar but found nothing.
I've spend my 2 last days to code this solution & debug it without success...
On the scope, the quadrature signal is there but it behaves with no real logic. Changing really fast or slowly whether I move or don't move the pot.
Here's my code
#include <p18f4685.h>
#include <stdlib.h>
#include <stdio.h>
#include <delays.h>
// ----------------------
// Configuration Hardware
// ----------------------
#pragma config OSC = HSPLL
#pragma config MCLRE = ON, PWRT = OFF
#pragma config DEBUG = ON, LVP = OFF
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config BOREN = OFF
#pragma config WDT = OFF
#pragma config XINST = OFF
#pragma code
// Variables
unsigned int position_t0=0;
unsigned int position_t1=0;
signed int speed=0;
unsigned int speed_abs=0;
int direction=0; // si 0 cw, si 1 ccw
unsigned int count_1 = 0;
unsigned int state_out = 0;
//proto fonctions
void setup(void);
void get_pot(void);
void set_out(void);
void low_isr(void);
void high_isr(void);
int abval(int);
void main(void)
{
setup(); //initialisation
get_pot();
LATE = 0b00000000;
while(1)
{
}
}
void setup (void)
{
/*config timers*/
T0CON = 0b11000101; // timer on, 8bits, internal clock, prescaler on + value 1/64 (152 interruptions par seconde)
// data acquisition interrup
T2CON = 0b00111100; // output moditication loop timer 8bits 1/8postscale 1200 interrupt/second
PR2 = 0b00001111;
/*config adc*/
ADCON1 = 0b00001010; // A0->A4 analo + VDD+GND reference
ADCON2 = 0b10111000; // A/D acq time (ADCON2) 20TAD, A/D conversion clock (ADCON2)
// right justified
ADCON0 = 0b00000001; // Turn on A/D module (ADCON0) + channel select
/*config des pins*/
// TRISA = 0b00011111; // 5 entrées analogiques + 3 digitales
// TRISB = 0b01001100; // sorties pour la version finale
TRISE = 0b00000000; // sorties pour la version test
// PORTA = 0b00000000; // Clear A
PORTE = 0b00000000; // clear E
/*config interruptions*/
RCONbits.IPEN = 1; // priority enabled
INTCON = 0b11100000; // enable les interruption hautes et basses, Timer0 interrupt On
INTCON2 = 0b10000100; // Pull up désactivés +timer0 high(acquisition vitesse)
PIE1bits.TMR2IE = 1; // enable interrupt timer2
IPR1bits.TMR2IP = 0; // timer 2 en priorité basse(mise à jour des pins)
}
void get_pot (void) //get the value of the pot and computes the data
{
ADCON0bits.CHS1 = 0;
ADCON0bits.CHS0 = 0;
ADCON0bits.GO = 1;
while(ADCON0bits.GO==1){}
position_t1 = ADRESH*256+ADRESL;
speed = position_t1 - position_t0;
if(speed<0) direction = 1;
else direction = 0;
speed_abs = abval(speed);
position_t0 = position_t1;
}
void set_out (void) //set the output according the speed and direction
{
if(speed_abs>1)
{
count_1++;
if(count_1>=(1023-speed_abs)/4) //counter that makes the output change more or less faster
{
if(direction==1)
{
switch(state_out)
{
case 0:
{
LATE = 0b00000000;
state_out++;
}
break;
case 1:
{
LATE = 0b00000001;
state_out++;
}
break;
case 2:
{
LATE = 0b00000011;
state_out++;
}
break;
case 3:
{
LATE = 0b00000010;
state_out=0;
}
break;
}
}
else if(direction==0)
{
switch(state_out)
{
case 0:
{
LATE = 0b00000000;
state_out=3;
}
break;
case 1:
{
LATE = 0b00000001;
state_out--;
}
break;
case 2:
{
LATE = 0b00000011;
state_out--;
}
break;
case 3:
{
LATE = 0b00000010;
state_out--;
}
break;
}
}
count_1=0;
}
}
}
int abval(int val)
{
return (val<0 ? (-val) : val);
}
#pragma interrupt high_isr
void high_isr (void) //interruption de récupération des adc
{
if(INTCONbits.TMR0IF==1)
{
get_pot();
INTCONbits.TMR0IF=0;
}
}
#pragma interruptlow low_isr
void low_isr (void) //interruption de mise à jour des sorties
{
if(PIR1bits.TMR2IF==1)
{
set_out();
PIR1bits.TMR2IF=0;
}
}
/*
*********************************************************************************************************
* Interupt Vectors
*********************************************************************************************************
*/
#pragma code low_vector=0x18
void interrupt_at_low_vector(void)
{
_asm goto low_isr _endasm
}
#pragma code high_vector=0x08
void interrupt_at_high_vector(void)
{
_asm goto high_isr _endasm
}
Part of the code comments are in french, i translated the important ones.
Do you see any obvious mistakes/wrong ways of coding. Do you have any advices of "where to search" or what to watch ?
Thanks by advance for your help !
Nicolas

Resources