Propeller to Propeller comunication
Dear All,
Another week, another discussion of me not understanding how to make my Activity Boards to work as intended.
I want to make two Propellers, embedded in their respective Activity Boards, communicate to each other, i.e. exchange at a rate of 50-500 KHz, one long variable.
Specifically, I am using the modified code attached below (microphone_to_headphone_2_cogs.spin), that uses one cog to do A/D conversion, stores the result in a long in the hub and there it can be taken by another cog , D/A converted and output to the jack. I would like now two split the process between two Propellers: one does A/D, stores the audio signal as a long in the hub, the signal is then sent to another Propeller to D/A converted and output again.
I am trying to figure out how I can correctly address the serial communication between Propellers.
My first thought was to use the PropBus object (https://github.com/parallaxinc/propeller/tree/master/libraries/community/p1/All/PropBus, Single wire multi-propeller comm link), with a one wire configuration with 100k pull up resistances as the author of the object suggests (attached also the two objects I am loading to the two different Propeller Activity Boards to try to make it work, RT is the mic Propeller and BC the headphone one), but I can't make it work and do not get any results.
Has anyone any experience with communication between Propellers? Can someone suggest me the best serial communication to make it work and point me to some objects that can be used to make two Propellers communicate with each other, or shed some light on why I can't make the PropBus work and how to make use of it correctly?
I don't need much complication, just to send the long variable in full at the rate of 50-500kHz.
Domenico
Comments
Hi,
Can't you just split the long into 4 bytes and send them over serial? No bus, just one line plus gnd.
Edit perhaps 2 bytes are sufficient?!
Christof
I did give some thought about it, splitting my "long signal_hub" in another variable "byte serial[4]", something like:
serial[0]:=byte[@signal_hub][0]
...
serial[3]:=byte[@signal_hub][3]
but then which object/serial communication do you suggest to use to send them over to the other propeller? And once they are there how would I put them together? I looked in the manual but could not really find a method to paste for bytes in a long, I am a really new when it comes to spin.
Domenico
Since you're not doing full-duplex you could use unrolled (high-speed) serial drivers on either end.
Transmit your long
Receive on the other side:
Easy-peasy, lemon-squeezey
Hi> @domeniv97 said:
Hi, once again,
do you really need to transfer a long=32bits? - The reason I ask, is that the ADC of P1 has about 11bits signal to noise ratio. This means, that there is no advantage to transfer more than 12bits of audio data. If you send 16bits instead of 32, you can still use 4 bits for other information.
If the project is about transmission of speech, than about 7 bits will be enough to have it be clearly understandable. As the important frequencies for speech are less than 2kHz, a sample frequency of perhaps 6kHz will sufficient for speech. So for speech, one byte at a rate of 6000 Bytes/sec will be sufficient, without complicated encoding methods. You only have to make sure that the scale of 7 bits are really used by the modulation amplitude, which can be achieved by an hardware audio compressor or also in software.
So it might be possible to reduce the data rate from "1long per 50kHz...500kHz" = 200.000..2000.000Bytes/s to something like 6.000Bytes/s. Which will make the transmission and also the processing very much more easy. Often such considerations decide, whether a project is feasible or not. I have heavy doubts, that it is possible to process 4*50kBytes/sec using SPIN.
Some other thoughts: If you have to do audio processing, than speed is very important. This means that interpreted SPIN will often have to be combined with assembler, which means, that you have to learn 2 languages. So it might be well worth to have a look at the compiled languages for P1. The downside of the compiled languages are, that they need much more code space, which is rather restricted. (Myself I do like to use Tachyon (Taqoz) Forth for the Propellers as Forth is the best compromise between speed and code density and makes experimenting fun. I know, that Forth is often seen as weird, so perhaps you will not fall in love with it.... :-) )
About the access of bytes as part of longs in SPIN. The manual for P1 is really good:
https://www.parallax.com/package/propeller-manual/
Good luck, Christof
Yes Spin on the Propeller 1 is quite slow. It's better to do anything in PASM, especially with your project, you have enough free time in the ADC and DAC cogs to do also the communication in the same cog.
The simplest is Async Serial, this needs just one data transmit/receive pin, without a clock pin, and without a sample rate sync pin.
Async Serial just adds a start- and a stopbit to allow to detect the begin of a dataword, the databits are sent with a fixed bitrate which bith the transmitter and the receiver need to know.
Here are two PASM subroutines for sending and receiving data-words up to 30 bits (start and stopbits have also to fit in the same 32bit register).
It defaults to 13 bits data size. Baudrate is 4 Mbit/s, so transmitting one sample takes 3.75 us - good for sample rates up to 250 kHz.
In your ADC and DAC cog, you don't need to communicate with the Spin variables, this makes it simpler:
The ADC cog defines the sample rate depending on the chosen bit size. On every ADC loop there is plenty of time to also send the data with AsncTx subroutine:
The DAC cog needs to synchronize to the received data anyway for receiving, so this also gives also the sample rate:
For sure this is not a working code, only snippets, and all is untested...
Andy
Thanks, I fairly understand the snippets and the code that you sent, but can't assure myself on how it functions: like this it seems to me that I will have to synchronize the two chips so that when signalOut.byte[0] goes out, the other chip expects to receive it and thus is waiting with a SignalIn.byte[0] inside a repeat or something of that sort, and the same for signalOut.byte[1], SignalIn.byte[1] and so forth, am I understanding it wrong? Because otherwise I can encounter the risk of bytes being read more than once or missed.
Domenico
Thanks as always Andy, I will have a look at the PASM and try to modify the code according to your routines and suggestions! I hope like this it will work well.
I had some worries on touching the ADC and DAC routines because, I do not clearly understand how the bits saving in the counter worked, since it seemed that the ADC counter mode saves them in the last n bits of the counter while the DAC wants them in the first n bits.
Thanks, I will try to familiarize more with the bitrates and the byte addressing, I was using byte[@address][index], but it is clear that I am far from familiar with propeller programming. In my defense: I am a major in physics and recently switched in computer science so I have a mostly numerical-methods centric approach to programming and miss out a lot of important knowledge.
Domenico
Somewhere here in the forum is a fancy one pin communications code. But, in the end I just used serial, like fullduplex serial with both pins the same.
Key is to make one Prop master so that others only speak when spoken to…
Then, can share bus with many props.
Also, good to have resistive loading at at least one prop to reduce noise.
This way was able to talk between boxes with coax cable connection…