London
Offline
Faraday Member
Karma: 6
Posts: 6226
Have fun!
|
 |
« Reply #135 on: April 16, 2010, 06:23:13 am » |
The problem may be that you are printing data even if nothing is received. try something like this: void loop() { if(mySerial.available() >= 6 && mySerial.read()=='q') { data = 0; inData = 0; while(inData != 'p') { inData = mySerial.read(); if(inData >= '0' && inData <= '9') data = data * 10 + inData - '0'; } if(data>=0 && data<=3600) Serial.println(data, DEC); } }
|
|
|
|
|
Logged
|
|
|
|
|
Batangas, Philippines
Offline
Newbie
Karma: 0
Posts: 36
Arduino rocks
|
 |
« Reply #136 on: April 19, 2010, 09:27:30 pm » |
Thanks mem! tried it out. Is this output reasonable enough or is there any other way I could eliminate more unnecessary data: 2665 2665 2669 2670 26 8 267 2 669 2267 8 267 2667 2667 2667 266 2669 0 266 2 266 269 268 2668 2668 268 2669 2669 269 26 266 266 0 2454 0 2 260 1490 787 2671 267 2672 2672 2672 262 267 2671 2671 267 2671 267 2670 2670 2670 2669 0 524 0 26 269 26 2667 267 2665 266 2665 2665 266 2665 266 2667 2667 266 2667 266 2669 2669 2669 269 2669 525 2669 2668 2 2 266 269 62 96 6 2669 2669 669 266 269 2669 2669 2669 266 269 2669 525 6 271 271 269 669 2669 268 266 2668 2668 266 2669 269 2669 2669 2669 268 266 2668 2668 266 2668 266 2668 2668 2668 266 2667 2667 266 2668 2668 266 2669 669 86 268 69 96 26 2669 72 269 262 268 268 0 626 269 266 266 267 2668 266 267 267 0 882 0 2 267 267 7 62 62 266 669 2669 2666 26 267 2667 266 2667 2667 266 2667 2669 0 2666 2666 2662 26 2667 9 2702 266 266 2688 2667 27 266 267 2669 2667 2669 26 2670 2670 2670 2 1197 2669 669 266 2669 2669 2667 26 26 2 2669 266 269 666 2670 2670 0 2667 2667 2667 266 266 266 0 268 266 0 266 2669 26 2668 2668 267 26 0 9 262 0 267 3530 2667 2667 266 267 266 2666 266 2267 0 669 2667 523 729 62 266 2668 266 266 2668 2668 2668 0 2669 266 1 2672 2669 0 26 2669 2669 268 26 0 27 2666 2 2669 2669 2669 2 2670 270 2670 2669 2668 266 267 266 8 2669 730 0 2669 2669 2669 269 2669 2669 29 2671 0 0 266 269 170 2668 2668 2668 1290 669 2669 2668 2 2669 669 266 2669 2669 2669 266 2669 2669 2669 266 266 0 266 2668 26 2669 2669 2669 0 266 269 226 2671 271 267 22 2669 1390 269 669 269 26 266 266 268 2668 2668 268 2668 2668 2668 668 266 2668 2668 266 266 268 2668 2668 2668 668 266 2668 2668 266 2668 269 2669 2669 0 266 2667 2669 2668 2 0 0 266 665 2665 2665 265 265 0 2669 669 0 266 266 266 266 2667 2667 267 2667 2667 2667 2667 267 2668 0 266 2666 2666 2666 2666 266 2665 2666 2666 26 522 266 6 288 1190 1120 2668 266 26 2669 2669 2669 26 525 69 266 268 2668 2668 267 2667 266 2666 266 2666 26 665 2666 2666 2666 266 0 266 2669 268 2666 2666 266 267 2666 2666 266 2666 2666 266 2666 2667 266 266 2667 266 266 2666 2666 2
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 2
Arduino rocks
|
 |
« Reply #137 on: April 21, 2010, 06:05:56 pm » |
I am doing something similar to one of the posters:
I am trying to connect the W800RF32 to an STK500 with an ATMEGA168 chip on it. I wrote code to read in the first byte and display the byte on 8 LEDs. The code works great with another serial output, but when I try to plug it up to the w800RF32
i get nothing (the uart reports no data).
The w800 works fine as I see the bytes when I connect it to WGLDesigns' debug software via serial cable.
When I connect the w800 to an oscilloscope it has a much weaker signal than my other device.
I am only connecting the W800's ground and Tx pins to the STk500's ground and the Rx on the atmega.
Am I doing something wrong? Do I need to beef up the signal?
|
|
|
|
|
Logged
|
|
|
|
|
London
Offline
Faraday Member
Karma: 6
Posts: 6226
Have fun!
|
 |
« Reply #138 on: April 21, 2010, 06:20:27 pm » |
[/quote] Is this output reasonable enough or is there any other way I could eliminate more unnecessary data[/quote] You need to say more about how the data you are receiving is formatted. If you have control over the sending side you could send a unique character to indicate the start of the data. If the data is not fixed length, you could also send an end of data character.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 2
Arduino rocks
|
 |
« Reply #139 on: April 23, 2010, 04:17:57 pm » |
Ah, I was using pin3 (isn't that TX?) but the signal is on Pin2 and very strong.
|
|
|
|
|
Logged
|
|
|
|
|
Batangas, Philippines
Offline
Newbie
Karma: 0
Posts: 36
Arduino rocks
|
 |
« Reply #140 on: April 28, 2010, 09:26:09 pm » |
You need to say more about how the data you are receiving is formatted. If you have control over the sending side you could send a unique character to indicate the start of the data. If the data is not fixed length, you could also send an end of data character. Well that was q and p intended for, maybe its the NSS' limitation?
|
|
|
|
|
Logged
|
|
|
|
|
London
Offline
Faraday Member
Karma: 6
Posts: 6226
Have fun!
|
 |
« Reply #141 on: April 28, 2010, 09:32:43 pm » |
@grindylow, could you post some lines of the data you are sending and also show what the sketch with NSS displays.
|
|
|
|
|
Logged
|
|
|
|
|
Batangas, Philippines
Offline
Newbie
Karma: 0
Posts: 36
Arduino rocks
|
 |
« Reply #142 on: April 28, 2010, 10:37:50 pm » |
This one sends compass data and uses hardware serial: #include <Wire.h> #include <CMPS03.h>
CMPS03 compass;
int compassReading; int led = 13; int btnRead;
void setup() { Serial.begin(9600); Wire.begin(); pinMode(led, OUTPUT); delay(1000); }
void loop() { compassReading = compass.read(); Serial.print('q'); Serial.print(compassReading, DEC); Serial.print('p'); if(Serial.available() > 0) btnRead = Serial.read(); if(btnRead == 'a') digitalWrite(led, HIGH); else digitalWrite(led, LOW); } This one receives data and uses NSS. It also displays serial output to the serial monitor: #include <NewSoftSerial.h>
const byte RX = 2; const byte TX = 3; const byte led = 13; const byte button = 4; NewSoftSerial mySerial(RX, TX); char inData; int data = 0;
void setup() { Serial.begin(9600); mySerial.begin(9600); pinMode(led, OUTPUT); pinMode(button, INPUT); delay(1000); }
void loop() { if(mySerial.available() >= 6 && mySerial.read() == 'q') { data = 0; inData = 0; while(inData != 'p') { inData = mySerial.read(); if(inData >= '0' && inData <= '9') data = data * 10 + inData - '0'; } Serial.println(data, DEC); }
if(digitalRead(button) == HIGH) { mySerial.print('a'); digitalWrite(led, HIGH); } else { mySerial.print('b'); digitalWrite(led, LOW); } } Look for my post above for the display on the serial monitor. thanks..
|
|
|
|
|
Logged
|
|
|
|
|
London
Offline
Faraday Member
Karma: 6
Posts: 6226
Have fun!
|
 |
« Reply #143 on: April 29, 2010, 03:13:08 am » |
It may also be worth trying to add a delay in your loop code to see if that helps. Try delay(100); If not, try running a test that sends known data: void loop() { Serial.print('q'); Serial.print(1234, DEC); Serial.print('p'); if(Serial.available() > 0) btnRead = Serial.read(); if(btnRead == 'a') digitalWrite(led, HIGH); else digitalWrite(led, LOW); } Then post the results.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 6
Arduino rocks
|
 |
« Reply #144 on: April 29, 2010, 03:15:59 am » |
Perhaps this is a silly question...
Is there any reason why the NewSoftSerial library busy waits in the interrupt handler? Surely this is pretty inefficient, and obviously has major challenges at very low baud rates.
Is there a reason why you couldn't utilise the timer and pin change interrupts to do things slightly differently?
For the moment I'm thinking about receive (although you could do the same for xmit), there are two approaches that I can think of...
1. Interrupt on the first pin change (as done currently), then set a timer to overflow in the middle of each following bit and use the interrupt to read the value. Once you get the stop bit you can disable the timer and save the byte in the buffer.
2. Possibly a bit more complex, but potentially less overhead, interrupt on the first pin change, set a timer to end on the stop bit, track any state changes in between and create the byte according to the time when the state change happened (using the timer countdown value).
With some clever timer work I would have thought you could get to a point where you can run a couple of concurrent software serial lines at reasonable speeds, and generally have much more available cpu time for the non-interrupt code.
I am very new to the Arduino, so I'm probably missing something fundamental, but if not I'll have a go at hacking something together to test the theory.
Lee.
|
|
|
|
|
Logged
|
|
|
|
|
Austin, TX USA
Offline
God Member
Karma: 3
Posts: 992
Arduino rocks
|
 |
« Reply #145 on: April 29, 2010, 07:16:35 am » |
Lee, that's not a silly question at all.
About a year ago a couple of us investigated doing something like this and actually developed some code that demonstrated the workability at low baud rates. The problem is that higher baud rates demand a level of timing precision that the Arduino cannot provide. Let's say you've just received 6 bits of your byte and are eagerly waiting for that interrupt to fire, signaling the arrival of the 7th. But wait -- another timer or interrupt has fired first and yours is delayed. At higher speeds it doesn't take much delay to cause the bit to be read after it has already changed values -- corrupting the data stream.
Thanks for the input.
Mikal
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 6
Arduino rocks
|
 |
« Reply #146 on: April 29, 2010, 08:46:56 am » |
Mikal, thanks for the response.
Very interesting ... but that suggests to me that my second option would still work, in that model you are only really interested in pin transitions and providing you log the time they happen it almost doesn't matter when you come back to analyse the data and recreate the stream. In fact the timer is only really needed to ensure that you can capture the last duplicate-high bit if there is no following data.
i.e.
pin goes low, so this is the beginning of the start bit, start a timer for 10.5 bits time (middle of stop bit), set data to 00000000. pin goes high, look at the time, this is the third bit, toggle 3rd bit onwards, data becomes 00111111. ping goes low, look at the time, this is the 7th bit, toggle 7th bit onwards, data becomes 00111100. etc.
In this case the stop bit would trigger an interrupt so the timer wouldn't actually be needed, but if the data ended in 1's, then the stop bit wouldn't trigger and therefore the timer would be needed.
Worst case, if somehow the timer is *way* delayed, we get the new start bit trigger and have to deal with the previous byte first.
The pin change interrupts are higher priority than all the timers, so it only leaves the external interrupts to give you a concern.
I may be flogging a dead horse, but it's been years since I've played with this kind of stuff and I seem to have turned into a kid again :-)
Lee.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 6
Arduino rocks
|
 |
