Jump to content

Distance sensor (like "D-Beam" controler)


goule
 Share

Recommended Posts

Hi all,

In my midibox project I use that distance sensor SHARP GP2D120; its datasheet is available here :

http://document.sharpsma.com/files/GP2D120_SS_final.pdf

If I connect directly the sensor on the J5, instead of reading 0 when in IDLE (nothing in front of my sensor) I read a flow of 0 and 1 that alternates very fast, as if it hesitates between the two values. Now if I put something (that does not move) in front of the sensor, I read for instance 34 35 34 35 34 35 34 35 etc. The digit 3 is displayed constantly while the LCD oscillates between 4 and 5.  >:(

I know that the PIC waits for a voltage range of 0 - 5 while that sensor gives 0.3 - 3. I suppose that's the reason of flickering values ...

Any idea to use that sensor correctly ?  ???

Thanx guys & gals,

Olivier

Link to comment
Share on other sites

  • Replies 65
  • Created
  • Last Reply

Top Posters In This Topic

hey;

one post is enough man  ;) most of us read through the whole forum anyway! (well, i do)

have you put a 10uF cap between Vcc and Ground like the datasheet suggest; maybe the power rail noise you might have without the cap causes the jitter.

cheers, marcel

Link to comment
Share on other sites

About posts :  :-[  you're right, I'll try to avoid next time (but as you saw I only posted in the 3 related topics  ;))

About capacitor : waouw I hadn't read carefully the datasheet  :-\ so perhaps that you are my saver (comes from a french expression, I don't know if that translation gives any sense, anyway)

I'll make the test this evening, thank you for your reply !!!  8)

Link to comment
Share on other sites

  • 2 weeks later...
  • 2 weeks later...
  • 3 months later...

Okay I've found a way to integrate this component into the MBHP. I had to write some sort of "MIDI gate" on my application (works like an audio gate but for midi values) , so that when an encoder isnt touched for a certain period, my program considers it as silent if it only flickers for instance between -5/+5 (midi CC values).

So now I can integrate my 2 distance sensors + my 3 joysticks + my Wahwah Crybaby pedal  8), I still have to test for the ribbon controllers.

Seems like my project never sees the end, but its a lot of fun anyway ;-)

I'll send a post with the source code (in C) for my MIDI gate when I'll be at home (now at office) but it's rather simple  ;)

Goule

Link to comment
Share on other sites

In my main.h :

#define              GATE_TIMEOUT  2000

unsigned int    GATE_THRESHOLD[8];

unsigned int    GATE_COUNTER[8]={0,0,0,0,0,0,0,0};

unsigned char GATE_MODE[8]={1,1,1,1,1,1,1,1};

unsigned char LAST_CC_VALUE[8];

In my main.c :

void Init(void) __wparam

{

        // Each analog input device can have its own threshold :

        GATE_THRESHOLD[0]=3; // Pitch Bend

        GATE_THRESHOLD[1]=3; // Modulation

        GATE_THRESHOLD[2]=4; // Joystick A / X

        GATE_THRESHOLD[3]=4; // Joystick A / Y

        GATE_THRESHOLD[4]=4; // Joystick B / X

        GATE_THRESHOLD[5]=4; // Joystick B / Y

        GATE_THRESHOLD[6]=5; // Whah

        GATE_THRESHOLD[7]=3; // D-Beam

}

void Timer(void) __wparam

{

        unsigned char i;

        for(i=0;i<8;i++)

        {

                if (GATE_COUNTER > GATE_TIMEOUT)    GATE_MODE=ON;

                else GATE_COUNTER++;

        }

}

void AIN_NotifyChange(unsigned char pin, unsigned int pin_value) __wparam

{

(...)

if (valeur7bits>LAST_CC_VALUE[pin])

        diff=valeur7bits-LAST_CC_VALUE[pin];

else

        diff=LAST_CC_VALUE[pin]-valeur7bits;

if (GATE_MODE[pin]!=ON || diff>GATE_THRESHOLD[pin])

{

        // Here you know you can take this controller into account (it is not filtered)

        LAST_CC_VALUE[pin]=valeur7bits;

      // Do what you have to (send midi controller values for instance)

      (...)

        // Resets the gate's Timeout

      GATE_COUNTER[pin]=0;

      GATE_MODE[pin]=OFF;

}

}

Hope it could help someone with that flickering problems ... at least it solved mine  8)

Have fun (as always with this wonderful project thanks to father Thorsten  ;D)

