What you need? Need an AVR programmer, a AT90S4433 microcontroller, and AVR Studio, some but not a lot of experience programming, and some but not a lot of experience with electronics.
What is it?
PWM is probably the simplest way to transmit a numerical value, be it via infrared, over a single wire, optical fiber, laser, radio, etc. you name it, it is easy. How it works is; as the name suggests; the pulse width is what holds the information, the frequency is trivial.
How does it work?
Say you need to send a number over from one device to another, if the number in question is 1, then it is trivial, you send some kind of a pulse. Now what if the number can vary between 1 and 10, you could go analog and send a voltage say between 1V and 10V, sure enough 8V would represent the number 8. Now what if the amplitude of the signal is prone to oscillations like say due to wire resistance or due to attenuation through the median it travels? Analog is not such a good idea anymore, so you do what the rest of the world has done and you turn to digital, which brings you to the next question. How do you transfer a binary number? You could do it in parallel, but if you are looking to send a vast range of numbers such as say numbers between 0 and 1000, you need 16 wires to send numbers over this range, so you could do it serially, but that involves protocols and a whole lot of homework. Luckily PWM is another way to transfer this number.
First both the transmitting and the receiving device has to know what range the numbers will be between, or bow many bits the binary number will be. So an 8-bit binary number can send any number between 0 and 255, and a 10-bit binary number can cover 0 to 1023.
Would it not be nice if you could send a pulse that by itself can represent a number in that range? Yes and you can, you set the width of the pulse to be X number of units long. A 1sec long pulse can represent 1000 and then a .013sec long pulse would represent 13, simple. With pulse width modulation it is exactly what you do. You use some kind of a base frequency to send pulses, then you measure the width of the pulse and knowing that a constant high is 100% x 2^n - 1 and a constant low is 0.
How do I do it?
Use an Atmel AT90S4433 and it has a built in PWM that can produce the proper pulse width and continue to send it at fCLK/2^(8,9,10) Hz.
The biggest trick is you have to initialize some registers and such, and that is what this example is here for, to show you how to do that.
;****************************************************
; This program will output a set width pulse on the
; PWM pin. (Pin 15 PB1/OC1)
;****************************************************
.include "4433def.inc"
.def temp = r16
.def temp2 = r17
.equ PRESET = $0001 ; What value do you want to send??
; Use only 10bit max, be careful!
.cseg
.org $000
rjmp reset ;reset handle
;****************************************************
;* MAIN PROGRAM
;****************************************************
reset:
SP_INIT: ;STACK POINTER
ldi temp, ramend ; Not needed for this code but here's
out sp, temp ; how you do it nayway.
PORT_INIT: ;SET PORTS AS INPUT OR OUTPUT
ldi temp,$02
out ddrb,temp ;Set Port B Pin 1 as output only for PWM.
PWM_INIT: ;INITIALIZE THE PULSE WOIDTH GENERATOR
ldi temp,0b10000011 ;Init PWM (10-Bit) and non-inverted on OCR1
out TCCR1A,temp ;0b10000010 - 9bit 0b10000001 - 8bit
ldi temp,$02
out TCCR1B,temp ;Clock divide by 2=8, 3=64, 4=256, 5=1024
ldi temp, low(PRESET)
out OCR1L, temp ;Write lowbyte to PWM
ldi temp, high(PRESET)
out OCR1H, temp ;Write highbyte to PWM
sei ;enable interrupts
loop: rjmp loop ; LOOP HERE FOREVER.
And that is it, you can copy and paste, but you'll learn more if you type it out. Use an oscilloscope to verify the pulse width is what you expected, remember that there is a clock divider and also there is the 8,9,10-bit PWM settings, so understand those first then you can calculate the frequency the PWM will run at and once you have that you can calculate the pulse width exactly.