Use UART events with Simplelink in Contiki-ng - uart

I'm actually trying to receive serial line message using the UART0 of a CC1310 with Contiki-ng.
I have implemented a uart callback function with will group all the characters received into a single variable, and stop collecting when it receives a "\n" character.
int uart_handler(unsigned char c)
{
if (c == '\n')
{
end_of_string = 1;
index = 0;
}
else
{
received_message_from_uart[index] = c;
index++;
}
return 0;
}
The uart0 is initialised at the main and only process of the system and then it waits in a infinite while loop until the flag end_of_string
PROCESS_THREAD(udp_client_process, ev, data)
{
PROCESS_BEGIN();
uart0_init();
uart0_set_callback(uart_handler);
while (1)
{
//wait for uart message
if (end_of_string == 1 && received_message_from_uart[0] != 0)
{
LOG_INFO("Received mensaje\n");
index = 0;
end_of_string = 0;
// Delete received message from uart
memset(received_message_from_uart, 0, sizeof received_message_from_uart);
}
etimer_set(&timer, 0.1 * CLOCK_SECOND);
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&timer));
}
PROCESS_END();
}
As you can see, the while loop stops at each iteration with a minimum time timer event. Although this method works, I think it is a bad way to do it, as I have read that there are uart events that can be used, but I have not been able to find anything for the CC1310.
Is it possible to use the CC1310 (or any other simplelink platform) UART with events and stop doing unnecessary iterations until a message has reached the device?

Related

STM32 Crash on Flash Sector Erase

I'm trying to write 4 uint32's of data into the flash memory of my STM32F767ZI so I've looked at some examples and in the reference manual but still I cannot do it. My goal is to write 4 uint32's into the flash and read them back and compare with the original data, and light different leds depending on the success of the comparison.
My code is as follows:
void flash_write(uint32_t offset, uint32_t *data, uint32_t size) {
FLASH_EraseInitTypeDef EraseInitStruct = {0};
uint32_t SectorError = 0;
HAL_FLASH_Unlock();
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
EraseInitStruct.Sector = FLASH_SECTOR_11;
EraseInitStruct.NbSectors = 1;
//EraseInitStruct.Banks = FLASH_BANK_1; // or FLASH_BANK_2 or FLASH_BANK_BOTH
st = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
if (st == HAL_OK) {
for (int i = 0; i < size; i += 4) {
st = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FLASH_USER_START_ADDR + offset + i, *(data + i)); //This is what's giving me trouble
if (st != HAL_OK) {
// handle the error
break;
}
}
}else {
// handle the error
}
HAL_FLASH_Lock();
}
void flash_read(uint32_t offset, uint32_t *data, uint32_t size) {
for (int i = 0; i < size; i += 4) {
*(data + i) = *(__IO uint32_t*)(FLASH_USER_START_ADDR + offset + i);
}
}
int main(void) {
uint32_t data[] = {'a', 'b', 'c', 'd'};
uint32_t read_data[] = {0, 0, 0, 0};
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
flash_write(0, data, sizeof(data));
flash_read(0, read_data, sizeof(read_data));
if (compareArrays(data,read_data,4))
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7,SET);
}
else
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14,SET);
}
return 0;
}
The problem is that before writing data I must erase a sector, and when I do it with the HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError), function, the program always crashes, and sometimes even corrupts my codespace forcing me to update firmware.
I've selected the sector farthest from the code space but still it crashes when i try to erase it.
I've read in the reference manual that
Any attempt to read the Flash memory while it is being written or erased, causes the bus to
stall. Read operations are processed correctly once the program operation has completed.
This means that code or data fetches cannot be performed while a write/erase operation is
ongoing.
which I believe means the code should ideally be run from RAM while we operate on the flash, but I've seen other people online not have this issue so I'm wondering if that's the only problem I have. With that in mind I wanted to confirm if this is my only issue, or if I'm doing something wrong?
In your loop, you are adding multiples of 4 to i, but then you are adding i to data. When you add to a pointer it is automatically multiplied by the size of the pointed type, so you are adding multiples of 16 bytes and reading past the end of your input buffer.
Also, make sure you initialize all members of EraseInitStruct. Uncomment that line and set the correct value!

UART Transmit failing after UART Receive thread starts in STM32 HAL Library