« Reply #147 on: April 30, 2010, 11:56:36 am » |
Ok, I've built a very rough example (with loads of hardcoding and assumptions) ... this seems to work nicely at 9600 baud ... it's actually all hardcoded at that speed for the moment. Obviously there's a whole lot of things that could be done to make this more efficient, and there's a few more error checks that would be needed (like getting a new start bit when the timer hadn't gone off etc) which would also make it more resilient against major timer issues. I would have thought you could get this to use Timer0 (without changing wiring.c) with some clever use of the compare interrupts, but I don't think the standard 64 clock cycle resolution would cut it for much faster than 9600, although I expect you could manage multiple 9600's ok -- that will be my next test as well as seeing how fast I can push this. If you needed to support multiple serial lines at different rates, then the timer mechanism would need to get more sophisticated. Please don't laugh at my code ... this was done in a hurry, I did borrow some from NewSoftSerial, and it's my first Arduino code (other than noddy examples) ... #include <avr/interrupt.h> #include "pins_arduino.h"
#ifndef cbi #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #endif #ifndef sbi #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) #endif
#if !defined(digitalPinToPCICR) // Courtesy Paul Stoffregen #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) #define digitalPinToPCICR(p) (((p) >= 0 && (p) <= 21) ? (&PCICR) : ((uint8_t *)NULL)) #define digitalPinToPCICRbit(p) (((p) <= 7) ? 2 : (((p) <= 13) ? 0 : 1)) #define digitalPinToPCMSK(p) (((p) <= 7) ? (&PCMSK2) : (((p) <= 13) ? (&PCMSK0) : (((p) <= 21) ? (&PCMSK1) : ((uint8_t *)NULL)))) #define digitalPinToPCMSKbit(p) (((p) <= 7) ? (p) : (((p) <= 13) ? ((p) - 8) : ((p) - 14))) #else #define digitalPinToPCICR(p) ((uint8_t *)NULL) #define digitalPinToPCICRbit(p) 0 #define digitalPinToPCMSK(p) ((uint8_t *)NULL) #define digitalPinToPCMSKbit(p) 0 #endif #endif
uint8_t bit = 0; // 0 = start bit, 1-8 = data, 9= stop bit volatile uint8_t data = 0; // the byte we are reading
// This is a noddy buffer to store the input... no overflow at the moment uint8_t buffer[32]; int p_save = 0; int p_get = 0; volatile int avail;
// Quick way of twiddling the right bits given the bit coming in... uint8_t bitmasks[8] = { 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80 };
// Bits for the port access... int port; volatile uint8_t *portRegister; uint8_t bitMask;
// This will be called for a pin state change, but we'll also call it if the timer // goes off... inline void handle_interrupt() { uint8_t val = *portRegister & bitMask;
// If we're the first signal the we are expecting a start bit (low), anything else // we just ignore. if(bit == 0) { if(val) return; data = 0; bit++; // Allow the timer to run... TCNT2 = 255-247; // 247 = 988us which is 9.5 bits sbi(TIFR2, TOV2); // this clears the overflow flag to stop instant interrupts. sbi(TIMSK2, TOIE2); } else { // This is a bit hacky ... we'll count what time the bit comes in using the timer // but we'll allow 13 timer ticks (52us) of flexibility, this is good since we // can cope with timing problems, but it does mean the timer will probably come in // at bit 10 (or wrap to bit 0 in this calc...) bit = (TCNT2 - ((255-247) - 13)) / 26; if(bit == 9 || bit == 0) { // clear the timer... cbi(TIMSK2, TOIE2); bit = 0; buffer[p_save] = data; p_save++; if(p_save == 32) p_save = 0; avail++; return; } if(!val) { data &= ~bitmasks[bit-1]; } else { data |= bitmasks[bit-1]; } } }
#if defined(TIMER2_OVF_vect) ISR(TIMER2_OVF_vect) { cbi(TIMSK2, TOIE2); // pretent we've had a signal change... handle_interrupt(); } #endif
#if defined(PCINT0_vect) ISR(PCINT0_vect) { handle_interrupt(); } #endif
#if defined(PCINT1_vect) ISR(PCINT1_vect) { handle_interrupt(); } #endif
#if defined(PCINT2_vect) ISR(PCINT2_vect) { handle_interrupt(); } #endif
int rx_pin = 5; int tx_pin = 6;
void setup() { Serial.begin(9600); pinMode(13, OUTPUT); pinMode(rx_pin, INPUT); // RX pinMode(tx_pin, OUTPUT); // TX digitalWrite(rx_pin, HIGH); // pullup for normal logic *digitalPinToPCICR(rx_pin) |= _BV(digitalPinToPCICRbit(rx_pin)); *digitalPinToPCMSK(rx_pin) |= _BV(digitalPinToPCMSKbit(rx_pin)); port = digitalPinToPort(rx_pin); portRegister = portInputRegister(port); bitMask = digitalPinToBitMask(rx_pin); // Let's mess around with timer2.... // Need to set it to normal mode, since the wiring.c code will set phase correct PWM cbi(TCCR2A, WGM20); // Let's make sure we have normal port operation cbi(TCCR2A, COM2A0); cbi(TCCR2A, COM2A1); cbi(TCCR2A, COM2B0); cbi(TCCR2A, COM2B1); // We'll set the /64 scaler, since this gives us 4us per tick on a 16Mhz board, so the // overflow will happen at 1024us ... we need 988us for a 9.5 bit 9600 clock // probably already set by wiring, but we'll do it anyway sbi(TCCR2B, CS22); }
int by;
void loop() { while(avail > 0) { // This is a "get" routine ... but it's in here for now... cli(); by = buffer[p_get]; p_get++; if(p_get == 32) p_get = 0; avail--; sei(); Serial.print(by, BYTE); } delay(100); }
Lee.
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 2
Arduino rocks
|
 |
« Reply #148 on: May 12, 2010, 06:52:08 pm » |
Hi, I was happy to find the NewSoftSerial and I'm trying to implement it in my Code, using a rfid-reader(ID20) to a trigger a soundfile on a mp3-decoder(Vmusic2). It works but it's really slow -it takes around 10 seconds to process what didn't happened to me with the old softwareSerial which reacted instantly (but i could only use 1 soft serial). What seems strange to me is that my LED test light (Line 57 - first part of the loop) goes high, but the delay instead of its 500ms works for around 10 seconds before it goes low again. Seems like it suspends, but i don't understand what could be happening there...?? Any guess what's wrong? (obviously i'm a newbie and thats just my second code i write..) thanks a lot flo #include <NewSoftSerial.h> /* Microcontroller RFID Reader Language: Wiring/Arduino
Reads data serially from a (Parallax or) ID Innovations ID12 RFID reader. */ #define ID20_RX 2 #define ID20_TX 3
#define VMUSIC_RX 7 #define VMUSIC_TX 8
#define tagLength 10 // each tag ID contains 10 bytes #define startByte 0x02 // for the ID Innovations reader, use 0x02 #define endByte 0x03 // for the ID Innovations reader, use 0x03 #define dataRate 9600 // for the ID Innovations reader, use 9600
//set up a new serial port NewSoftSerial musicSerial = NewSoftSerial(VMUSIC_RX, VMUSIC_TX); NewSoftSerial idSerial = NewSoftSerial(ID20_RX, ID20_TX);
char val = 0; // TEST variable to store the data from the serial port int LED = 4; // TEST testLED int test = 333; // TEST variable
char tagID[tagLength + 1]; // array to hold the tag you read int tagIndex = 0; // counter for number of bytes read int tagComplete = false; // whether the whole tag's been read char rotundrund[] = "3A0082556D"; char weissekarte[] = "460071B5EC";
int tracknumber = 0;
void setup() { Serial.begin(dataRate); // define pin modes for tx, rx: pinMode(VMUSIC_RX, INPUT); pinMode(VMUSIC_TX, OUTPUT); pinMode(ID20_RX, INPUT); pinMode(ID20_TX, OUTPUT); pinMode(LED, OUTPUT); // set the data rate for the SoftwareSerial port musicSerial.begin(9600); idSerial.begin(9600); }
void loop() { // read in and parse serial data: if (idSerial.available() > 0) { readByte(); digitalWrite(LED, HIGH); delay(500); digitalWrite(LED, LOW); } // if - check ob tag schon da ist, sonst nicht ausdrucken if(tagComplete == true) { Serial.println(tagID);
// in Array reinschreiben -> Neue Funktion
tagComplete = false;
if (strcmp(tagID, rotundrund) == 0) { // Serial.println("rot und rund"); // read from Vmusic // Serial.println("playing track 2 "); //ich glaube musicserial eht hier nicht weil nict aktiviert // musicSerial.print("VPF 002.mp3"); // musicSerial.print(0x0D,BYTE); } else if (strcmp(tagID, weissekarte) == 0) { Serial.println("weisse karte"); } else { Serial.println("unbekannte ID"); }
} // Array abchecken mit PlayList -> Neue Funktion
// ------------- Warum druckt es immer wieder aus? Kann man das stoppen? --------------- }
/* This method reads the bytes, and puts the appropriate ones in the tagID */ void readByte() { char thisChar = idSerial.read(); //Serial.print(thisChar, HEX); // TEST: read whole tagstrip with StartByte & Endbyte switch (thisChar) { case startByte: // start character // reset the tag index counter tagIndex = 0; break; case endByte: // end character tagComplete = true; // you have the whole tag tagID[tagLength + 1] = '\0'; break; default: // any other character tagComplete = false; // there are still more bytes to read // add the byte to the tagID if (tagIndex < tagLength) { tagID[tagIndex] = thisChar; // increment the tag byte counter tagIndex++; } break; } }
|
|
|
|
« Last Edit: May 12, 2010, 07:28:49 pm by flofluse »
|
Logged
|
|
|
|
|
UK
Offline
Faraday Member
Karma: 15
Posts: 2852
Gorm deficient
|
 |
« Reply #149 on: May 13, 2010, 01:45:42 am » |
Could it be something to do with repeated calls to "delay (500);"? Like, a half-second delay for every received character?
|
|
|
|
« Last Edit: May 13, 2010, 01:46:27 am by GrooveFlotilla »
|
Logged
|
Per Arduino ad Astra
|
|
|
|
|