Goule

Link to comment
Share on other sites

thanks for that :)

I've always a bunch of exotic sensors on my midi-boxes and while experimenting with MIOS I was very disappointed at the beginning, because there were very unstable signals. Then I used to reduce the deadband (knowing this wasn't the best solution), but this gate is working quite beautiful... and came at the right time, before I started to write my own...

;D

btw: I've also distance sensors from SHARP, each one ~25 EUR, but I found the two longer-ranged ones more interesting ;)

GP2D120 has a range of > 25 cm (datasheet says > 30 cm)

GP2D12/GP2D15 has a range of > 60 cm (datasheet says > 80 cm)

GP2Y0A02YK has a range of nearly 100 cm (datasheet says > 150 cm)

Link to comment
Share on other sites

You're welcome, I'm glad that this trick could help someone  8)

BTW, this confirms what I was thinking about unstability about sensors ... I was quite dissapointed and was wondering if I had perhaps some bad soldering or something. I never could have all the "toys" soldered and working (well, until I wrote that MIDI filter).

I find it's great to set different values in the GATE_THRESHOLD[ ] array, to keep the filter quite sensitive (or "reactive" I don't know - please forget my english as I'm french   :-\) as the jitter range is different from one type of sensor to another.

Which of the sensors do you find best ? Isnt the last one a little to long for usability ?

I'll send pictures of the baby soon, I'm still looking for its name  ;D

Seeya,

Goule

Link to comment
Share on other sites

I like the 80 cm best, it has enough "space inbetween" to fine-control something...

Since I stumbled upon MidiBox, I used Miditron (http://www.eroktronix.com/) it is quite affordable for its capabilities. The distance sensors work very well with miditron... but I think the strength of MidiBox (the ability to control every bit in the machine) is also its curse... but maybe there's an electronician-pro reading around here and gives us some hints to improve sensor-readings without coding?

Nevertheless, your gate is improving things very well... I'm just struggeling a bit with the timer-settings; sometimes my MidiBox is restarting, if I set the timer-init value above 9ms ( MIOS_TIMER_Init(90000 & 0xFF, 90000 >> 8); // 9 ms ) ... ist that right? humm...

Regards,

Michael

Link to comment
Share on other sites

So I think I'll have to find a 80 cm instead of my poor 25  :P

My values :

             MIOS_TIMER_Init(4,10000);

;) hope it'll work for you

Now a bonus :

Some photos

The LCD + my 2 analog joysticks  ;D :

LCDJOY_resize.JPG

The button part coming from my old non working DX7  ::) :

DX7_resize.JPG

The Performance mode (considered as its "normal working" mode) :

LCD_resize.JPG

The 2 detended rotary encoders (one with switch), equiped with big knobs  8) :

ROTARY_resize.JPG

For those who never seen a GP2D120 here is how it looks :

GP2D120_resize.JPG

A view of my Core module :

CORE_resize.JPG

And, finally, a view of the whole bunch. You can see my midified CryBaby whah in the foreground  ;D 8) :P

It takes 2 cables to bring ground & +5volts to the whah, plus one cable back to the AIN to read the value, so I used a simple stereo 6.35 jack to plug them up !  :o ;D A must have when using for instance Guitar Rig 2  8) ;)

ALL_resize.JPG

Seeya,

Goule

Link to comment
Share on other sites

hey, this is looking very cool  8)

I have mine in a marauded IKEA®-clock with a bending "gooseneck" (is that the right word?) – nevertheless I'll post some pics later, too!

Right now I am trying to improve your script with a min/max value; I think esp. the min-value is quite important to filter out too low signals coming from nowhere, but the problem is, that I don't know why the comparison between the sevenBitValue ( "MIOS_AIN_Pin7bitGet(pin)" ) won't compare to an unsigned char (eg 20) ??

It is getting even more complicated, because it worked already, then I changed something and now it stopped working ???

Does anyone know what I am doing wrong here?

unsigned char	sevenBitValue;
unsigned char	gateMin[8] = {20,20,0,0,0,0,0,0};


void AIN_NotifyChange(unsigned char pin, unsigned int pin_value) __wparam {
	// ... some other code here...

	// get 7-bit value
	sevenBitValue = MIOS_AIN_Pin7bitGet(pin);

	// this one is not recognized ??
	if(sevenBitValue <= gateMin[pin]) { return; }
       // these ones don't work either:
	// if(sevenBitValue < 20) { sevenBitValue = 0; }
	// if(sevenBitValue < 0x14) { sevenBitValue = 0x0; }
}