I am using STM32F1 (STM32F103C8T6) in order to develop a project using FreeRTOS.
The following is my GPIO and USART1 interface configuration:
__GPIOA_CLK_ENABLE();
__USART1_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;//115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
HAL_UART_Init(&huart1);
HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
The question is: Why does UART transmit work before threads start but not after threads started or from threads? I want to transmit data from threads. i.e
int main(void)
{
Initializations();
//THIS WORKS!!
uart_transmit_buffer[0] = 'H';
uart_transmit_buffer[1] = 'R';
uart_transmit_buffer[2] = '#';
uint8_t nums_in_tr_buf = 0;
nums_in_tr_buf = sizeof(uart_transmit_buffer)/sizeof(uint8_t);
state = HAL_UART_Transmit(&huart1, uart_transmit_buffer, nums_in_tr_buf, 5000);
StartAllThreads();
osKernelStart();
for (;;);
}
static void A_Random_Thread(void const *argument)
{
for(;;)
{
if (conditionsMet()) //Executed once when a proper response received.
{
//BUT NOT THIS :(!!
uart_transmit_buffer[0] = 'H';
uart_transmit_buffer[1] = 'R';
uart_transmit_buffer[2] = '#';
uint8_t nums_in_tr_buf = 0;
nums_in_tr_buf = sizeof(uart_transmit_buffer)/sizeof(uint8_t);
state = HAL_UART_Transmit(&huart1, uart_transmit_buffer, nums_in_tr_buf, 5000);
}
}
}
I have made sure no thread is in deadlock. The problem is UART_HAL_Transmit gives HAL_BUSY state.
Furthermore, I have dedicated one thread to receiving and parsing information from UART RX and I suspect this might be a cause of the problem. The following is the code:
static void UART_Receive_Thread(void const *argument)
{
uint32_t count;
(void) argument;
int j = 0, word_length = 0;
for (;;)
{
if (uart_line_ready == 0)
{
HAL_UART_Receive(&huart1, uart_receive_buffer, UART_RX_BUFFER_SIZE, 0xFFFF);
if (uart_receive_buffer[0] != 0)
{
if (uart_receive_buffer[0] != END_OF_WORD_CHAR)
{
uart_line_buffer[k] = uart_receive_buffer[0];
uart_receive_buffer[0] = 0;
k++;
}
else
{
uart_receive_buffer[0] = 0;
uart_line_ready = 1;
word_length = k;
k = 0;
}
}
}
if (uart_line_ready == 1)
{
//osThreadSuspend(OLEDThreadHandle);
for (j = 0; j <= word_length; j++)
{
UART_RECEIVED_COMMAND[j] = uart_line_buffer[j];
}
for (j = 0; j <= word_length; j++)
{
uart_line_buffer[j] = 0;
}
uart_line_ready = 0;
RECEIVED_COMMAND = ParseReceivedCommand(UART_RECEIVED_COMMAND);
if (RECEIVED_COMMAND != _ID_)
{
AssignReceivedData (word_length); //Results in uint8_t * RECEIVED_DATA
}
//osThreadResume(OLEDThreadHandle);
}
//Should be no delay in order not to miss any data..
}
}
Another cause to the problem I suspect could be related to interrupts of the system (Also please notice initialization part, I configured NVIC):
void USART1_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart1);
}
Any help or guidance to this issue would be highly appreciated. Thanks in advance.
From what I can see HAL_UART_Transmit would've worked with the F4 HAL (v1.4.2) if it weren't for __HAL_LOCK(huart). The RX thread would lock the handle and then the TX thread would try to lock as well and return HAL_BUSY. HAL_UART_Transmit_IT and HAL_UART_Receive_IT don't lock the handle for the duration of the transmit/receive.
Which may cause problems with the State member, as it is non-atomically updated by the helper functions UART_Receive_IT and UART_Transmit_IT. Though I don't think it would affect operation.
You could modify the function to allow simultaneous RX and TX. You'd have to update this every time they release a new version of the HAL.
The problem is that the ST HAL isn't meant to be used with an RTOS. It says so in the definition of the macro __HAL_LOCK. Redefining it to use the RTOS's mutexes might worth trying as well. Same with HAL_Delay() to use the RTOS's thread sleep function.
In general though, sending via a blocking function in a thread should be fine, but I would not receive data using a blocking function in a thread. You are bound to experience overrun errors that way.
Likewise, if you put too much processing in the receive interrupt you might also run into overrun errors. I prefer using DMA for reception, followed by interrupts if I've run out of DMA streams. The interrupt only copies the data to a buffer, similarly to the DMA. A processRxData thread is then used to process the actual data.
When using FreeRTOS, you have to set interrupt priority to 5 or above, because below 5 is reserved for the OS.
So change your code to set the priority to:
HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
The problem turned out to be something to do with blocking statements.
Since UART_Receive_Thread has HAL_UART_Receive inside and that is blocking the thread until something is received, that results in a busy HAL (hence, the HAL_BUSY state).
The solution was using non-blocking statements without changing anything else.
i.e. using HAL_UART_Receive_IT and HAL_UART_Transmit_IT at the same time and ignoring blocking statements worked.
Thanks for all suggestions that lead to this solution.

