STM32Duino ADC does't give sampled data - arduino

I try original O-Scope project (PigOScope) without touchscreen based on STM32F103C8T6 Bluepill board, but got some problem:
I used newest rogerclarkmelbourne/Arduino_STM32 Core and downloaded
pingumacpenguin/STM32-O-Scope sketch. I compiled and uploaded it to the device via UART from 0x08000000 address. Then I started the device. The grid and coordinate lines were displayed on the screen. Also on the screen were displayed inscriptions below 0.0 uS/Sample etc... But any noise or pulse signal from PB1 on my Probe. Why the chart is not drawn?
Also I tried to log my steps in Usart in DMA activation code function:
void takeSamples()
{
// This loop uses dual interleaved mode to get the best performance out of
the ADCs
Serial.println("Init DMA");
dma_init(DMA1);
dma_attach_interrupt(DMA1, DMA_CH1, DMA1_CH1_Event);
Serial.println("Enable DMA for ADC");
adc_dma_enable(ADC1);
dma_setup_transfer(DMA1, DMA_CH1, &ADC1->regs->DR, DMA_SIZE_32BITS,
dataPoints32, DMA_SIZE_32BITS, (DMA_MINC_MODE |
DMA_TRNS_CMPLT));// Receive buffer
Serial.println("Set DMA transfer");
Serial.println(maxSamples / 2);
dma_set_num_transfers(DMA1, DMA_CH1, maxSamples / 2);
dma1_ch1_Active = 1;
Serial.println("Enable the channel and start the transfer");
dma_enable(DMA1, DMA_CH1); // Enable the channel and start the transfer.
samplingTime = micros();
Serial.println(samplingTime);
while (dma1_ch1_Active); // SOME BUG OR WHAT.... PROGRAM STOP HERE!!!
samplingTime = (micros() - samplingTime);
Serial.println("Disable DMA");
dma_disable(DMA1, DMA_CH1); //End of trasfer, disable DMA and Continuous
mode.
}
Event handler for stop interrupt
static void DMA1_CH1_Event()
{
dma1_ch1_Active = 0;
}
Volatile flag to stop routine
volatile static bool dma1_ch1_Active = 0;
Program keep crushing on while loop i think... And program does't work beyond takeSamples() function.
Why program does't exit the loop?

Related

Arduino - Gyro sensor - ISR - TimeStamp

I currently working to recreate a quad-copter controller.
I am working on getting data from my gyro sensor, and to do that, I'm using
an ISR with an interuption.
My problem is, when I call my function "gyro.getX" on the main program, it work.
But, when I call this function from my ISR, it doesn't work.
I thing that I find the reson of the bug, the function I'm using is provided by the "Adafruit_LSM9DS0" library (from ST), and it used a "timestamp".
I thing that the current time from my ISR is different that the current time from my Main program, but i don't know how to fi it.
Here a shortcut of my program:
void loop(){
/*main prog*/
}
/*
*Reserve interrupt routine service (ISR) by Arduino
*/
ISR(TIMER2_OVF_vect)
{
TCNT2 = 256 - 250; // 250 x 16 µS = 4 ms
if (varCompteur++ > 25)// 25 * 4 ms = 100 ms (half-period)
{
varCompteur = 0;
SensorGet(pX, pY);//Feed gyro circular buffers
}
}
void SensorGet(float * pRollX, float * pPitchY)
{
lsm.getEvent(&accel, &mag, &gyro, &temp);
GiroX_Feed(pX, gyro.gyro.x);
GiroY_Feed(pPitchY, gyro.gyro.y);
}
bool Adafruit_LSM9DS0::getEvent(sensors_event_t *accelEvent,
sensors_event_t *magEvent,
sensors_event_t *gyroEvent,
sensors_event_t *tempEvent)
{
/* Grab new sensor reading and timestamp. */
read();
uint32_t timestamp = millis();
/* Update appropriate sensor events. */
if (accelEvent) getAccelEvent(accelEvent, timestamp);
if (magEvent) getMagEvent(magEvent, timestamp);
if (gyroEvent) getGyroEvent(gyroEvent, timestamp);
if (tempEvent) getTempEvent(tempEvent, timestamp);
return true;
}
The problem isn't the time. The problem is likely that your sensor uses the I2C and it is disabled during an interrupt routine, or it's some other communication protocol that relies on interrupts to function and is therefore disabled during your ISR.
You are really abusing the interrupt. This is not the kind of thing interrupts are for. Interrupt should be super fast, no time for communications there. So the real question is why do you think you need an interrupt for this?