I'm really stuck  ???

What is wrong with these values?

Any hint is appreciated!

btw:

I also added a pedal switch, so that the distance sensor can only send signals if the pedal is pressed – and it sends an ALL_NOTES_OFF signal when released (good for playing sounds  8)

I can post the code if anone is interested...

Link to comment
Share on other sites

Hello AudioCommander,

I don't understand what's the aim of having a min value : the idea in my filter is already filtering the values until they reach a threshold, so it's already a min, no ? I don't really understand what your program does  :-\ So it's quite hard to help you at the moment ...

By the way, your idea of triggering the activation of the D-Beam via pedal switch is really great ! I think I'll do that in my own project (with a cannibalized pedal coming from a Behringer Vamp2)  ;D

I'm waiting for the pictures of your babe  8)

Goule

Link to comment
Share on other sites

Hi goule, thanks for your answer :)

I use the sensors for triggering NOTE_ONs. For Example when playing "Pad-Sounds", I use a technique of picking or gently weeping, for "Lead-Sounds" I simply hold my hand above the beam.

The distance sensors have the ugly behavior of sending some random data in the low areas (mostly 0, 1 and 2; but every 50th message is a random 15 or sth like that)...

While this behavior is not disturbing for Lead-Sounds it is very bad for "picked" Pad-Sounds, because they won't stay (which is exactly what I want to achieve: 1 weep = 1 note or a chord that stays as long as I weep again).

Therefore I want to filter out all signals between 0 and (say) 20.

Now this is what the gate does (to my understanding)

  • at the beginning, the gateMode is ON (1)
  • a signal will be processed –> the gate is set to OFF (0) and the counter is set to Zero (0)
  • now @ the timer => if the GateCounter (is currently 0) is higher than the timeout (2000) the gate will be enabled again. this is NOT the case. That means, the gateMode remains OFF (0) =>
  • so ( @ AIN again ) GATE_MODE[pin] != ON and that means the next signals will be processed until the timeout occurs and the gate is enabled again, whether or not the signal is below the threshold.

humm... I'm going to think about it...  :-\

But meanwhile here is my code for the pedal:

in main.h

#define	BUTTON_AIN_PEDAL 5
unsigned char	ainUsePedal[8] = {0,1,0,0,0,0,0,0};
and in main.h
void DIN_NotifyToggle(unsigned char pin, unsigned char pin_value) __wparam {
	switch(pin) {
		case BUTTON_AIN_PEDAL:
			if(pin_value == 1) { 	// button has been released
				for(i=0; i<8; i++) {
					if(ainUsePedal[i]) { 
						// send panic
						MIOS_MIDI_BeginStream();
						MIOS_MIDI_TxBufferPut(0xB0 + i);
						MIOS_MIDI_TxBufferPut(0x7B);     // CC 123: ALL NOTES OFF
						MIOS_MIDI_TxBufferPut(0x00);
						MIOS_MIDI_EndStream();
					}
				}
			}
			break;
		default:
			// nothing special...
			break;
	}
}

void AIN_NotifyChange(unsigned char pin, unsigned int pin_value) __wparam {
	// if usePedal check pedal state
	if(ainUsePedal[pin]) {
		if(MIOS_DIN_PinGet(BUTTON_AIN_PEDAL)) {
			// pedal is +5V => is NOT pressed
			return;
		}
	}
}

so, the AIN signal will never be processed if the BUTTON_AIN_PEDAL is not pressed (@ pin 5 in my example).

Whenever the pedal will be released, an ALL_NOTES_OFF (PANIC) message on the appropriate channel is sent additionally 8)

still... pics are coming later... maybe also some codesnippets for expanding and smoothing signals... (if I'll ever find out why my program is behaving so strangely...)    ;)

Link to comment
Share on other sites

..so as promised, here are some pics of my sensors; these are from the previous prototype; I think, I'll remove the clips and mount them on a case once the MB is ready to be "packed"...

dist_sensor_duo.jpg&h=500

dist_sensor_nah.jpg&w=500

dist_sensor_2.jpg&w=500

as previously mentioned, I ripped some very cheap battery-powered clocks from IKEA® apart; the only thing remaining inside were the two SMD-LEDs; the buttons are currently unconnected, but it may be interesting connecting one of these buttons to the DIN and using them as an ON/OFF switch...

;)

Link to comment
Share on other sites

...and here is my code for a "gate" (threshold and peak, values are filtered simply by being triggered very slowly) and an expander (expands values based on the 10-bit value); also an inverter to invert signals (127 - 0 => 0 - 127);

the offset/peak values can be calculated/measured as followed:

10bit resolution: 0..1023

sensor range (measured): 0.4V - 3.1V => as 10bit value: 81..635

expOffset would be 81

to get the factor: 635 - 81 = 554 / 127 = 4,4 => rounded: 5

expFactor is 5

if we have a max value of 635, the expander does this calc:

635 / 5 = 127

tadaaa... 8)

in the header:

#define	BUTTON_AIN_PEDAL 5

unsigned char	sevenBitValue;
unsigned int	tenBitValue;

unsigned char	i;
unsigned int 	k;

unsigned char	inverter[8];
signed char		invertedValue;

unsigned char	gateEnabled[8];
unsigned char	gateThreshold[8];
unsigned char	gatePeak[8];
unsigned int	gateCounter[8];
unsigned int	gateTimeout;

unsigned char	expEnabled[8];
unsigned char	expOffset[8];
unsigned char	expFactor[8];
and this into main.c

void Init(void) __wparam {	

	/* -------- main Config --------- */ 

	for(i=0; i<numAin; i++) {
		inverter[i] = 0;

		gateEnabled[i] = 0;
		gateThreshold[i] = 0;
		gatePeak[i] = 127;
		gateCounter[i] = 0;

		expEnabled[i] = 0;
		expOffset[i] = 100;
		expFactor[i] = 5;
	}

	// GATE ----------------------------------------------------------------
	gateEnabled[0] = 1;		// Distance Sensor
	gateThreshold[0] = 20;
	gatePeak[0] = 120;

	gateEnabled[1] = 1;		// Distance Sensor
	gateThreshold[1] = 20;
	gatePeak[1] = 120;

	gateEnabled[2] = 1;		// Pressure Sensor
	gateThreshold[2] = 0;
	gatePeak[2] = 120;

	gateTimeout	= 40;

	// EXPANDER ------------------------------------------------------------
	expEnabled[0] = 1;		// Distance Sensor
	expOffset[0] = 81;				// offset = minimum value (10-bit)
	expFactor[0] = 5; 				// factor = (max(635) - offset) / 127

	expEnabled[1] = 1;		// Distance Sensor
	expOffset[1] = 81;
	expFactor[1] = 5; 				// 635 - 81 = 554 / 127

	expEnabled[2] = 1;		// Pressure Sensor 
	expOffset[2] = 255;
	expFactor[2] = 6; 				// 1024 - 270 = 754 / 127

	// INVERTER ------------------------------------------------------------
	inverter[2] = 1;
}


void Timer(void) __wparam {
	for(i=0; i<numAin; i++) {
		if(gateEnabled[i]) {      // see posting below; this has been edited and corrected!
			if(gateCounter[i] >= 127) {
				gateCounter[i] = 0;
			} else {
				gateCounter[i]++;
			}
           }
	}
}


void AIN_NotifyChange(unsigned char pin, unsigned int pin_value) __wparam {

	if(gateEnabled[pin]) { 							// *** process GATE ***
		if(gateCounter[pin] >= gateTimeout) {			// if it's time
			gateCounter[pin] = 0;
			// get + check 7bit value
			sevenBitValue = MIOS_AIN_Pin7bitGet(pin);
			if(sevenBitValue <= gateThreshold[pin]) { return; }
			if(sevenBitValue >= gatePeak[pin]) { return; }
			if(sevenBitValue == lastAinValue[pin]) { return; }
		} else {
			return;										// not the time yet
		}

	} else {										// no gate
		// get 7-bit value
		sevenBitValue = MIOS_AIN_Pin7bitGet(pin);
	}

	if(expEnabled[pin]) {							// *** process EXPANDER ***

		tenBitValue = MIOS_AIN_PinGet(pin);
		if(tenBitValue <= expOffset[pin]) {
			sevenBitValue = 0;
		} else {
			tenBitValue = tenBitValue - expOffset[pin];
			k = ADK_DIV(tenBitValue, expFactor[pin]);
			sevenBitValue = k;
			if(sevenBitValue > 127) { sevenBitValue = 127; }
		}
	}

	if(inverter[pin]) {								// *** process INVERTER ***
		invertedValue = sevenBitValue - sevenBitValue - sevenBitValue;
		sevenBitValue = invertedValue + 127;
	}

	// last check to avoid sending duplicates:
	if(sevenBitValue == lastAinValue[pin]) { return; }

	// send MIDI data
	MIOS_MIDI_BeginStream();
	MIOS_MIDI_TxBufferPut(0xB0 + pin);		// CH 1 + pin
	MIOS_MIDI_TxBufferPut(0x14);			// CC 20
	MIOS_MIDI_TxBufferPut(sevenBitValue);	// value
	MIOS_MIDI_EndStream();

	// store input
	lastAinPin = pin;
	lastAinValue[lastAinPin] = sevenBitValue;
}