pic Interrupt on change doesn't trigger first time

I'm trying to comunicate a pic18f24k50 with an arduino 101. I'm using two lines to establish a synchronized comunication. On every change from low to high of the first line, I read the value from the second line.
I have no problems with the arduino code, my problem is that in the pic, the Interrupt on change triggers on the second change from low to high instead of triggering on the first change. This only happens the first time I send data, after that, it works perfectly (it triggers on the first change and I receive the byte properly). Sorry for my english, I'll try to explain myself better with this image:
Channel 1 is the clock signal, channel2 is the data (Im sending one byte for the moment, with bit values 10101010). Channel 4 is an output I'm changing every time I process a bit. (as you can see, it begins on the second rise of the clock signal instead of the first one). This is captured on the first sent byte, the next ones works ok.
I post the relevant code in the pic here:
This is where I initialize things:
TRISCbits.TRISC6 = 0;
TRISCbits.TRISC1 = 1;
TRISCbits.TRISC2 = 1;
IOCC1 = 1;
ANSELCbits.ANSC2=0;
IOCC2 = 0;
INTCONbits.IOCIE = 1;
INTCONbits.IOCIF = 0;
And this is on the interrupt code:
void interrupt SYS_InterruptHigh(void)
{
if (INTCONbits.IOCIE==1 && INTCONbits.IOCIF==1)
{
readByte();
}
}
void readByte(void)
{
while(contaBits<8)
{
INTCONbits.IOCIE = 0;
INTCONbits.IOCIF = 0;
while (PORTCbits.RC1 != HIGH)
{
}
if (PORTCbits.RC1 == HIGH)
{
LATCbits.LATC6 = !LATCbits.LATC6;
//LATCbits.LATC6 = ~LATCbits.LATC6;
switch (contaBits)
{
case 0:
if (PORTCbits.RC2 == HIGH)
varByte.b0 = 1;
else
varByte.b0 = 0;
break;
case 1:
if (PORTCbits.RC2 == HIGH)
varByte.b1 = 1;
else
varByte.b1 = 0;
break;
case 2:
if (PORTCbits.RC2 == HIGH)
varByte.b2 = 1;
else
varByte.b2 = 0;
break;
case 3:
if (PORTCbits.RC2 == HIGH)
varByte.b3 = 1;
else
varByte.b3 = 0;
break;
case 4:
if (PORTCbits.RC2 == HIGH)
varByte.b4 = 1;
else
varByte.b4 = 0;
break;
case 5:
if (PORTCbits.RC2 == HIGH)
varByte.b5 = 1;
else
varByte.b5 = 0;
break;
case 6:
if (PORTCbits.RC2 == HIGH)
varByte.b6 = 1;
else
varByte.b6 = 0;
break;
case 7:
if (PORTCbits.RC2 == HIGH)
varByte.b7 = 1;
else
varByte.b7 = 0;
break;
}
contaBits++;
}
}//while(contaBits<8)
INTCONbits.IOCIE = 1;
contaBits=0;
}
LATCbits.LATC6 = !LATCbits.LATC6; <-- this is the line corresponding to channel 4.
RC1 is channel 1
and RC2 is channel 2
My question is what am I doing wrong, why on the first sent of bytes the interrupt doesn't triggers on the first change of the line 1?
Thank you.
What are you trying to achieve?
The communication protocol as you're describing is commonly refered to as SPI (Serial Peripheral Interface). You should use the hardware implementation available by PIC/Microchip, if possible, for best performance.
Keep your code documented/formatted/logic
I noticed your code being a little, weird.
Weird code gives weird errors.
First:
You're using interrupts, you have this blocking code in your interrupt. Which isn't nice at all.
Second:
Your "contabits" and "varByte" variable come out of nowhere, probably they're global. Which might not be the best practice.
Though, if you're using interrupts, and when it might make sense to transfer the variables to your main program by using a global. The global should be volatile.
Third:
That case switch is just 8x the same code, but a little different.
Also, add some comments to your code.
To be honest
I didn't spot your actual error, has been a long time since I worked with PIC.
But, you should try hardware SPI.
Below is my attempt at software SPI as you described, it might be a little more logical, and takes out any annoyance of the interrupts.
I would recommend replacing the while(CLOCK_PIN_MACRO != 1){}; with for(unsigned int timeout = 64000; timeout > 0; timeout--){};.
So that you can be sure your program won't hang while waiting for an SPI signal that won't come. (Make the timeout something what fits your needs)
#define CLOCK_PIN_MACRO PORTCbits.RC1
#define DATA_PIN_MACRO PORTCbits.RC2
/*
Test, without interrupts.
I would strongly advise to use Hardware SPI or non-blocking code.
*/
unsigned char readByte(void){
unsigned char returnByte = 0;
for(int i = 0; i < 8; i++){ //Do this for bit 0 to 7, to get a complete byte.
while(CLOCK_PIN_MACRO != 1){}; //Wait until the Clock pin goes high.
if(DATA_PIN_MACRO == 1) //Check the data pin.
returnByte = returnByte & (1 << i); //Shift the bit in our byte. (https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/BitOp/bitshift.html)
while(CLOCK_PIN_MACRO == 1){}; //Wait untill the Clock pin goes low again.
}
return returnByte;
}
void setup(){
TRISCbits.TRISC6 = 0;
TRISCbits.TRISC1 = 1;
TRISCbits.TRISC2 = 1;
//IOCC1 = 1;
ANSELCbits.ANSC2=0;
//IOCC2 = 0;
INTCONbits.IOCIE = 1;
INTCONbits.IOCIF = 0;
}
void run(){
unsigned char theByte = readByte();
}
main(){
setup();
while(1){
run();
}
}
You can find the following from the datasheet.
The pins are compared with the old value latched on the last read of
PORTB. The "mismatch" outputs of RB7:RB4 are ORed together to generate
the RB Port Change Interrupt with Flag bit,RBIF (INTCON<0>).
This means that when you read PORTB RB7:RB4 pins, the value of each pin will be stored in an internal latch. Interrupt will be generated only when there is any change in the pin input from the previously latched value.
Then, what will be the default initial value in the latch? i.e. Before we read anything from PORTB.
What ever it is. in your case the default latch value is different from the logic state of your input signal. During the next transition of the signal the latch value and signal level becomes same. So no intterrupt is generated first time.
What you can do is setting the latch value to the initial state of your signal. This can be done by reading PORTB (should be done before enabling the intterrupt).
The below code is enough to simply read the register.
unsigned char ch;
ch = PORTB;
Hope this will help.

Traffic lights simulation and xbee communication

So i am having this project. The system will give priority to emergency vehicles when they get close to traffic lights and when they get close i want to change the state of the traffic lights from red to green but in correct sequence.
I have managed to pull it off but it doesnt work with a real car because the xbees (coordinator on the vehicle and end device on home-made traffic lights) take sometime to communicate which is not enough for the speed of a vehicle approaching traffic lights with lets say an average speed of 60km/h.
The system works like this. There is an arduino on the vehicle which has a GPS shield and an xbee set to COORDINATOR on it. In the program on the arduino it checks if the gps reads coordinates that are saved inside the arduino so it checks against real time coordinates and if they match, the xbee gets to send a message across to the corresponding xbees that are set as end-devices on the traffic lights which again setup is arduino + xbee.
The problem 1 is i need to make a faster connection between the xbees (COORDINATOR - END DEVICE)
Here is the arduino sketch for ARDUINO-GPS-COORDINATOR. Note: GPS Shield is from adafruit and i use their code plus some of mine.
// Test code for Adafruit GPS modules using MTK3329/MTK3339 driver
//
// This code shows how to listen to the GPS module in an interrupt
// which allows the program to have more 'freedom' - just parse
// when a new NMEA sentence is available! Then access data when
// desired.
//
// Tested and works great with the Adafruit Ultimate GPS module
// using MTK33x9 chipset
// ------> http://www.adafruit.com/products/746
// Pick one up today at the Adafruit electronics shop
// and help support open source hardware & software! -ada
#include <Adafruit_GPS.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11);
SoftwareSerial xbee(13,12);
// If using hardware serial (e.g. Arduino Mega), comment out the
// above SoftwareSerial line, and enable this line instead
// (you can change the Serial number to match your wiring):
//HardwareSerial mySerial = Serial1;
Adafruit_GPS GPS(&mySerial);
// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences.
#define GPSECHO true
// this keeps track of whether we're using the interrupt
// off by default!
boolean usingInterrupt = false;
void useInterrupt(boolean); // Func prototype keeps Arduino 0023 happy
void setup()
{
Serial.begin(115200);
Serial.println("Adafruit GPS library basic test!");
xbee.begin(9600);
xbee.println("SoftwareSerial on coordinator working!");
GPS.begin(9600);
// uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
// uncomment this line to turn on only the "minimum recommended" data
//GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
// For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since
// the parser doesn't care about other sentences at this time
// Set the update rate
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate
// For the parsing code to work nicely and have time to sort thru the data, and
// print it out we don't suggest using anything higher than 1 Hz
// Request updates on antenna status, comment out to keep quiet
GPS.sendCommand(PGCMD_ANTENNA);
// the nice thing about this code is you can have a timer0 interrupt go off
// every 1 millisecond, and read data from the GPS for you. that makes the
// loop code a heck of a lot easier!
useInterrupt(true);
delay(1000);
// Ask for firmware version
mySerial.println(PMTK_Q_RELEASE);
}
// Interrupt is called once a millisecond, looks for any new GPS data, and stores it
SIGNAL(TIMER0_COMPA_vect) {
char c = GPS.read();
// if you want to debug, this is a good time to do it!
#ifdef UDR0
if (GPSECHO)
if (c) UDR0 = c;
// writing direct to UDR0 is much much faster than Serial.print
// but only one character can be written at a time.
#endif
}
void useInterrupt(boolean v) {
if (v) {
// Timer0 is already used for millis() - we'll just interrupt somewhere
// in the middle and call the "Compare A" function above
OCR0A = 0xAF;
TIMSK0 |= _BV(OCIE0A);
usingInterrupt = true;
} else {
// do not call the interrupt function COMPA anymore
TIMSK0 &= ~_BV(OCIE0A);
usingInterrupt = false;
}
}
// difference_ratio
float diff_ratio = 0.010;
// COORDINATES INDEX
float coord_lat = 23;
float coord_lon = 23;
uint32_t timer = millis();
void loop() // run over and over again
{
// in case you are not using the interrupt above, you'll
// need to 'hand query' the GPS, not suggested :(
if (! usingInterrupt) {
// read data from the GPS in the 'main loop'
char c = GPS.read();
// if you want to debug, this is a good time to do it!
if (GPSECHO)
if (c) Serial.print(c);
}
// if a sentence is received, we can check the checksum, parse it...
if (GPS.newNMEAreceived()) {
// a tricky thing here is if we print the NMEA sentence, or data
// we end up not listening and catching other sentences!
// so be very wary if using OUTPUT_ALLDATA and trytng to print out data
//Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false
if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false
return; // we can fail to parse a sentence in which case we should just wait for another
}
// if millis() or timer wraps around, we'll just reset it
if (timer > millis()) timer = millis();
// approximately every 2 seconds or so, print out the current stats
if (millis() - timer > 2000) {
timer = millis(); // reset the timer
Serial.print("\nTime: ");
Serial.print(GPS.hour, DEC); Serial.print(':');
Serial.print(GPS.minute, DEC); Serial.print(':');
Serial.print(GPS.seconds, DEC); Serial.print('.');
Serial.println(GPS.milliseconds);
Serial.print("Date: ");
Serial.print(GPS.day, DEC); Serial.print('/');
Serial.print(GPS.month, DEC); Serial.print("/20");
Serial.println(GPS.year, DEC);
Serial.print("Fix: "); Serial.print((int)GPS.fix);
Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
if (GPS.fix) {
//Serial.print("Location: ");
//Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
//Serial.print(", ");
//Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
Serial.print("Location (in degrees, works with Google Maps): ");
Serial.print(GPS.latitudeDegrees, 4);
Serial.print(", ");
Serial.println(GPS.longitudeDegrees, 4);
//Serial.print("Speed (knots): "); Serial.println(GPS.speed);
//Serial.print("Angle: "); Serial.println(GPS.angle);
//Serial.print("Altitude: "); Serial.println(GPS.altitude);
//Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
if(GPS.latitudeDegrees + diff_ratio >= coord_lat && coord_lat >= GPS.latitudeDegrees - diff_ratio) {
if(GPS.longitudeDegrees + diff_ratio >= coord_lon && coord_lon >= GPS.longitudeDegrees - diff_ratio){
Serial.println("location OKAY");
xbee.println("K");
}
}
//if((float)GPS.latitude > (home_lat - diff_ratio) && (float)
}
}
}
The important part is where it says if(GPS.fix()) and later on.
And here is the sketch for the traffic light simulation which if it receives the message "K" it will stay to green light until it does not receive it anymore.
#include <SoftwareSerial.h>
SoftwareSerial xbee(3,2);
int greenled = 8; //Led's and pins
int yellowled = 9;
int redled = 10;
int ard_led = 13;
void setup(){
pinMode(greenled,OUTPUT);
pinMode(yellowled, OUTPUT);
pinMode(redled, OUTPUT);
pinMode(ard_led,OUTPUT);
Serial.begin(9600);
xbee.begin(9600);
}
void loop(){
delay(700);
if(xbee.available() > 0 && xbee.read() == 'K' && digitalRead(ard_led) == 0){
//Serial.println("second block");
digitalWrite(redled,HIGH);
delay(1000);
digitalWrite(yellowled, HIGH); //Yellow and red on for 2 seconds
digitalWrite(ard_led,HIGH);
}else if(xbee.available() > 0 && xbee.read() == 'K' && digitalRead(ard_led) == 1){
//Serial.println("third block");
blinking_green();
}
else if(!xbee.available() && xbee.read() != 'K' && digitalRead(greenled) == 0){
//Serial.println("first block");
digitalWrite(redled, HIGH);
delay(1000);
digitalWrite(yellowled, HIGH); //Yellow and red on for 2 seconds
delay(1000);
digitalWrite(redled, LOW); //Red and Yellow off
digitalWrite(yellowled, LOW);
digitalWrite(greenled, HIGH); //Green on for 5 seconds
delay(3000);
digitalWrite(greenled, LOW); //Green off, yellow on for 2 seconds
digitalWrite(yellowled, HIGH);
delay(1000);
digitalWrite(yellowled,LOW);
digitalWrite(redled,HIGH);
} else if(!xbee.available() && xbee.read() != 'K' && digitalRead(greenled) == 1 && digitalRead(yellowled == 0)){
//Serial.println("fourth block");
digitalWrite(greenled,LOW);
digitalWrite(yellowled, HIGH);
delay(1000);
digitalWrite(yellowled, LOW);
digitalWrite(redled,HIGH);
digitalWrite(ard_led,LOW);
}
}
void blinking_green(){
digitalWrite(redled, LOW); //Red and Yellow off
digitalWrite(yellowled, LOW);
digitalWrite(greenled,HIGH);
delay(2500);
}
Problem 2: How can i interrupt the traffic lights simulation instantly when it receives a message from a nearby arduino to change the traffic light to green BEFORE it finishes that loop? Because in a real example green and red light would say for over 20 seconds.
Question: Will a faster baud rate on the xbees achieve faster xbee communication?
thank you in advance
You need to change the loop() on your traffic light simulation. Have a variable you use to store the "state" of the light, along with a timer to keep track of when the next state change happens. This way, your loop can also check the XBee serial input every time around.
if (xbee_event_happened()) {
set_leds_off();
timer = millis();
state = STATE_FLASH_GREEN_OFF;
}
switch (state) {
case STATE_FLASH_GREEN_OFF:
if (millis() - timer > 1000) {
set_leds_green();
state = STATE_FLASH_GREEN_ON;
timer = millis();
}
break;
case STATE_FLASH_GREEN_ON:
if (millis() - timer > 1000) {
set_leds_off();
state = STATE_FLASH_GREEN_OFF;
timer = millis();
}
break;
case STATE_RED:
if (millis() - timer > 5000) {
set_leds_green();
state = STATE_GREEN;
timer = millis();
}
break;
case STATE_GREEN:
if (millis() - timer > 3000) {
set_leds_yellow();
state = STATE_YELLOW;
timer = millis();
}
break;
// etc.
}
This just covers the basics, but it shows an important aspect of loop() function design -- it should never run for more than a few milliseconds. Don't have a delay inside of your main loop, track the state of the device and then use logic to decide if the state needs to change on that pass of the loop.
Additionally, use higher baud rates when possible to avoid latency from serial transmissions, get rid of the 700ms delay in your loop, and organize your if/else structure better:
if (xbee.available() > 0) {
character = xbee.read();
if (character == 'K') {
if (digitalRead(ard_led)) {
// second block
} else {
// third block
}
} else if (character == 'X') {
// do something different? Vehicle left area?
}
}