Are interrupts the right thing to use for my robot?

So I have this old motorized wheelchair that I am trying to convert into a robot. I replaced the original motor driver with a sabertooth 2x12 and I’m using an Arduino micro to talk to it. The motors shaft goes all the way threw so I attached a magnet and a Hall Effect sensor to the back side to act as a rotary encoder. My current goal is to be able to tell the robot to move forward a certain amount of feet then stop. I wrote some code to do this linearly however this didn't work so well. Then I learned about interrupts and that sounded like exactly what I needed. So I tried my hand at that and things went wrong on several different levels.
LEVEL ONE: I have never seemed to be able to properly drive the motors it seems like any time I put the command to turn them on inside of a loop or if statement they decide to do what they want and move sporadically and unpredictably
LEVEL TWO: I feel like the interrupts are interrupting themselves and the thing I set in place to stop the wheels from moving forward because I can tell it to move 14 rotary encoder clicks forward and one wheel will continue moving way past 1000 clicks while the other stops
LEVEL THREE: couple times I guess I placed my interrupts wrong because when I uploaded the code windows would stop recognizing the Arduino and my driver would break until I uploaded the blink sketch after pressing the reset button which also reloaded and fixed my drivers. Then if I deleted one of my interrupts it would upload normally.
LEVEL FOUR: my Hall Effect sensors seem to not work right when the motors are on. They tend to jump from 1 to 200 clicks in a matter of seconds. This in turn floods my serial port and crashes the Arduino ide.
So as you can see there are several flaws somewhere in the system whether it’s hardware or software I don't know. Am I approaching this the right way or is there some Arduino secret I don’t know about that would make my life easier? If I am approaching this right could you take a look at my code below and see what I’m doing wrong.
#include <Servo.h>//the motor driver uses this library
Servo LEFT, RIGHT;//left wheel right wheel
int RclickNum=0;//used for the rotory encoder
int LclickNum=0;//these are the number of "clicks" each wheel has moved
int D =115;//Drive
int R =70;//Reverse
int B =90;//Break
int Linterrupt = 1;//these are the interrupt numbers. 0 = pin 3 and 1 = pin 2
int Rinterrupt = 0;
int clickConvert = 7;// how many rotery encoder clicks equal a foot
void setup()
{
Serial.begin(9600); //starting serial communication
LEFT.attach( 9, 1000, 2000);//attaching the motor controller that is acting like a servo
RIGHT.attach(10, 1000, 2000);
attachInterrupt(Linterrupt, LclickCounter, FALLING);//attaching the rotory encoders as interrupts that will
attachInterrupt(Rinterrupt, RclickCounter, FALLING);//trip when the encoder pins go from high to low
}
void loop()
{//This is for controling the robot using the standard wasd format
int input= Serial.read();
if(input == 'a')
left(2);
if(input == 'd')
right(2);
if(input == 'w')
forward(2);
if(input == 's')
backward(2);
if(input == 'e')
STOP();
}
void forward(int feet)//this is called when w is sent threw the serial port and is where i am testing all of my code.
{
interrupts(); //turn on the interrupts
while(RclickNum < feet * clickConvert || LclickNum < feet * clickConvert)// while either the left or right wheel hasnt made it to the desired distance
{
if(RclickNum < feet * clickConvert)//check if the right wheel has gone the distance
RIGHT.write(D); //make the right wheel move
else
RIGHT.write(B);//stop the right wheel
if(LclickNum < feet * clickConvert)
LEFT.write(D);
else
LEFT.write(B);
}
noInterrupts();//stop the interrupts
resetCount();//set the click counters back to zero
}
//once i have the forward function working i will implament it through out the other functions
//----------------------------------------------------------------------
void backward(int feet)
{
RIGHT.write(R);
LEFT.write(R);
}
void left(int feet)
{
RIGHT.write(D);
LEFT.write(R);
}
void right(int feet)
{
RIGHT.write(R);
LEFT.write(D);
}
void STOP()
{
resetCount();
RIGHT.write(B);
LEFT.write(B);
}
void LclickCounter()//this is called by the left encoder interrupt
{
LclickNum++;
Serial.print("L");
Serial.println(LclickNum);
}
void RclickCounter()//this is called by the right encoder interrupt
{
RclickNum++;
M Serial.print("R");
Serial.println(RclickNum);
}
void resetCount()
{
RclickNum=0;
LclickNum=0;
}
don't use interrupt() and nointerrupt() (or cli() and sei()) as they will stop timer and serial interrupt, breaking a lot of things. Just set to 0 the counting variable OR use detachInterrupt and attachInterrupt.
variable used inside interrupt AND normal execution flow should be declared as volatile, or their value my be unsyncornized. So declare them like volatile int RclickNum=0;
interrupt should be fast to execute, as by default other interrupt will NOT execute while inside an interrupt.
NEVER use Serial inside interrupt; if Serial buffer is full, it will call Serial.flush(), that will wait for Serial interrupt of byte written, but because you are alreadi inside an interrupt will never happen...dead lock aka you code hangs forever!
because your "moving" function use quite a long time to execute, if multiple command arrive to the serial, thay will remain isnode the buffer until readed. So if in the terminal you write "asd" and then "e", you will see robot go left, backward, right, stop (yes, actually the stop function is not usefull as it does nothing because your "moving" function are "blocking", that mean they won't return until they ended, so the loop() code (and the read of "e") will not execute until the buffer of serial has been processed.

Arduino DUE, Serial interrupt procedure to wakeup from sleep mode

i'd like to put the SAM3X chip on sleepmode until a character arrives on the serial port. i was thinking of using an ausiliary flag in the Serial interrupt procedure in order to trigger the wake up procedure? what do you think abou? any advice or any other way i should follow or try?
I recommend reviewing .\arduino-1.5.2\hardware\arduino\sam\cores\arduino\UARTClass.cpp as its UARTClass::begin will detail how the Arduino Framework initializes the SAM's Serial IRQ with:
// Configure interrupts
_pUart->UART_IDR = 0xFFFFFFFF;
_pUart->UART_IER = UART_IER_RXRDY | UART_IER_OVRE | UART_IER_FRAME;
// Enable UART interrupt in NVIC
NVIC_EnableIRQ(_dwIrq);
// Enable receiver and transmitter
_pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN ;
Where you will need to ensure the baud rate generator is not stopped while in sleepmode.
Along with reading the SAM3X data sheet starting with 5.5.3. which leaves the peripheral clocks enabled.
looks like you may be able to insert the wake up into the UARTClass::IrqHandler
void UARTClass::IrqHandler( void )
{
uint32_t status = _pUart->UART_SR;
// Did we receive data ?
if ((status & UART_SR_RXRDY) == UART_SR_RXRDY)
{
// wake up!!!! Not sure if you even need to wakeup, it should from the sleepmode
_rx_buffer->store_char(_pUart->UART_RHR);
}
With regards to sleeping:
\arduino-1.5.2\hardware\arduino\sam\system\libsam\source\pmc.c
Line 972: void pmc_enable_sleepmode(uint8_t uc_type)
Line 988: void pmc_enable_waitmode(void)
Line 1009: void pmc_enable_backupmode(void)
So I would suspect the following:
pmc_enable_sleepmode(WFI);
would put the unit a sleep and the IrqHandler of the UART_SR_RXRDY would wake itself up, without any code change.
One other alternative would be to use the serial pin's IO as to trigger an interrupt.
attachInterrupt(0, EnableSerialRX, CHANGE);
It would though, loose at least the first byte. the trade off is that you can use the lower power modem of pmc_enable_backupmode() rather than sleep

UDR register cleared before reading data

I am trying to simulate the uart using ATmega128. I have written this code in AVR STUDIO 4.
The PORTB0 is for used switch so that when it is pressed it is connected to 5v dc and it sends 'a' to uart1. at other times it is connected to ground. the reception of data is by interrupt.
Using debugger, when there is data in UDR1 and RXC1 is set, program jumps to ISR, and then UDR register is immediately cleared and nothing is retrieved. Can any one tell me why this happens?
Here is the code.
volatile unsigned char rxdata;
void uart_init(void)
{
UCSR1A = 0x00;
UCSR1B |= (1<<RXCIE1)|(1<<RXEN1)|(1<<TXEN1); //0b10011000;
UCSR1C |= (1<<7)|(1<<UCSZ11)|(UCSZ10); //0b10000110;
UBRR1H = 0;
UBRR1L = 103; //9600 baud rate
}
ISR(USART1_RX_vect)
{
rxdata = UDR1;
PORTC = rxdata;
}
void putch(char data)
{
while(!(UCSR1A & 0x20));
UDR1 = data;
}
And the main program is
void port_init(void)
{
DDRC = 0xFF;
}
int main(void)
{
port_init();
uart_init();
sei();
while(1)
{
if (PINB & 0x01){
putch('a');
}
}
}
I had this once. In my case, setting the breakpoint before the flag was evaluated in the code cleared it, because The AVR Studio "read" the flag (as I had the flag register open). Setting the breakpoint AFTER the line where the flag was read, helped. In your case, set the breakpoint on line PORTC = rxdata;
To get a better debug feeling, I read the flag into a variable right at the beginning of the ISR and set the breakpoint right after this.
It's been some years since this happened and I'm not even sure if this was really the case. So, maybe you can verify this ;)
I took a look at the AVR Studio 4 help section. Regarding known simulator issues with respect to UART functions it states:
The UART/USART UDR register can only be modified from the application. Input via stimuli files or by modifying the I/O view etc is not possible.

GPS module stops working, is unable to setMode to on

I have been using the GPS module on waspmotes, and I have been able to get data off it. However on a fine day, with clear visible skies(which I don't think matters), I cannot be able to set the power mode on.
On calling GPS.setMode(GPS_ON), it fails to set the power mode on, and on freezes on subsequent call to: gpsConnected = GPS.check();
I have tried changing the GPS unit to no avail. I am using the following code. (NB: I have removed the unnecessary bits of code for the sake of brevity)
void setup()
{
ACC.ON();
USB.begin(); // Opening UART to show messages using 'Serial Monitor'
//Initialize the GPS module
GPS.ON(); // Turn GPS on
GPS.setMode(GPS_ON); // set GPS on
if(!GPS.pwrMode) USB.println("Was unable to set on the GPS internal power mode."); //this message gets printed.
if(!GPS.setCommMode(GPS_NMEA_GGA)) USB.println("Was unable to set the GPS communication mode.");
// Power up the Real Time Clock(RTC), init I2C bus and read initial values
RTC.ON();
........
}
void loop(){
//declare the variables
len, i, j = 0;
char degree[4] = "", minutes[8] = "", *latitude, *longitude, *altitude;
uint8_t temperature = 0;
int8_t fileFound = 0;
double latitude_dd, longitude_dd;
byte accOk;
//check if the GPS has connected to the satellite
GPS.begin(); // open the uart
GPS.init(); // Inits the GPS module
gpsConnected = GPS.check();
........
........
}
What might have happened???
Any help will be appreciated.
This was caused by using the RTC.setTime function. In the code, as can be seen here: http://pastebin.com/RmA98MkD, on line 195, RTC.setTimeFromGPS(), I was setting the boards time with the time that I received from GPS. This ended up screwing the GPS connection up and the code only looped once. You can see detailed conversations from here: http://www.libelium.com/forum/viewtopic.php?f=16&t=9861
You Need to simple test. First you ensure that you are giving TTl input to the Tx and rx pin . If you upload this program It will gives GPS output string.If you are using GPS module with Serial output of RS 232 out, As you said it wont work.IT expecting TTl input only
void setup()
{
Serial.begin();
}
void loop()
{
}

Resources