PICAXE Synthesiser project

Having just finished an eight week university project using the PICAXE (they're just so easy to use it feels like cheating), I am trying to use my aquired knowledge to create something closer to my heart - a b*tchin' synthesiser.

The idea is to use the PWMOUT command to create musical scales, with the data for the PWM stored in EEPROM (Or a table depending on which turns out to simplify the code).

Here is what I am working with so far: A 10k pot on pin 4 using readadc10 to give me plenty of resolution for changing notes. This is then split by an if statement to match it to a note, which is read from EEPROM into two variables - period and duty.

Code:
eeprom 0,(238, 222, 224,195, 212, 170, 199, 146, 188, 124, 178, 102, 168, 83, 158, 64, 149, 45, 141, 29, 133, 13)

symbol	pot1=4
symbol	freq1=w0
symbol	period=b2
symbol	duty=w2

main:
	readadc10 pot1,freq1
	if freq1<93 then
		read 0,period
		read 1,duty
	elseif freq1<186 then
		read 2,period
		read 3,duty
	elseif freq1<279 then
		read 4,period
		read 5,duty
	elseif freq1<372 then
		read 6,period
		read 7,duty
	elseif freq1<465 then
		read 8,period
		read 9,duty
	elseif freq1<558 then
		read 10,period
		read 11,duty
	elseif freq1<651 then
		read 12,period
		read 13,duty
	elseif freq1<743 then
		read 14,period
		read 15,duty
	elseif freq1<836 then
		read 16,period
		read 17,duty
	elseif freq1<929 then
		read 18,period
		read 19,duty
	elseif freq1>929 then
		read 20,period
		read 21,duty
	endif
	
	duty=duty+255
	pwmout pwmdiv16, 2, period, duty
	goto main
	end
This looks real messy to me, especially as I am only using 11 pitches at the moment, I'd rather use a different technique for when I'm using 4 octaves. Would it work if I split the program into parallel tasks - one constantly checking to see if the ADC has increased, using a difference instead of thresholds. eg

Code:
readadc 4, b0
pauseus (whatever the smallest increment I can use is)
readadc 4, b1

if b0>b1 then
b2=b0-b1
elseif b1>b0
b2=b1-b0
endif

if b2>threshold then
goto increase pitch
This obviously won't work for negative values, which I don't quite comprehend how to work in PICAXE, unless some has divised a way to use twos complement.

Second problem: When the pitch values change too much, the PWMDIV changes, which is hard to change. Can I store the PWMDIV in a variable? This is being extremely hopeful, mayb ASCII in a word var?

Of course, if someone could help me with getting a negative pitch solution for the second code snippet, another threshold could be used for switching between subroutines that use different PWMDIV.

Apologies for the mess, this idea is still forming in my head.

PS. What is pretty cool about the current coding is that due to the ADC fluctuating due to circuit noise, you can set the note in between notes where it creates a sort of random grimey mess.

EDIT: I tried this, and it works with a few adjustments:

Code:
	readadc pot1,adc1
	pauseus 5000
	readadc pot1,adc2
	
	if adc1>adc2 then
		rd=rd-2 min 0 max 22
	elseif adc1<adc2 then
		rd=rd+2 max 22
	endif
The only problem with this is it makes terrible use of the pot, it reaches the frequency limits before the pot is near the edges, and does the same back which just makes it frustrating. To get this to work i would need something more like a rotary encode moving the pointer in the EEPROM.

Any suggestions to replace the large IF statement?
 
Last edited:

JimPerry

Senior Member
The only problem with this is it makes terrible use of the pot, it reaches the frequency limits before the pot is near the edges, and does the same back which just makes it frustrating. To get this to work i would need something more like a rotary encode moving the pointer in the EEPROM.
Partial fix - put a resistor each side of Pot to limit its range to what you want (could even use a preset each side to tweak it) :rolleyes:
 

hippy

Ex-Staff (retired)
Period and duty can be stored in variables, and duty can always be calculated from period to give 50% duty. PWMDIV cannot be stored in a variable, but it's easy enough to use a SELECT-CASE to select the right one ...

pwmdiv = 4
period = 100

duty = period * 2
Select Case pwmdiv
Case 1 : PwmOut 2, period, duty
Case 4 : PwmOut PWMDIV4, 2, period, duty
Case 16 : PwmOut PWMDIV16, 2, period, duty
Case 64 : PwmOut PWMDIV64, 2, period, duty
End Select

You could determine period, duty and pwmdiv from a single frequency but not sure how complicated the code might be.
 

Jamster

Senior Member
The trouble with a PICAXE in a synthisiser is that it would only be monophonic (1 note at a time) without some clever software, also it can only generate square waves from the pwm outputs so would be a single-oscillator-monophonic-squarewave-generator rather than a synthisiser...
Yes, in theory, you could use analogue circuitry to change waves/add cutoff frequencies/adsr filters/etc or possibly the DAC output on the PICAXE and a lot of knowledge of waves but these make it a much larger project.

On the other hand, if you dont mind a pretty basic synth then yes this is easily possibly. :)