please note that this code is not yet optimized!

the division ADK_DIV() comes from goule: http://www.midibox.org/forum/index.php?topic=5944.0

I also shortened to the essential, so don't wonder if there's someting missing...

best regards,

Michael

Link to comment
Share on other sites

Audiocommander,

Your photos really look nice. It's a great idea to have put the GPD into a device which has a flexible arm !  :o :D

+ thank you for the source code. Could you tell me how hard it is to mix assembler and C code (cause I read once that you did that, don't remember if it is in that thread) ???

Bye,

Goule

Link to comment
Share on other sites

Hi Goule,

Could you tell me how hard it is to mix assembler and C code

TK showed me (in the arithmetic thread ;) );

it's really simple, just put __asm and __endasm; around the assembler code:

unsigned char Scale_8bit(unsigned char value, unsigned char min, unsigned char max)
{
  // scaled value is (<8-bit random> * <range>) >> 8
  PRODL = value;     // 8bit value
  PRODH = max-min+1; // range
__asm
    movf _PRODL, W
    mulwf _PRODH, 0
__endasm;

  return min + PRODH;
}

The expander/gate combo now works really great for me; but to make it work good one has to measure the values with a multimeter and calculate a bit... otherwise one might get lost in trial & error nirwana  ::)

This share of infos is really refreshing, btw :)

Bye,

Michael

ps: I configured the expValues as const unsigned char[] = {...}, this might improve things, 'cause once the hard-wired sensors are calibrated, there's no need to change values by knobs (jeez, you surely know all this)...

Link to comment
Share on other sites

Very interresting indeed, I'll see with your code if I can improve mine  ;D

By the way, I think you should perhaps check into the Timer() function to stop incrementing after GateTimeout is reach, otherwise leaving your machine in IDLE could lead to an overflow (or am I missing something ?).

About your Scale_8bit function : could you explain me what it does ?  :-[ I'm not very familliar with assembler code ...

Was it impossible to do that in pure C code ?

Very best regards,

Olivier aka Goule

Link to comment
Share on other sites

About your Scale_8bit function

well, actually, this is not mine, but Thorsten showed me how to multiplicate two 8-bit values:

http://www.midibox.org/forum/index.php?topic=5944.msg36574#msg36574

Thank you for the hint with the timer, you're right; this caused definitely an overflow  :-[

Cheers,

Michael

Link to comment
Share on other sites

wow, those pics look cool. Great idea with the clocks - IKEA is sometimes too cheap to NOT buy anything... Quick q. about this one: Did you thread your own wiring through the goosenecks? If so, was it difficult? I may do the same thing for some gooseneck lights I've got planned - these look really sturdy.

Link to comment
Share on other sites

Did you thread your own wiring through the goosenecks? If so, was it difficult?

Yes, but this wasn't really a problem.

It has been more complex to drill a hole in the clip and mount a socket in there and to leave enough space that it doesn't get teared off once the clip will be opened... but anyway, I think these wobbly parts are the first ones I'll substitute...

...ah and the front glass has also been problematic, but one can fix everything with a "klebepistole" (soldering with melted plastic sticks, don't know the word??)

But these goosenecks with clock have been much cheaper (~4 EUR if I remember right) than single goosenecks  ;)  (although I'm not sure, they're selling it anymore, this has been over a year ago...)

Regards,

Michael

Link to comment
Share on other sites

It's called a glue gun, but I understood klebepistole as well ;)

I'm just so inspired by the whole recycling thing - I'm doing a suitcase controller with input jacks as well, I'm doing the classic circuitbending theremin thing - Using LEDs and a good quality photoresistor, and I'll be running tests on a "virtual shaker", made with 4 mercury tilt-switches to trigger midi notes from inside a tennis ball or something.

Alright: I'm heading back to the parts list spreadsheet ;)

Link to comment
Share on other sites

  • 2 months later...

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share


×
×
  • Create New...