Embedded: SDHC SPI write issue

I am currently working at a logger that uses a MSP430F2618 MCU and SanDisk 4GB SDHC Card.
Card initialization works as expected, I also can read MBR and FAT table.
The problem is that I can't write any data on it. I have checked if it is write protected by notch, but it's not. Windows 7 OS has no problem reading/writing to it.
Though, I have used a tool called "HxD" and I've tried to alter some sectors (under Windows). When I try to save the content to SD card, the tool pop up a windows telling me "Access denied!".
Then I came back to my code for writing to SD card:
uint8_t SdWriteBlock(uchar_t *blockData, const uint32_t address)
{
uint8_t result = OP_ERROR;
uint16_t count;
uchar_t dataResp;
uint8_t idx;
for (idx = RWTIMEOUT; idx > 0; idx--)
{
CS_LOW();
SdCommand(CMD24, address, 0xFF);
dataResp = SdResponse();
if (dataResp == 0x00)
{
break;
}
else
{
CS_HIGH();
SdWrite(0xFF);
}
}
if (0x00 == dataResp)
{
//send command success, now send data starting with DATA TOKEN = 0xFE
SdWrite(0xFE);
//send 512 bytes of data
for (count = 0; count < 512; count++)
{
SdWrite(*blockData++);
}
//now send tow CRC bytes ,through it is not used in the spi mode
//but it is still needed in transfer format
SdWrite(0xFF);
SdWrite(0xFF);
//now read in the DATA RESPONSE TOKEN
do
{
SdWrite(0xFF);
dataResp = SdRead();
}
while (dataResp == 0x00);
//following the DATA RESPONSE TOKEN are a number of BUSY bytes
//a zero byte indicates the SD/MMC is busy programing,
//a non_zero byte indicates SD/MMC is not busy
dataResp = dataResp & 0x0F;
if (0x05 == dataResp)
{
idx = RWTIMEOUT;
do
{
SdWrite(0xFF);
dataResp = SdRead();
if (0x0 == dataResp)
{
result = OP_OK;
break;
}
idx--;
}
while (idx != 0);
CS_HIGH();
SdWrite(0xFF);
}
else
{
CS_HIGH();
SdWrite(0xFF);
}
}
return result;
}
The problem seems to be when I am waiting for card status:
do
{
SdWrite(0xFF);
dataResp = SdRead();
}
while (dataResp == 0x00);
Here I am waiting for a response of type "X5"(hex value) where X is undefined.
But most of the cases the response is 0x00 (hex value) and I don't get out of the loop. Few cases are when the response is 0xFF (hex value).
I can't figure out what is the problem.
Can anyone help me? Thanks!
4GB SDHC
We need to see much more of your code. Many µC SPI codebases only support SD cards <= 2 GB, so using a smaller card might work.
You might check it yourself: SDHC needs a CMD 8 and an ACMD 41 after the CMD 0 (GO_IDLE_STATE) command, otherwise you cannot read or write data to it.
Thank you for your answers, but I solved my problem. It was a problem of timing. I had to put a delay at specific points.