Subject:
|
Re: light sensor problem?
|
Newsgroups:
|
lugnet.robotics.rcx.legos
|
Date:
|
Mon, 24 Jul 2000 00:14:30 GMT
|
Viewed:
|
2358 times
|
| |
| |
> Having fixed the other screwup, I can report that snipping the code I
> discussed earlier allows everything to build just fine. It doesn't,
> however, solve the issue with the light sensors.
>
> I also tried swapping the two lines I mentioned earlier:
>
> mov.b r6l,@_ds_channel ; store next channel
> bclr r6l,@_PORT6:8 ; set output inactive for reading
>
> That didn't help either, at least not a whole lot. So... maybe the problem
> isn't in ds_handler(), but I can't figure out where else it could be.
> Anyone? Or does everyone else just not care that the scaling is screwed
> up?
I looked through the dsensor stuff, and it looks quite bad to me...
We execute a delay loop inside an interrupt handler.
We issue the command to start the next read from that same handler.
This will read the sensors very quickly, for the cost of high interrupt
load and (maybe) inproper driving of the sensors (See Kekoa's comments
in e-mails last year).
I doubt we need this very fast reading of sensors. This makes implementing
more sophisticated events like change over time and such harder.
Another aproach for the dsensor driver would be this:
Get a wakeup every X milliseconds. Inside the called routine:
- Turn of the output driver to the active sensors.
- Program timer compare B to wake up after the required
delay time.
Inside the timer interrupt:
- Program the A/D to sample all sensors and generate an interrupt.
Inside the A/D interrupt:
- Turn off A/D sampling.
- Read the A/D values for all sensors.
- Turn the output driver for the active sensors back on.
This scheme would be very efficient considering CPU resources. I did
not measure it yet, but we would probably sleep a lot more in the idle
process, so we should have better battery savings.
Also all sensors are quaranteed to be driven correctly, once the
constant needed for the 8 bit timer is well known. Speed should not
be a problem, as reading the sensors every 1 ms (for example) would
allow one rotation sensor 'tick' every 1 ms, i.e. one rotation every
16 ms, i.e. 62 rotations per second, which is 3720 rpm...
I have implemented some sample code, which takes over the ad_vector
from legOS and handles it similar to the above scheme. The values look
very stable and accurate with that.
If ACTIVE_SENSORS in the sample code below is defined to 0 (the default
state in legOS when no program is run, or no light/rotation sensor are
active), this code reduces power consumption from 26.3 mA to 18.1 mA
(I just measured it, after hacking up the sample, this seems to prove
the statement about efficiency above).
The user, and the battery handler of course ;-) should use the values
latched in ad_value[] as sensor data, this can easily be done with some
defines in dsensor.h.
Personally I like this code (or some code like this, if this evolves
into an actual driver) better for another reason: It contains less
assembly, which makes it easier to follow...
I will take this into our lab at work to measure the timing for the
light sensor with a scope, just to make shure we have this right. I just
don't know exactly when I will get to this, I hope within this week.
Eddie C. Dost
ecd@skynet.be
--
#include <conio.h>
#include <unistd.h>
#include <sys/h8.h>
#define SENSOR_READ_DELAY 100 /* microseconds (must be << 1ms) */
/* accuracy is 2 us, could be made */
/* better when changing systime to */
/* use TCR_CLOCK_8 */
#define SENSOR_READ_INTERVAL 2 /* milliseconds */
#define ACTIVE_SENSORS 7 /* 1, 2, and 3 */
static void ad_handler(void) __attribute__ ((rcx_interrupt));
static void ocib_handler(void) __attribute__ ((rcx_interrupt));
static unsigned char *rom_port6_ddr = (unsigned char *)0xfd85;
static unsigned int *ad_vector = (unsigned int *)0xfdbc;
static unsigned int *ocib_vector = (unsigned int *)0xfda4;
static unsigned short ad_value[4];
static unsigned char active_sensors;
static int display;
static void ad_handler(void)
{
AD_CSR &= ~(ADCSR_ENABLE_IRQ | ADCSR_START);
ad_value[0] = AD_C >> 6;
ad_value[1] = AD_B >> 6;
ad_value[2] = AD_A >> 6;
ad_value[3] = AD_D >> 6;
PORT6 |= active_sensors;
}
static void ocib_handler(void)
{
T_IER &= ~(TIER_ENABLE_OCB);
T_CSR &= ~(TCSR_OCB);
AD_CSR &= ~(ADCSR_END);
AD_CSR |= ADCSR_ENABLE_IRQ | ADCSR_START;
}
int
ad_thread(int argc, char **argv)
{
unsigned short cnt;
while (1) {
msleep(SENSOR_READ_INTERVAL);
/* Program OCRB:
*
* Watch out for wrap arounds! OCRA clears the
* counter at 500.
*/
cnt = (T_CNT + (SENSOR_READ_DELAY >> 1)) % 500;
PORT6 &= ~(active_sensors);
T_OCR |= TOCR_OCRB;
T_OCRB = cnt;
T_CSR &= ~(TCSR_OCB);
T_IER |= TIER_ENABLE_OCB;
}
}
static void ad_init(void)
{
*rom_port6_ddr |= 0x07;
PORT6_DDR = *rom_port6_ddr;
AD_CSR = 0;
*ad_vector = (unsigned int)ad_handler;
AD_CR &= ~(ADCR_EXTERN);
AD_CSR = ADCSR_TIME_266 | ADCSR_SCAN | ADCSR_GROUP_0 | ADCSR_AN_3;
*ocib_vector = (unsigned int)ocib_handler;
PORT6 |= active_sensors;
}
int
display_thread(int argc, char **argv)
{
while (1) {
lcd_number(ad_value[display], sign, e0);
msleep(50);
}
}
int
main(int argc, char **argv)
{
active_sensors = ACTIVE_SENSORS;
ad_init();
execi(ad_thread, 0, NULL, PRIO_HIGHEST - 1, 64);
execi(display_thread, 0, NULL, PRIO_NORMAL, DEFAULT_STACK_SIZE);
while (1) {
cputc_hex_0(display + 1);
wait_event(dkey_pressed, KEY_VIEW);
wait_event(dkey_released, KEY_VIEW);
display = (display + 1) & 3;
}
return 0;
}
|
|
Message has 2 Replies: | | Re: light sensor problem?
|
| (...) :) Bad is, of course, all relative... (...) Yes, though IMHO fast = good. It allows us to do things with legOS that might not be doable with other firmwares. (...) I'm not sure which comments you are referring to- do you have a URL for the (...) (24 years ago, 24-Jul-00, to lugnet.robotics.rcx.legos)
| | | Re: light sensor problem?
|
| (...) :-) It is not the best implementation I've seen... :-) (...) Yes. I hate the delay loop but we I can't imagine how to do it better if we still need maximum speed in reading values from sensors. The routine also change his sampling speed if we (...) (24 years ago, 24-Jul-00, to lugnet.robotics.rcx.legos)
|
Message is in Reply To:
| | Re: light sensor problem?
|
| (...) Having fixed the other screwup, I can report that snipping the code I discussed earlier allows everything to build just fine. It doesn't, however, solve the issue with the light sensors. I also tried swapping the two lines I mentioned earlier: (...) (24 years ago, 23-Jul-00, to lugnet.robotics.rcx.legos)
|
26 Messages in This Thread:
- Entire Thread on One Page:
- Nested:
All | Brief | Compact | Dots
Linear:
All | Brief | Compact
This Message and its Replies on One Page:
- Nested:
All | Brief | Compact | Dots
Linear:
All | Brief | Compact
|
|
|
|