I'm not quite sure how you mean when you say "negative pitch" because that is not possible considering that pitch is measures in Hz -number of waves passing a fixedpoint each second... I may have misinterpreted though...

Jamster

Added: You could use a PICAXE for each note, that would allow you polyphonic tunes...
 

Jamster

Senior Member
I wonder if you could create a decent polyphonic synth with one of the many PWM chips you can get these days, expecially the chainable ones... you would need some circuitry to get different volumes but could quite easily use the PWM chip and RC filter and prehaps optocouplers to change the volume...
 

AndyGadget

Senior Member
With a 14m2 and a simple resistor mixer you can have three tones playing at once. It would be pretty tricky to get polyphonicity(?) from this, but you can do a lot of fun things by playing around with the relative frequencies, for instance, playing the same note at three octaves gives a pretty good 'church organ' sound, and twiddling with the duty cycle you can modify the attack / decay and produce some reasonable phasing effects. Frequencies slightly off give beat / vibrato effects. Changing the PicAxe clock frequency gives you a range of octaves from POP-POP-POP up to hypersonics. All square(ish) wave of course and nothing approaching a 'real' synth, but fun none the less.
Mine's still very much a work in progress and currently on hold, but hopefully back on the front burner soon.
 
The trouble with a PICAXE in a synthisiser is that it would only be monophonic (1 note at a time) without some clever software
Polyphony is not the aim of this synthesiser, otherwise I would probably be using a microcontroller as just the control which would link to some VCOs. This synth is going to be a an FM glitch synth, but i'm still trying to decide whether to add a midi input for a keyboard, or just a serious of switches.

08M2 #1 - Square Wave Oscillator, Carrier
08M2 #2 - Square Wave Oscillator, Modulator

Combine these two using a VCA with a home rolled opto-isolator (it just tastes better if you roll your own).

08M2 #3 - Buffered DAC output, Envelop generator

Another VCA stage to add the envelope.

Period and duty can be stored in variables, and duty can always be calculated from period to give 50% duty. PWMDIV cannot be stored in a variable, but it's easy enough to use a SELECT-CASE to select the right one ...

pwmdiv = 4
period = 100

duty = period * 2
Select Case pwmdiv
Case 1 : PwmOut 2, period, duty
Case 4 : PwmOut PWMDIV4, 2, period, duty
Case 16 : PwmOut PWMDIV16, 2, period, duty
Case 64 : PwmOut PWMDIV64, 2, period, duty
End Select

You could determine period, duty and pwmdiv from a single frequency but not sure how complicated the code might be.
I don't know how slow the math would be for updating the frequency from a pot, might be worth looking in to for when I'm idiot proofing it.

Turns out I have never heard of the select case function before, but it looks kind of handy for this situation, cheers hippy.

So new plan for the code:

4 octaves of pitches(with another root on top), using 2 bytes to express each pitch (period, duty). 98 values in the table, 1024 possible ADC results, 1024/98=10.45 so every 10.5 step increases the pitch will go up a semitone.
This will be for the modulation frequency, I am planning on making the main oscillator scale related, perhaps pentatonic for some nice easy sounding music (this is if I don't add midi).

Code:
	symbol	period=b2
	symbol	duty = w2
	symbol	thresh1=b3
	symbol	pwmdiv=b6
	symbol	thresh2=b7

	readadc10, w0		; read the adc
	w0=w0*10/209*2		; scale it to point to the tables
	
	read b0, period		; the period and duty values will be
	inc b0			; stored next to each other
	read b0, duty
	dec b0
	
	if b0>thresh1 then
		duty=duty+255	; compensate for the values where the duty is over 255
	endif
	
	if b0<thresh2 then	; since there is only one change so far, a threshold will
		pwmdiv=1		; suffice when selecting the pwmdiv
	elseif b0>thresh2 then
		pwmdiv=2
		
	Select Case pwmdiv
	Case 1 : PwmOut PWMDIV16, 2, period, duty
	Case 2 : PwmOut PWMDIV64, 2, period, duty
	End Select
	
	goto main
The other alternative is to add another byte in the EEPROM for the Select Case. Keeping a balance between EEPROM memory and program length will be another obstacle later.
 
Top