Message Boards Message Boards

Tutorial and package for the Redpitaya scope/generator board

Posted 9 years ago

Starting from this post I finally got something with this RedPitaya board using the redPitaya SCPI server and string commands through TCP/IP connection. This is a cross post of a post I put here on the Mathematica StackExchange. SCPI server works ways faster than the serial port access. Below is a tutorial I built while experimenting with the board and SCPI commands and existing examples. I hope it could be useful for others. For me it answers my original question. :) PS : Thanks also to Pavel on the Redpitaya Forum who helped a lot. Thanks to Vitaly who suggested to share again on this group.

Christian Néel


Communication via TCP/IP device

Launch the SCPI interface from Serial console :

Here we start communication with the board using a simple Serial console on USB COM port and PuTTY. (PuTTY utility allow simple serial communication as well as Raw TCP/IP or SSH within the same utility)

Console from COM port

Note: this could be done by editing the initialisation on Red Pitaya SD Card,or communicating with Serial link by Mathematica ...

After launching SCPI server:

initialization of TCP/IP with JLink

I got the source from from this link: "Mathematica TCP socket client toward Trading Platform" on Mathematica StackExchange

Needs["JLink`"];
InstallJava[];
(*ip addess and port where SCPI server is running*)
tcpaddress = "192.168.1.100";
tcpport = 5000;
(*create a Socket object*)
socket = JavaNew["java.net.Socket", tcpaddress, tcpport];
out = JavaNew["java.io.PrintWriter", socket@getOutputStream[], True];
in = JavaNew["java.io.BufferedReader", 
   JavaNew["java.io.InputStreamReader", socket@getInputStream[]]];

Using SCPI / API functions

example of simplest SCPI command communication. Everything is a string...

(*send the request*)
out@println["ACQ:DEC?"];
(*read the response*)in@readLine[]

After use, the socket is closed

socket@close[];

Note: this was done using MMA10.1, after 10.1 the TCPsocket funtion are native function in MMA.

Using package redpitaya.m

For convenience I wrote a package that contents a set of function that matches (approximately) the API name in the SCPI definition document. The function list includes as well the TCP initialisations For reference, see the SCPI command release link at :http:// http://redpitaya.com/examples-new//. Since I found that the above link may evolve the reference of SCPI function on: https://github.com/RedPitaya/RedPitaya// and more precisely on: https://github.com/RedPitaya/RedPitaya/blob/master/scpi-server/doc/SCPIAPI_commands.odt?raw=true

Now we load the specific package that wraps the SCPI functions with Mathematica (in this example it is located in this notebook directory)

SetDirectory[NotebookDirectory[]];
 <<redpitaya.m

Then, test package has been loaded by typing a command help (type ?rp*)

?rp*

and get a list of all available functions of the package). Clicking a fonction name displays the help at the bottom of the list

enter image description here

Or type directly the requested function help:

enter image description here

Initialize communication

rpSCPIinit[]

Test communication

rpAcqGetGain[1]

LV


Builds from Matlab examples on site

This set of examples follows (roughly) the specifications of Matlab example that are provided on the Red Pitaya Site Reference examples here : http://redpitaya.com/examples-new/

Digital

Blink

Test function which lights LED1 for 5 seconds then turn it off.

rpDpinSetLedState[1, 1];
Pause[5];
rpDpinSetLedState[1, 0];

The function is just a text wrapper for calling SCPI server as shown in the package help:

enter image description here

Bar graph with LEDs

Matlab example here : http://redpitaya.com/examples-new/bar-graph-with-leds/

Test function which displays the LED based on a discretized value p from 0 to 7:

Clear[barLED];
barLED[p_] := (rpDpinSetLedState @@ #) & /@Table[{i, Boole[Floor[Clip[p, {0, 7}]] == i]}, {i, 0, 7}];

Tests

barLED[5];
Pause[1];
barLED[-33];
Pause[1];
barLED[22];
Pause[1];
barLED[0];

Push button and turn on LED diode

Matlab example here : http://redpitaya.com/examples-new/push-button-and-turn-on-led-diode/

Code below is for test purpose only, a better implementation could be done using Mathematica scheduling capabilities;

rpDpinSetDioDirection[5, "INP", "N"]
s = 0; While[ s == 0,
 s = 1 - rpDpinGetDioState[5, "N"];
 rpDpinSetLedState[7, s]]

Test button

Interactive LED bar graph

Matlab example here : http://redpitaya.com/examples-new/interactive-led-bar-graph/

Bar graph with Slider control

Slider[Dynamic[LED], {0, 7, 1}]
Dynamic[(rpDpinSetLedState @@ #) & /@Transpose[{Range[0, 7],Boole[# <= LED] & /@ Range[0, 7]}];]
(* using (#\[GreaterEqual]LED)& or(#<=LED)functions gives a thermometer or ribbon display*)

enter image description here

Sorry no video here but the first tests of moving slider on the screen and seing the LED position moving on the board is quite rewarding :)

Analog

Read analog voltage on slow analog input

Matlab example here http://redpitaya.com/examples-new/read-analog-voltage-on-slow-analog-input/

Read 10 turns Potentiometer and put it on the LED bar display...for a while. Test with potard

Again this code is just for checking, a better implementation still to be done with Mathematica scheduling capabilities.

Do[barLED[7/3.3*rpApinGetAinValue[3]], {100}]

Set analog voltage on slow analog output

Matlab example here: http://redpitaya.com/examples-new/set-analog-voltage-on-slow-analog-output-4/

here we apply a variable voltage setpoint to AOUT2 and we measure the voltage with the corresponding ADC. Some additionnal info about the functions:

enter image description here

enter image description here

data = {};
Do[rpApinSetAoutValue[2, voltage];
 AppendTo[data, {voltage, rpApinGetAoutValue[2]}], {voltage, 0, 3.3, 
  0.01}]
ListPlot[data]

enter image description here

Then draw the transfert function error for evaluation of the DAC/ADC chain:

ListPlot[Transpose[{data[[;; , 1]], 
   data[[;; , 2]] - Clip[data[[;; , 1]], {0, 1.8}]}], Joined -> True]

Residual between DAC an ADC

Interactive voltage setting on slow analog output

Matlab example here : http://redpitaya.com/examples-new/interactive-voltage-setting-on-slow-analog-output-2/

Get slider input and put it on the slow DAC output and read it back with ADC on demand.

    data = {}; Manipulate[rpApinSetAoutValue[2, value]; 
 Grid[{{Button["Read & display", data = rpApinGetAoutValue[2]], 
    data}}, Frame -> All], {value, 0, 1.8, .01}]

Slider for writing DAC and display ADC

Generating signals at RF outputs (125 MS/s)

Generate continuous signal

Matlab example here : http://redpitaya.com/examples-new/generate-continuous-signal-on-fast-analog-outputs/

Use API-Like basic functions for driving generator (see definition in the redpitaya.m package).

rpGenWaveform[1, "SINE"]
rpGenFreq[1, 20000]
rpGenAmp[1, 0.9]
rpGenOutEnable[1]

enter image description here

Using the redpitaya WebScope application for visualizing the signals in the same time is also Ok. Image below show the result after the waveform has been changed with the following instructions:

rpGenOutDisable[1]
rpGenWaveform[1, "SQUARE"]
rpGenOutEnable[1]

enter image description here

Beware! when you close the Web browser windows, the communication with the Red Pitaya is closed and you need to restart the SCPI server (well...at least it worked for me).

Simultaneous generation on both channels:

rpGenOutDisable[#] & /@ {1, 2};
rpGenWaveform[#, "SINE"] & /@ {1, 2};
rpGenFreq[1, 20000, 0]
rpGenFreq[2, 40000, 75]
rpGenAmp[#, 0.5, 0.5] & /@ {1, 2};
rpGenOutEnable[#] & /@ {1, 2};

2 channels

Using PWM output

rpGenPWM[1, 10];
rpGenPWM[2, 10];
rpGenFreq[1, 20000, 0]
rpGenFreq[2, 20000, 180]

enter image description here

Generate signal pulses

Matlab example here : http://redpitaya.com/examples-new/generate-signal-pulses/

Configure using API-Like basic functions for driving generator (see definition in the redpitaya.m package).

rpGenReset[];
rpGenOutDisable[1];
rpGenWaveform[1, "SINE"];
rpGenFreq[1, 5000];
rpGenBurstConfig[1, 5, 3, 
  0.002];(*note that the period is expressed in seconds, it is \
expressed in \[Micro]s in the SCPI*)
rpGenBurstEnable[];
rpGenBurstTrigSource[1, "INT"];
rpGenBurstTrigger[1];(*prepare trigger but wait for outpt enable*)

Launch burst in a controlled manner

rpGenOutEnable[1];

enter image description here

Clean-up for return to normal operation

rpGenBurstConfig[1, "INF", "INF", 1]
rpGenBurstDisable[1];

Test for return to normal operation

rpGenWaveform[1, "TRIANGLE"]
rpGenFreq[1, 2000]
rpGenAmp[1, 0.9]
rpGenOutEnable[1]

Note: It is a bit awkward to organize the sequencing of all functions to get a good control of the burst, The matlab example shows a good sequencing of calls but some subtilities are hidden in the Red Pitaya SCPI. Probably need to build a more sophisticated function for easier use.

EDIT The most recent update of the redpitaya SCPI server (march 2016 in my understanding) seems to show a more straightforward burst mode (but I had no time to play with).

Generate signal on external trigger

Matlab example here :http://redpitaya.com/examples-new/generate-signal-on-fast-analog-outputs-with-external-triggering/

Configure using API-Like basic functions for driving generator (see definition in the redpitaya.m package).

rpGenReset[];
rpGenWaveform[1, "SINE"]
rpGenFreq[1, 20000]
rpGenAmp[1, 1]
rpGenBurstConfig[1, 4, 1, 
  0.001];(*note that the period is expressed in seconds, it is \
expressed in \[Micro]s in the SCPI*)
rpGenBurstEnable[];
rpGenBurstTrigSource[1, "GATED"]
rpGenOutEnable[1]
(*prepare trigger and wait for external input *)

enter image description here

Clean-up for return to normal operation

rpGenBurstConfig[1, "INF", "INF", 1]
rpGenBurstDisable[1];

Custom waveform signal generation

Matlab example here :http://redpitaya.com/examples-new/custom-signal-generating/

Generate two arbitrary waveforms:

{x, y} = Transpose[Table[{Sin[t] + Sin[3 t]/3, 1/2 Sin[t] + Sin[4 t]/4}, {t, 0, 2 Pi,2 Pi/16383}]] // N;
ListPlot[Transpose[{x, y}], PlotLabel -> "XY graph"]
ListPlot[{x, y}, PlotLabel -> "Waveforms"]

enter image description here enter image description here

Configure using API-Like basic functions for driving generator (see definition in the redpitaya.m package).

rpGenReset[];
rpGenArbitrary[1, x]
rpGenArbitrary[2, y]
rpGenFreq[#, 10000] & /@ Range[2];
rpGenAmp[#, 1] & /@ Range[2];
rpGenOutEnable /@ Range[2];

enter image description here

Acquiring signals at RF inputs (125 MS/s)

On trigger signal acquisition

Matlab example here :http://redpitaya.com/examples-new/single-buffer-acquire/ Configure using API-Like basic functions for driving generator (see definition in the redpitaya.m package).

setup Generators CH1 & CH2 (CH2 connected to Acq CH1 on my RP configuration and vice versa)

rpGenReset[]
rpGenWaveform[1, "TRIANGLE"]
rpGenWaveform[2, "SINE"]
rpGenFreq[1, 10000, 90]
rpGenFreq[2, 10000]
rpGenAmp[#, 1, 0] & /@ Range[2];
rpGenOutEnable[#] & /@ Range[2];

setup Acquisition CH1 & CH2

rpAcqReset[]
n = 64;(*decimation factor see RP documentation  here we sample at \
about 103kHz*)
rpAcqSetDecimation[64](*125/n MS/s and n=1,8,64,1024,8192,65535*)
timebase = Table[N[i n/((125 10^6))], {i, 0, 16383}];
(*timebase ticks for display later*)
rpAcqSetAveraging["OFF"]
rpAcqSetTriggerThreshold[500](*trigger level 500mV*)
rpAcqSetTriggerDelay[8192];(*triggers at the beginning of the buffer*)
rpAcqSetGain[1, "HV"];
rpAcqSetGain[2, "HV"];
rpAcqSetDataUnit["VOLTS"];
rpAcqSetDataFormat["FLOAT"];

enter image description here

Run Acquisition CH1 & CH2

rpAcqStart[]
rpAcqSetTriggerSource["CH1_PE"]
(*Trigger source setting must be after ACQ:START*)
While[rpAcqGetTriggerState[] != "TD"](*wait for trigger*)
rpAcqGetWritePointerAtTrig[](*print current trigger pointer*)
data1 = Transpose@{timebase,rpAcqGetFullDataNum[1]};(*get full buffer CH1*)
data2 = Transpose@{timebase,rpAcqGetFullDataNum[2]};(*get full buffer CH2*)
ListPlot[{data1, data2}, Joined -> True, PlotRange -> {{0, 500 10^-6}, All},ImageSize -> "Large", PlotTheme -> "Detailed"]
rpAcqStop[]

enter image description here Oops! seems that picture was taken when the CH1 was disconnected (Hardware issue..).Anyway, it is possible to play with the data:

ListPlot[{Log@Abs@Fourier[(Transpose@data1)[[2]]], Log@Abs@Fourier[(Transpose@data2)[[2]]]}, PlotRange -> {{0, All}, All}, Joined -> True, ImageSize -> "Large", PlotTheme -> "Detailed"]

enter image description here

Signal acquisition on external trigger

Matlab example here :http://redpitaya.com/examples-new/on-given-external-trigger-acquire-signal-on-fast-analog-input/

Configure using API-Like basic functions for driving generator (see definition in the redpitaya.m package).

setup Generators CH1 & CH2 (CH2 connected to Acq CH1 on my RP configuration and vice versa)

rpGenReset[]
rpGenWaveform[1, "TRIANGLE"]
rpGenWaveform[2, "SINE"]
rpGenFreq[1, 10000, 90]
rpGenFreq[2, 10000]
rpGenAmp[#, 1, 0] & /@ Range[2];
rpGenOutEnable[#] & /@ Range[2];

setup Acquisition CH1 & CH2

rpAcqReset[]
n = 64;(*decimation factor see RP documentation  here we sample at about 103kHz*)
rpAcqSetDecimation[64](* x 125/n MS/s and n=1,8,64,1024,8192,65535*)
timebase = Table[N[i n/((125 10^6))], {i, 0, 16383}];
(*timebase ticks for display later*)
rpAcqSetAveraging["OFF"]
rpAcqSetTriggerThreshold[500](*trigger level 500mV*)
rpAcqSetTriggerDelay[8192];(*triggers at the beginning of the buffer*)
rpAcqSetGain[1, "HV"];
rpAcqSetGain[2, "HV"];
rpAcqSetDataUnit["VOLTS"];
rpAcqSetDataFormat["FLOAT"];

Run Acquisition CH1 & CH2

rpAcqStart[]
rpAcqSetTriggerSource["EXT_PE"](*Trigger source setting must be after \
ACQ:START*)
While[rpAcqGetTriggerState[] != "TD"](*wait for trigger*)
rpAcqGetWritePointerAtTrig[](*print current trigger pointer*)
data1 = Transpose@{timebase, rpAcqGetFullDataNum[1]};(*get full buffer CH1*)
data2 = Transpose@{timebase, rpAcqGetFullDataNum[2]};(*get full buffer CH2*)
ListPlot[{data1, data2}, Joined -> True, PlotRange -> {{0, 500 10^-6}, All},ImageSize -> "Large", PlotTheme -> "Detailed"]
rpAcqStop[]

enter image description here

Synchronised one pulse signal generation and acquisition

Matlab example here :http://redpitaya.com/examples-new/synchronized-one-pulse-generating-and-acquiring/

Configure using API-Like basic functions for driving generator (see definition in the redpitaya.m package).

rpGenReset[]
rpAcqReset[]
(*waveform settings*)
rpGenWaveform[1, "SINE"];
rpGenFreq[1, 10000]
rpGenAmp[1, 0.5];
(* burst generation settings*)
rpGenBurstEnable[];
rpGenBurstConfig[1, 5, 2, 0.004]
rpGenOutEnable[1];
(*acuqisition settings*)
rpAcqSetDecimation[64];
rpAcqGetSamplingRateHz[]
rpAcqSetGain[1, "HV"];
rpAcqSetTriggerThreshold[0.25];
rpAcqSetTriggerDelay[8192];
rpAcqSetTriggerSource["AWG_PE"];
(*acquisition phase*)
rpAcqStart[];(*acquisition launch*)
rpGenBurstTrigger[]
(*wait for trigger & display*)
While[rpAcqGetTriggerState[] != "TD"];
data1 = rpAcqGetFullDataNum[1];
ListPlot[data1, Joined -> True, ImageSize -> "Large", PlotRange -> All, PlotTheme -> "Detailed"]
rpAcqReset[]

enter image description here

End

rpSCPIclose[]

The full package is attached and also the tutorial notebook.

Attachments:
POSTED BY: Christian Neel
3 Replies

enter image description here - you earned "Featured Contributor" badge, congratulations !

This is a great post and it has been selected for the curated Staff Picks group. Your profile is now distinguished by a "Featured Contributor" badge and displayed on the "Featured Contributor" board.

POSTED BY: EDITORIAL BOARD

Hi again Ian,

Thanks for the feedback! About SocketConnect I had the info but since I wrote the package with the version 10.1 (I think) I never took the time to rewrite it after that. But you are right SocketConnect and readLine are probably the best ways to secure the connection. I'll try to test it when I can put the hand on a Redpitaya again one of theses weekend.

Christian

POSTED BY: Christian Neel

Hi again Christian,

This is really cool, I'm glad to see this package! I see that most of your usage of the J/Link component here pertains to be able to write and read from sockets. We have the ability now (since 10.3) to connect to a socket from the Wolfram Language with SocketConnect.

For example, some of your commands could become like this:

socket = SocketConnect["ip address"];
WriteLine[socket,"DIG:PIN LED9,1"]

Then when you need to read from the socket, you can use

result = ReadLine[socket]

Ian

POSTED BY: Ian Johnson
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract