Sensor Data Logging in the PSLab Android App

The PSLab Android App allows users to log data from sensors connected to the PSLab hardware device. The Connected sensors should support I2C, SPI communication protocols to communicate with the PSLab device successfully. The only prerequisite is the additional support for the particular sensor plugin in Android App. The user can log data from various sensors and measure parameters like temperature, humidity, acceleration, magnetic field, etc. These parameters are useful in predicting and monitoring the environment and in performing many experiments.

The support for the sensor plugins was added during the porting python communication library code to Java. In this post,  we will discuss how we logged real time sensor data from the PSLab Hardware Device. We used Realm database to store the sensor data locally. We have taken the MPU6050 sensor as an example to understand the complete process of logging sensor data.

Creating Realm Object for MPU6050 Sensor Data

The MPU6050 sensor gives the acceleration and gyroscope readings along the three axes X, Y and Z. So the data object storing the readings of the mpu sensor have variables to store the acceleration and gyroscope readings along all three axes.

public class DataMPU6050 extends RealmObject {

   private double ax, ay, az;
   private double gx, gy, gz;
   private double temperature;

   public DataMPU6050() {  }

   public DataMPU6050(double ax, double ay, double az, double gx, double gy, double gz, double temperature) {
       this.ax = ax;
       this.ay = ay;
       this.az = az;
       this.gx = gx;
       this.gy = gy;
       this.gz = gz;
       this.temperature = temperature;
   }

  // getter and setter for all variables
}

Creating Runnable to Start/Stop Data Logging

To sample the sensor data at 500ms interval, we created a runnable object and passed it to another thread which would prevent lagging of the UI thread. We can start/stop logging by changing the value of the boolean loggingThreadRunning on button click. TaskMPU6050 is an AsyncTask which reads each sample of sensor data from the PSLab device, it gets executed inside a while loop which is controlled by boolean loggingThreadRunning. Thread.sleep(500) pauses the thread for 500ms, this is also one of the reason to transfer the logging to another thread instead of logging the sensor data in UI thread. If such 500ms delays are incorporated in UI thread, app experience won’t be smooth for the users.

Runnable loggingRunnable = new Runnable() {
   @Override
   public void run() {
       try {
           MPU6050 sensorMPU6050 = new MPU6050(i2c);
           while (loggingThreadRunning) {
               TaskMPU6050 taskMPU6050 = new TaskMPU6050(sensorMPU6050);
               taskMPU6050.execute();
              // use lock object to synchronize threads
               Thread.sleep(500);
           }
       } catch (IOException   InterruptedException e) {
           e.printStackTrace();
       }
   }
};

Sampling of Sensor Data

We created an AsyncTask to read each sample of the sensor data from the PSLab device in the background thread. The getRaw() method read raw values from the sensor and returned an ArrayList containing the acceleration and gyro values. After the values were read successfully, they were updated in the data card in the foreground which was visible to the user. This data card acts as a real-time screen for the user. All the samples read are appended to ArrayList mpu6050DataList, when the user clicks on button Save Data, the collected samples are saved to the local realm database.

private ArrayList<DataMPU6050> mpu6050DataList = new ArrayList<>();

private class TaskMPU6050 extends AsyncTask<Void, Void, Void> {

   private MPU6050 sensorMPU6050;
   private ArrayList<Double> dataMPU6050 = new ArrayList<>();

   TaskMPU6050(MPU6050 mpu6050) {
       this.sensorMPU6050 = mpu6050;
   }

   @Override
   protected Void doInBackground(Void... params) {
       try {
           dataMPU6050 = sensorMPU6050.getRaw();
       } catch (IOException e) {
           e.printStackTrace();
       }
       return null;
   }

   @Override
   protected void onPostExecute(Void aVoid) {
       super.onPostExecute(aVoid);
       // update data card TextViews with data read.
       DataMPU6050 tempObject = new DataMPU6050(dataMPU6050.get(0), dataMPU6050.get(1), dataMPU6050.get(2),
               dataMPU6050.get(4), dataMPU6050.get(5), dataMPU6050.get(6), dataMPU6050.get(3));
       mpu6050DataList.add(tempObject);
       synchronized (lock) {
           lock.notify();
       }
   }
}
Source: PSLab Android App

There is an option for Start/Stop Logging, clicking on which will change the value of boolean loggingThreadRunning which stops starts/stops the logging thread.

When the Save Data button is clicked, all the samples of sensor data collected from the  PSLab device till that point are saved to the local realm database.

realm.beginTransaction();
for (DataMPU6050 tempObject : mpu6050DataList) {
   realm.copyToRealm(tempObject);
}
realm.commitTransaction();

Data can also be written asynchronously to the local realm database. For other methods to write to a real database refer write section of Realm docs.

Resources

Fascinating Experiments with PSLab

PSLab can be extensively used in a variety of experiments ranging from the traditional electrical and electronics experiments to a number of innovative experiments. The PSLab desktop app and the Android app have all the essential features that are needed to perform the experiments. In addition to that there is a large collection of built-in experiments in both these experiments.

This blog is an extension to the blog post mentioned here. This blog lists some of the basic electrical and electronics experiments which are based on the same principles which are mentioned in the previous blog. In addition to that, some interesting and innovative experiments where PSLab can be used are also listed here. The experiments mentioned here require some prerequisite knowledge of electronic elements and basic circuit building. (The links mentioned at the end of the blog will be helpful in this case)

Op-Amp as an Inverting and a Non-Inverting Amplifier

There are two methods of doing this experiment. PSLab already has a built-in experiment dedicated to inverting and non-inverting amplification of op-amps. In the Android App, just navigate to Saved Experiments -> Electronics Experiments -> Op-Amp Circuits -> Inverting/ Non-Inverting. In case of the Desktop app, select Electronics Experiments from the main drop-down at the top of the window and select the Inverting/Non-inverting op-amp experiment.

This experiment can also performed using the basic features of PSLab. The only advantage of this methodology is that it allows much more tweaking of values to observe the Op-Amp behaviour in greater detail. However, the built-in experiment is good enough for most of the cases.

  • Construct the above circuits on a breadboard.
  • For the amplifier, connect the terminals of CH1 and GND of PSLab on the input side i.e. next to Vi and the terminals of CH2 and GND on the output side i.e next to Vo.
  • Usually, an Op-Amp like LM741 have a set of pins, one dedicated for the inverting input and the other dedicated for the non-inverting input. It is recommended to consult the datasheet of the Op-Amp IC used in order to get the pin number with which the input has to be connected.
  • The terminals of W1 and GND are also connected on the input side and they are used to generate a sine wave.
  • The resistors displayed in the figure have the values R1 = 10k and R2 = 51k. Resistance values other than these can also be considered. The gain of the op-amp would depend on the ratio of R2/R1, so it is better to consider values of R2 which are significantly larger than R1 in order to see the gain properly.
  • Use the PSLab Desktop App and open the Waveform Generator in Control. Set the wave type of W1 to Sine and set the frequency at 1 kHz and magnitude to 0.1 V. Then go ahead and open the Oscilloscope.
  • CH1 would display the input waveform and CH2 will display the output waveform and the plots can be observed.
  • If the input is connected to the inverting pin of the op-amp, the output obtained will be amplified and will have a phase difference of 90o with the input waveform whereas when the non-inverting pin is selected, the output is just amplified and no such phase difference is observed.
  • Note: Take proper care while connecting the V+ and V- pins of the op-amp, else the op-amp will be damaged.

Diode as an Integrator and Differentiator

An integrator in measurement and control applications is an element whose output signal is the time integral of its input signal. It accumulates the input quantity over a defined time to produce a representative output.

Integration is an important part of many engineering and scientific applications. Mechanical integrators are the oldest application, and are still used in such as metering of water flow or electric power. Electronic analogue integrators are the basis of analog computers and charge amplifiers. Integration is also performed by digital computing algorithms.

In electronics, a differentiator is a circuit that is designed such that the output of the circuit is approximately directly proportional to the rate of change (the time derivative) of the input. An active differentiator includes some form of amplifier. A passive differentiator circuit is made of only resistors and capacitors.

  • Construct the above circuits on a breadboard.
  • For both the circuits, connect the terminals of CH1 and GND of PSLab on the input side i.e. next to input voltage source and the terminals of CH2 and GND on the output side i.e next to Vo.
  • Ensure that the inverting and the non-inverting terminals of the op-amp are connected correctly. Check for the +/- signs in the diagram. ‘+’ corresponds to non-inverting and ‘-’ corresponds to inverting.
  • The terminals of W1 and GND are also connected on the input side and they are used to generate a sine wave.
  • The resistors displayed in the figure have the values R1 = 10k and R2 = 51k. Resistance values other than these can also be considered. The gain of the op-amp would depend on the ratio of R2/R1, so it is better to consider values of R2 which are significantly larger than R1 in order to see the gain properly.
  • Use the PSLab Desktop App and open the Waveform Generator in Control. Set the wave type of W1 to Sine and set the frequency at 1 kHz and magnitude to 5V (10V peak to peak). Then go ahead and open the Oscilloscope.
  • CH1 would display the input waveform and CH2 will display the output waveform and the plots can be observed.
  • If all the connections are made properly and the values of the parameters are set properly, then the waveform obtained should be as shown below.

Performing experiments involving ICs (Digital circuits)

The experiments mentioned so far including the ones mentioned in the previous blog post involved analog circuits and so they required features like the arbitrary waveform generator. However, digital circuits work using discrete values only. PSLab has the features needed to perform digital experiments which mainly involve the use of a square wave generator with a variable duty cycle.

PSLab board has dedicated pins named SQR1, SQR2, SQR3 and SQR4. The options for configuring these pins is present under the Advanced Control section in the Desktop app and in the Android app Applications->Control->Advanced. The options include selecting the pins which we want to use for digital outputs and then configuring the frequency and duty cycle of the square wave generated from that particular pin.

Innovative Experiments using PSLab

PSLab has quite a good number of interesting built-in experiments. These experiments can be found in the dropdown list at the top in the Desktop App and under the Saved Experiments header in the Android App. The built-in experiments come bundled with good quality documentation having circuit diagrams and detailed procedure to perform the experiments.

Some of the interesting experiments include:

  • Lemon Cell Experiment: In this experiment, the internal resistance and the voltage supplied by the lemon cell are measured.

 

  • Sound Beats: In acoustics, a beat is an interference pattern between two sounds of slightly different frequencies, perceived as a periodic variation in volume whose rate is the difference of the two frequencies.

 

  • When tuning instruments that can produce sustained tones, beats can readily be recognized. Tuning two tones to a unison will present a peculiar effect: when the two tones are close in pitch but not identical, the difference in frequency generates the beating.
  • This experiment requires producing two waves together of different frequencies and connecting them to the same oscilloscope channel. The pattern observed is shown below.

References:

  1. The previous blog on experiments using PSLab – http://blog.fossasia.org/electronics-experiments-with-pslab/
  2. More about op-amps and their characteristics – http://www.electronics-tutorials.ws/opamp/opamp_1.html
  3. Read more about differential and integrator circuits – https://www.allaboutcircuits.com/textbook/semiconductors/chpt-8/differentiator-integrator-circuits/
  4. Experiments involving digital circuits for reference – http://web.iitd.ac.in/~shouri/eep201/experiments.php

Implement Wave Generation Functionality in The PSLab Android App

The PSLab Android App works as an Oscilloscope using the audio jack of Android device. The implementation for the scope using in-built mic is discussed in the post Using the Audio Jack to make an Oscilloscope in the PSLab Android App. Another application which can be implemented by hacking the audio jack is Wave Generation. We can generate different types of signals on the wires connected to the audio jack using the Android APIs that control the Audio Hardware. In this post, I will discuss about how we can generate wave by using the Android APIs for controlling the audio hardware.

Configuration of Audio Jack for Wave Generation

Simply cut open the wire of a cheap pair of earphones to gain control of its terminals and attach alligator pins by soldering or any other hack(jugaad) that you can think of. After you are done with the tinkering of the earphone jack, it should look something like shown in the image below.

Source: edn.com

If your earphones had mic, it would have an extra wire for mic input. In any general pair of earphones the wire configuration is almost the same as shown in the image below.

Source: flickr

Android APIs for Controlling Audio Hardware

AudioRecord and AudioTrack are the two classes in Android that manages recording and playback respectively. For Wave Generation application we only need AudioTrack class.

Creating an AudioRecord object: We need the following parameters to initialise an AudioRecord object.

STREAM TYPE: Type of stream like STREAM_SYSTEM, STREAM_MUSIC, STREAM_RING, etc. For wave generation purpose we are using stream music. Every stream has its own maximum and minimum volume level.

SAMPLING RATE: it is the rate at which source samples the audio signal.

BUFFER SIZE IN BYTES: total size in bytes of the internal buffer from where the audio data is read for playback.

MODES: There are two modes

  • MODE_STATIC: Audio data is transferred from Java to native layer only once before the audio starts playing.
  • MODE_STREAM: Audio data is streamed from Java to native layer as audio is being played.

getMinBufferSize() returns the estimated minimum buffer size required for an AudioTrack object to be created in the MODE_STREAM mode.

private int minTrackBufferSize;
private static final int SAMPLING_RATE = 44100;
minTrackBufferSize = AudioTrack.getMinBufferSize(SAMPLING_RATE, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);

audioTrack = new AudioTrack(
       AudioManager.STREAM_MUSIC,
       SAMPLING_RATE,
       AudioFormat.CHANNEL_OUT_MONO,
       AudioFormat.ENCODING_PCM_16BIT,
       minTrackBufferSize,
       AudioTrack.MODE_STREAM);

Function createBuffer() creates the audio buffer that is played using the audio track object i.e audio track object would write this buffer on playback stream. Function below fills random values in the buffer due to which a random signal is generated. If we want to generate some specific wave like Square Wave, Sine Wave, Triangular Wave, we have to fill the buffer accordingly.

public short[] createBuffer(int frequency) {
   // generating a random buffer for now
   short[] buffer = new short[minTrackBufferSize];
   for (int i = 0; i < minTrackBufferSize; i++) {
       buffer[i] = (short) (random.nextInt(32767) + (-32768));
   }
   return buffer;
}

We created a write() method and passed the audio buffer created in above step as an argument to the method. This method writes audio buffer into audio stream for playback.

public void write(short[] buffer) {
   /* write buffer to audioTrack */
   audioTrack.write(buffer, 0, buffer.length);
}

Amplitude of the signal can be controlled by changing the volume level of the stream on which the buffer is being played. As we are playing the audio in music stream, so STREAM_MUSIC is passed as a parameter to the setStreamVolume() method.

value: value is amplitude level of the stream. Every stream has its different amplitude levels. getStreamMaxVolume(STREAM_TYPE) method is used to find the maximum valid amplitude level of any stream.
flag: this stackoverflow post explain all the flags of the AudioManager class.

AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, value, flag);

Roadmap

We are working on implementing methods to fill audio buffer with specific values such that waves like Sinusoidal wave, Square Wave, Sawtooth Wave can be generated during the playback of the buffer using the AudioTrack object.

Resources

Electronics Experiments with PSLab

Numerous college level electronics experiments can be performed using Pocket Science Lab (PSLab). The Android app and the Desktop app have all the essential features needed to perform these experiments and both these apps have quite a large number of experiments built-in. Some of the common experiments involve the use of BJT (Bipolar Junction Transistor), Zener Diode, FET (Field Effect Transistor), Op-Amp ( Operational Amplifier) etc. This blog walks through the details of performing some experiments using the above commonly used elements.  

The materials required for all the experiments are minimal and includes a few things like PSLab hardware device, components like Diodes, Transistors, Op-Amps etc., connecting wires/jumpers and secondary components like resistors, capacitors etc. Most of these elements would be a part of the PSLab Accessory Kit.

It is recommended to read this blog here, go through the resources mentioned at the end and also get acquainted with construction of circuits before advancing with the experiments mentioned in this blog.

Half Wave and Full Wave Rectifiers

The Bipolar Junction Transistor (BJT) can be used as a rectifier. Rectifiers are needed in circuits to obtain a nearly constant and stable output voltage and prevent any ripples in the circuit. The rectifier can be half wave or full wave depending on whether it rectifies one or both cycles of Alternating Voltage.

The circuit for the Half and Full Wave rectifier is given as follows:

  • Construct the above circuits on a breadboard.
  • For the half wave rectifier, connect the terminals of CH1 and GND of PSLab on the input side and the terminals of CH2 and GND on the output side.
  • The terminals of W1 and GND are also connected on the input side and they are used to generate a sine wave.
  • Use the PSLab Desktop App and open the Waveform Generator in Control. Set the wave type of W1 to Sine and set the frequency at 100 Hz and magnitude to 10mV. Then go ahead and open the Oscilloscope.
  • CH1 would display the input waveform and CH2 will display the output waveform and the plots can be observed.
  • The plot obtained will have rectification in only half of the cycle. In order to obtain rectification in the complete cycle, the full wave rectifier is needed.
  • For the full wave rectifier, the procedure is the same but an additional diode is used. Use an additional channel CH3 to plot the extra input.

  • The plot obtained from the above steps would still have ripples and so a capacitor is placed in parallel to cancel this effect.
  • Place a 100uF/330uF capacitor in parallel to the resistor RL and an additional 1 ohm resistor in the circuit.

BJT Inverter

  • Transistor has a lot of functions. The most common of them is its use as an amplifier. However, transistor can be used as a switch in a circuit i.e. as an inverter.
  • The circuit for this experiment is shown below. For this experiment, it is recommended to use an external 5V DC supply like a battery. Connect the transistor and the diode initially and then connect the resistors accordingly. (Connect the terminals of diode and transistor carefully else they will be damaged).
  • When the circuit is constructed completely, connect CH1 to Vi and CH2 to Vo. Vi and Vo are input and outputs respectively and are marked in the figure.
  • The terminals of W1 and GND are also connected on the input side and they are used to generate a sine wave.
  • Use the PSLab Desktop App and open the Waveform Generator in Control. Set the wave type of W1 to Sine and set the frequency at 200 Hz and magnitude to 10mV.
  • Then go ahead and open the Oscilloscope. Use the X-Y mode of the oscilloscope to obtain the plot between Vi and Vo which should look like the graph shown below.

Common Mode Gain and Differential Mode Gain in Op-Amps

Gain of any amplifier can be calculated by calculating the ratio of the output and input voltage. On plotting the graph in X-Y mode, a Vo vs Vi graph is obtained. The slope of that graph gives us the gain at any particular input voltage.

  • For finding the Differential Mode gain of an Op-Amp, construct the circuit as shown below.
  • When the circuit is constructed completely, connect CH1 to Vi and CH2 to Vo. Vi and Vo are input and outputs respectively and are marked in the figure. The terminals of W1 and GND are also connected on the input side and they are used to generate a sine wave.
  • The power supply provided to the Op-Amp are set to + 12V. (If faced with any confusion, please refer to the resources mentioned at the end of the blog to learn more about Op-Amps before proceeding ahead.)
  • Use the PSLab Desktop App and open the Waveform Generator in Control. Set the wave type of W1 to Sine and set the frequency at 1000 Hz and magnitude to 0.5V. Then go ahead and open the Oscilloscope. Use the X-Y mode of the oscilloscope to obtain the plot between Vi and Vo.
  • For finding the Common Mode gain of the Op-Amp, remove the waveform generator input i.e W1 from R3 and attach it to R2. The rest of the steps remain the same.

Schmitt Trigger

In electronics, a Schmitt trigger is a comparator circuit with hysteresis implemented by applying positive feedback to the noninverting input of a comparator or differential amplifier. It is an active circuit which converts an analog input signal to a digital output signal.

  • Construct the circuit as shown below. Although the diagram shows a variable resistor be used, a constant value resistor would also work fine.
  • When the circuit is constructed completely, connect CH1 to Vi and CH2 to Vo. Vi and Vo are input and outputs respectively and are marked in the figure. The terminals of W1 and GND are also connected on the input side and they are used to generate a sine wave.
  • The power supply provided to the Op-Amp are set to + 12V. (If faced with any confusion, please refer to the resources mentioned at the end of the blog to learn more about Op-Amps before proceeding ahead. If done incorrectly, Op-Amps will be damaged)
  • Use the PSLab Desktop App and open the Waveform Generator in Control. Set the wave type of W1 to Sine and set the frequency at 1000 Hz and magnitude to 0.5V. Then go ahead and open the Oscilloscope. Use the X-Y mode of the oscilloscope to obtain the plot between Vi and Vo which should look like the graph shown below.

Resources:

  1. Read more about Half wave and Full wave rectifier and their applications – https://en.wikipedia.org/wiki/Rectifier
  2. Read more about the Bipolar Junction Transistor and its use as a switch – http://www.electronicshub.org/transistor-as-switch/
  3. Understand the common mode and differential mode of Op-Amp – https://www.allaboutcircuits.com/video-lectures/op-amps-common-differential/
  4. Find more about Schmitt Trigger and its uses – https://en.wikipedia.org/wiki/Schmitt_trigger

SPI Communication in PSLab

PSLab supports communication using the Serial Peripheral Interface (SPI) protocol. The Desktop App as well as the Android App have the framework set-up to use this feature. SPI protocol is mainly used by a few sensors which can be connected to PSLab. For supporting SPI communication, the PSLab Communication library has a dedicated class defined for SPI. A brief overview of how SPI communication works and its advantages & limitations can be found here.

The class dedicated for SPI communication with numerous methods defined in them. The methods required for a particular SPI sensor may differ slightly, however, in general most sensors utilise a certain common set of methods. The set of methods that are commonly used are listed below with their functions.

In the setParameters method, the SPI parameters like Clock Polarity (CKP/CPOL), Clock Edge (CKE/CPHA), SPI modes (SMP) and other parameters like primary and secondary prescalar which are specific to the device used.

Primary Prescaler (0,1,2,3) for 64MHz clock->(64:1,16:1,4:1,1:1)

Secondary prescaler (0,1,..7)->(8:1,7:1,..1:1)

The values of CKP/CPOL and CKE/CPHA needs to set using the following convention and according to our requirements.

  • At CPOL=0 the base value of the clock is zero, i.e. the idle state is 0 and active state is 1.
    • For CPHA=0, data is captured on the clock’s rising edge (low→high transition) and data is changed at the falling edge (high→low transition).
    • For CPHA=1, data is captured on the clock’s falling edge (high→low transition) and data is changed at the rising edge (low→high transition).
  • At CPOL=1 the base value of the clock is one (inversion of CPOL=0), i.e. the idle state is 1 and active state is 0.
    • For CPHA=0, data is captured on the clock’s falling edge (high→low transition) and data is changed at the rising edge (low→high transition).
    • For CPHA=1, data is captured on the clock’s rising edge (low→high transition) and data is changed at the falling edge (high→low transition).

public void setParameters(int primaryPreScalar, int secondaryPreScalar, Integer CKE, Integer CKP, Integer SMP) throws IOException {
        if (CKE != null) this.CKE = CKE;
        if (CKP != null) this.CKP = CKP;
        if (SMP != null) this.SMP = SMP;

        packetHandler.sendByte(commandsProto.SPI_HEADER);
        packetHandler.sendByte(commandsProto.SET_SPI_PARAMETERS);
        packetHandler.sendByte(secondaryPreScalar | (primaryPreScalar << 3) | (this.CKE << 5) | (this.CKP << 6) | (this.SMP << 7));
        packetHandler.getAcknowledgement();
    }

 

The start method is responsible for sending the instruction to initiate the SPI communication and it takes the channel which will be used for communication as input.

public void start(int channel) throws IOException {
        packetHandler.sendByte(commandsProto.SPI_HEADER);
        packetHandler.sendByte(commandsProto.START_SPI);
        packetHandler.sendByte(channel);
    }

 

The setCS method is responsible for selecting the slave with which the SPI communication has to be done. This feature of SPI communication is known as Chip Select (CS) or Slave Select (SS). A master can use multiple Chip/Slave Select pins for communication whereas a slave utilises just one pin as SPI is based on single master multiple slaves principle. The capacity of PSLab is limited to two slave devices at a time.

public void setCS(String channel, int state) throws IOException {
        String[] chipSelect = new String[]{"CS1", "CS2"};
        channel = channel.toUpperCase();
        if (Arrays.asList(chipSelect).contains(channel)) {
            int csNum = Arrays.asList(chipSelect).indexOf(channel) + 9;
            packetHandler.sendByte(commandsProto.SPI_HEADER);
            if (state == 1)
                packetHandler.sendByte(commandsProto.STOP_SPI);
            else
                packetHandler.sendByte(commandsProto.START_SPI);
            packetHandler.sendByte(csNum);
        } else {
            Log.d(TAG, "Channel does not exist");
        }
    }

 

The stop method is responsible for sending the instruction to the stop the communication with the slave.

public void stop(int channel) throws IOException {
        packetHandler.sendByte(commandsProto.SPI_HEADER);
        packetHandler.sendByte(commandsProto.STOP_SPI);
        packetHandler.sendByte(channel);
    }

 

PSLab SPI class has methods defined for sending either 8-bit or 16-bit data over SPI which are further classified on whether they request the acknowledgement byte (it helps to know whether the communication was successful or unsuccessful) or not.

The methods are so named send8, send16, send8_burst and send16_burst . The burst methods do not request any acknowledgement value and as a result work faster than the normal methods.

public int send16(int value) throws IOException {
        packetHandler.sendByte(commandsProto.SPI_HEADER);
        packetHandler.sendByte(commandsProto.SEND_SPI16);
        packetHandler.sendInt(value);
        int retValue = packetHandler.getInt();
        packetHandler.getAcknowledgement();
        return retValue;
    }

 

Resources:

I2C Communication in PSLab

PSLab supports communication using the I2C protocol and both the Desktop App and the Android App have the framework set-up to use the I2C protocol. I2C protocol is mainly used by sensors which can be connected to PSLab. For supporting I2C communication, PSLab board has a separate block for I2C communication and has pins named 3.3V, GND, SCL and SDA. A brief overview of how I2C communication works and its advantages & limitations compared to SPI communication can be found here.

The PSLab Python and Java communication libraries have a class dedicated for I2C communication with numerous methods defined in them. The methods required for a particular I2C sensor may differ, however, in general most sensors utilise a certain common set of methods. The set of methods that are commonly used are listed below with their functions. For utilising the methods, the I2C bus is first notified using the HEADER byte (it is common to all the methods) and then a byte to uniquely determine the method in use.

The send method is used to send the data over the I2C bus. First the I2C bus is initialised and set to the correct slave address using I2C.start(address) followed by this method. The method takes the data to be sent as the argument.

def send(self, data):
    try:
        self.H.__sendByte__(CP.I2C_HEADER)
        self.H.__sendByte__(CP.I2C_SEND)
        self.H.__sendByte__(data)  # data byte
        return self.H.__get_ack__() >> 4
    except Exception as ex:
        self.raiseException(ex, "Communication Error , Function : " + inspect.currentframe().f_code.co_name)

 

The read method reads a fixed number of bytes from the I2C slave. One can also use I2C.simpleRead(address,  numbytes) instead to read from the I2C slave. This method takes the length of the data to be read as argument.  It fetches length-1 bytes with acknowledge bits for each.

def read(self, length):
     data = []
     try:
        for a in range(length - 1):
             self.H.__sendByte__(CP.I2C_HEADER)
             self.H.__sendByte__(CP.I2C_READ_MORE)
             data.append(self.H.__getByte__())
             self.H.__get_ack__()
       self.H.__sendByte__(CP.I2C_HEADER)
       self.H.__sendByte__(CP.I2C_READ_END)
       data.append(self.H.__getByte__())
       self.H.__get_ack__()
    except Exception as ex:
       self.raiseException(ex, "Communication Error , Function : " + inspect.currentframe().f_code.co_name)
   return data

 

The readBulk method reads the data from the I2C slave. This takes the I2C slave device address, the address of the device from which the data is to be read and the length of the data to be read as argument and the returns the bytes read in the form of a list.

def readBulk(self, device_address, register_address, bytes_to_read):
        try:
            self.H.__sendByte__(CP.I2C_HEADER)
            self.H.__sendByte__(CP.I2C_READ_BULK)
            self.H.__sendByte__(device_address)
            self.H.__sendByte__(register_address)
            self.H.__sendByte__(bytes_to_read)
            data = self.H.fd.read(bytes_to_read)
            self.H.__get_ack__()
            try:
                return [ord(a) for a in data]
            except:
                print('Transaction failed')
                return False
        except Exception as ex:
           self.raiseException(ex, "Communication Error , Function : " + inspect.currentframe().f_code.co_name)

 

The writeBulk method writes the data to the I2C slave. It takes address of the particular I2C slave for which the data is to be written and the data to be written as arguments.

def writeBulk(self, device_address, bytestream):
        try:
            self.H.__sendByte__(CP.I2C_HEADER)
            self.H.__sendByte__(CP.I2C_WRITE_BULK)
            self.H.__sendByte__(device_address)
            self.H.__sendByte__(len(bytestream))
            for a in bytestream:
                self.H.__sendByte__(a)
            self.H.__get_ack__()
        except Exception as ex:
  self.raiseException(ex, "Communication Error , Function : " + inspect.currentframe().f_code.co_name)

 

The scan method scans the I2C port for connected devices which utilise I2C as a communication mode. It takes frequency as an argument to set the frequency of the communication and is by default set to 100000. An array containing the addresses of the connected devices (which are integers) is returned.

def scan(self, frequency=100000, verbose=False):
        self.config(frequency, verbose)
        addrs = []
        n = 0
        if verbose:
            print('Scanning addresses 0-127...')
            print('Address', '\t', 'Possible Devices')
        for a in range(0, 128):
            x = self.start(a, 0)
            if x & 1 == 0:  # ACK received
                addrs.append(a)
                if verbose: print(hex(a), '\t\t', self.SENSORS.get(a, 'None'))
                n += 1
            self.stop()
       return addrs

 

Additional Sources

  1. Learn more about the principles behind i2c communication https://learn.sparkfun.com/tutorials/i2c
  2. A simple experiment to demonstrate use of i2c communication with Arduino http://howtomechatronics.com/tutorials/arduino/how-i2c-communication-works-and-how-to-use-it-with-arduino/
  3. Java counterpart of the PSLab I2C library https://github.com/fossasia/pslab-android/blob/master/app/src/main/java/org/fossasia/pslab/communication/peripherals/I2C.java

Real time Sensor Data Analysis on PSLab Android

PSLab device has the capacity to connect plug and play sensors through the I2C bus. The sensors are capable of providing data in real time. So, the PSLab Android App and the Desktop app need to have the feature to fetch real time sensor values and display the same in the user interface along with plotting the values on a simple graph.

The UI was made following the guidelines of Google’s Material Design and incorporating some ideas from the Science Journal app. Cards are used for making each section of the UI. There are segregated sections for real time updates and plotting where the real time data can be visualised. A methods for fetching the data are run continuously in the background which receive the data from the sensor and then update the screen.

The following section denotes a small portion of the UI responsible for displaying the data on the screen continuously and are quite simple enough. There are a number of TextViews which are being constantly updated on the screen. Their number depends on the type and volume of data sent by the sensor.

<TextView
       android:layout_width="wrap_content"
       android:layout_height="30dp"
       android:layout_gravity="start"
       android:text="@string/ax"
       android:textAlignment="textStart"
       android:textColor="@color/black"
       android:textSize="@dimen/textsize_edittext"
       android:textStyle="bold" />

<TextView
       android:id="@+id/tv_sensor_mpu6050_ax"
       android:layout_width="wrap_content"
       android:layout_height="30dp"
       android:layout_gravity="start"
       android:textAlignment="textStart"
       android:textColor="@color/black"
       android:textSize="@dimen/textsize_edittext"
       android:textStyle="bold" />

 

The section here represents the portion of the UI responsible for displaying the graph. Like all other parts of the UI of PSLab Android, MPAndroidChart is being used here for plotting the graph.

<LinearLayout
       android:layout_width="match_parent"
       android:layout_height="160dp"
       android:layout_marginTop="40dp">

       <com.github.mikephil.charting.charts.LineChart
               android:id="@+id/chart_sensor_mpu6050"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
               android:background="#000" />
</LinearLayout>

 

Since the updates needs to continuous, a process should be continuously run for updating the display of the data and the graph. There are a variety of options available in Android in this regard like using a Timer on the UI thread and keep updating the data continuously, using ASyncTask to run a process in the background etc.

The issue with the former is that since all the processes i.e. fetching the data and updating the textviews & graph will run on the UI thread, the UI will become laggy. So, the developer team chose to use ASyncTask and make all the processes run in the background so that the UI thread functions smoothly.

A new class SensorDataFetch which extends AsyncTask is defined and its object is created in a runnable and the use of runnable ensures that the thread is run continuously till the time the fragment is used by the user.

scienceLab = ScienceLabCommon.scienceLab;
i2c = scienceLab.i2c;
try {
    MPU6050 = new MPU6050(i2c);
} catch (IOException e) {
    e.printStackTrace();
}
Runnable runnable = new Runnable() {
    @Override
    public void run() {
        while (true) {
            if (scienceLab.isConnected()) {
                try {
                    sensorDataFetch = new SensorDataFetch();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                sensorDataFetch.execute();
            }
        }
    }
};
new Thread(runnable).start();

 

The following is the code for the ASyncTask created. There are two methods defined here doInBackground and onPostExecute which are responsible for fetching the data and updating the display respectively.

The raw data is fetched using the getRaw method of the MPU6050 object and stored in an ArrayList. The data type responsible for storing the data will depend on the return type of the getRaw method of each sensor class and might be different for other sensors. The data returned by getRaw is semi-processed and the data just needs to be split in sections before presenting it for display.

The PSLab Android app’s sensor files can be viewed here and they can give a better idea about how the sensors are calibrated, how the intrinsic nonlinearity is taken care of, how the communication actually works etc.

After the data is stored, the control moves to the onPostExecute method, here the textviews on the display and the chart are updated. The updation is slowed down a bit so that the user can visualize the data received.

private class SensorDataFetch extends AsyncTask<Void, Void, Void> {
   MPU6050 MPU6050 = new MPU6050(i2c);
   ArrayList<Double> dataMPU6050 = new ArrayList<Double>();

   private SensorDataFetch(MPU6050 MPU6050) throws IOException {
   }

   @Override
   protected Void doInBackground(Void... params) {
       try {
           if (MPU6050 != null) {
               dataMPU6050 = MPU6050.getRaw();
           }
       } catch (IOException e) {
           e.printStackTrace();
       }
           return null;
   }

   protected void onPostExecute(Void aVoid) {
       super.onPostExecute(aVoid);
       tvSensorMPU6050ax.setText(String.valueOf(dataMPU6050.get(0)));
       tvSensorMPU6050ay.setText(String.valueOf(dataMPU6050.get(1)));
       tvSensorMPU6050az.setText(String.valueOf(dataMPU6050.get(2)));
       tvSensorMPU6050gx.setText(String.valueOf(dataMPU6050.get(3)));
       tvSensorMPU6050gy.setText(String.valueOf(dataMPU6050.get(4)));
       tvSensorMPU6050gz.setText(String.valueOf(dataMPU6050.get(5)));
       tvSensorMPU6050temp.setText(String.valueOf(dataMPU6050.get(6)));
   }
}

The detailed implementation of the same can be found here.

Additional Resources

  1. Learn more about how real time sensor data analysis can be used in various fields like IOT http://ieeexplore.ieee.org/document/7248401/
  2. Google Fit guide on how to use native built-in sensors on phones, smart watches etc. https://developers.google.com/fit/android/sensors
  3. A simple starter guide to build an app capable of real time sensor data analysis http://developer.telerik.com/products/building-an-android-app-that-displays-live-accelerometer-data/
  4. Learn more about using AsyncTask https://developer.android.com/reference/android/os/AsyncTask.html

Integrating Travis CI and Codacy in PSLab Repositories

Continuous Integration Testing and Automated Code Review tools are really useful for developing better software, improving code and overall quality of the project. Continuous integration can help catch bugs by running tests automatically and to merge your code with confidence.

While working on my GsoC-16 project, my mentors guided and helped me to integrate Travis CI and Codacy in PSLab github repositories. This blog post is all about integrating these tools in my github repos, problems faced, errors occurred and the test results.

travisTravis CI is a hosted continuous integration and deployment system. It is used to build and test software projects hosted on github. There are two versions of it, travis-ci.com for private repositories, and travis-ci.org for public repositories.

Read : Getting started with Travis CI

Travis is configured with the “.travis.yml” file in your repository to tell Travis CI what to build. Following is the code from ‘.travis.yml‘ file in our PSLab repository. This repo contains python communication library for PSLab.

language: python
python:
  - "2.6"
  - "2.7"
  - "3.2"
  - "3.3"
  - "3.4"
# - "3.5"
# command to install dependencies
# install: "pip install -r requirements.txt"
# command to run tests
script: nosetests

With this code everything worked out of the box (except few initial builds which errored because of missing ‘requirements.txt‘ file) and build passed successfuly 🙂 🙂

Later Mario Behling added integration to FOSSASIA Slack Channel.

Slack notifications

Travis CI supports notifying  Slack channels about build results. On Slack, set up a new Travis CI integration. Select a channel, and you’ll find the details to paste into your ‘.travis.yml’. Just copy and paste the settings, which already include the proper token and you’re done.

The simplest configuration requires your account name and the token.

notifications:
  slack: '<account>:<token>'     
notifications:
  slack: fossasia:***tokenishidden****

Import errors in Travis builds of PSLab-apps Repository

PSLab-apps repository contains PyQt bases apps for various experiments. The ‘.travis.yml‘ file mentioned above gave several module import errors.

$ python --version
Python 3.2.5
$ pip --version
pip 6.0.7 from /home/travis/virtualenv/python3.2.5/lib/python3.2/site-packages (python 3.2)
Could not locate requirements.txt. Override the install: key in your .travis.yml to install dependencies.
0.33s$ nosetests
E
======================================================================
ERROR: Failure: ImportError (No module named sip)

The repo is installable and PSLab was working fine on popular linux distributions without any errors. I was not able to find the reason for build errors. Even after adding proper ‘requirements.txt‘ file,  travis builds errored.

On exploring the documentation I could figure out the problem.

Travis CI Environment uses separate virtualenv instances for each Python version. System Python is not used and should not be relied on. If you need to install Python packages, do it via pip and not apt. If you decide to use apt anyway, note that Python system packages only include Python 2.7 libraries (default python version). This means that the packages installed from the repositories are not available in other virtualenvs even if you use the –system-site-packages option. Therefore I was getting Import module errors.

This problem was solved by making following changes in the ‘.travis.yml‘ file

language: python

python:
  #- "2.6"
  - "2.7"
  #- "2.7_with_system_site_packages"
  - "3.2"
  #- "3.2_with_system_site_packages"
  - "3.3"
  - "3.4"
before_install:
    - sudo mkdir -p /downloads
    - sudo chmod a+rw /downloads
    - curl -L http://sourceforge.net/projects/pyqt/files/sip/sip-4.16.5/sip-4.16.5.tar.gz -o /downloads/sip.tar.gz 
    - curl -L http://sourceforge.net/projects/pyqt/files/PyQt4/PyQt-4.11.3/PyQt-x11-gpl-4.11.3.tar.gz -o /downloads/pyqt4.tar.gz
    # Builds
    - sudo mkdir -p /builds
    - sudo chmod a+rw /builds

install:
    - export DISPLAY=:99.0
    - sh -e /etc/init.d/xvfb start
    - sudo apt-get install -y libqt4-dev
    - sudo apt-get install -y mesa-common-dev libgl1-mesa-dev libglu1-mesa-dev
#    - sudo apt-get install -y python3-sip python3-sip-dev python3-pyqt4 cmake
    # Qt4
    - pushd /builds
    # SIP
    - tar xzf /downloads/sip.tar.gz --keep-newer-files
    - pushd sip-4.16.5
    - python configure.py
    - make
    - sudo make install
    - popd
    # PyQt4
    - tar xzf /downloads/pyqt4.tar.gz --keep-newer-files
    - pushd PyQt-x11-gpl-4.11.3
    - python configure.py -c --confirm-license --no-designer-plugin -e QtCore -e QtGui -e QtTest
    - make
    - sudo make install
    - popd
 # - "3.5"
# command to install dependencies
#install: "pip install -r requirements.txt"
# command to run tests
script: nosetests

notifications:
  slack: fossasia:*****tokenishidden*******


codacy

Codacy is an automated code analysis and review tool that helps developers ship better software, faster. With Codacy integration one can get static analysis, code complexity, code duplication and code coverage changes in every commit and pull request.

Read : Integrating Codacy in github is here.

Codacy integration has really helped me to understand and enforce code quality standard. Codacy gives you impact of every pull request in terms of quality and errors directly into GitHub.

codacy check

Codacy also grades your project in different categories like Code Complexity, Compatibility, security, code style, error prone etc. to help you better understand the overall project quality and what are the areas you should improve.

Here is a screen-shot of Codacy review for PSLab-apps repository.

codacyreport

I am extremely happy to share that my learning adventure has got  Project Certification at ‘A’ grade. Project quality analysis shows that more than 90% of the work has A grade 🙂 🙂

Travis CI and Codacy Badges for my GSoC Repositories:

PSLab : Python Library for Communication with PSLab

Travis CI Badge         Codacy Badge

PSLab-apps : Qt based GUI applications for PSLab

Travis CI Badge         Codacy Badge

Pocket Science Lab : ExpEYES Programs, Sensor Plugins

Travis CI Badge         Codacy Badge

That’s all for now. Have a happy coding, testing and learning 🙂 🙂

Design Your Own Experiments With PSLab

PSLab, with its simple and open architecture allows programmers, hobbyists to use the tool for various measurements and to develop new experiments with simple python code.

One of the main target group, the PSLab is aimed at, is high-school science teachers and students, who may or may-not be familiar with the computer programming. For such users it is difficult to design or develop new experiments on their own. They may also find it difficult to fetch the data and plot required graphs, if a ready-made GUI is not available for that particular experiment.

To enable such users to quickly design a simple experiment for studying various phenomena, we have developed a simple Experiment Designer GUI. This incorporates few controls, read-back elements and easy functions to select parameters and plot graphs.

The screen shot of the ‘Design Your Own Experiment’ GUI along with the App-window is here..

experiment designer1

Experiment Designer allows the user to define the control and read-back sequences of parameters and execute them.

Features of “Design Your Own Experiment” GUI

  • Configure Experiment : Here user can select the required channels ( manual / sweep / read-back). One can also add a derived channel for measuring some physical quantity, for example ‘current’.
  • Make Measurements : Selected channels are displayed. User can make measurements individually for each step or  can sweep in auto mode.
  • Plot and View Plots: Enables user to plot selected parameters. Acquired plots can be selectively displayed or deleted.
  • Save Plots: Data acquired can be save in a spreadsheet.
  • Save Profile : Experiment profile can be saved for repeating the experiment in future. Saved profiles can be loaded from “Load Profile” tab.

Example : Diode IV Characteristics Experiment

For this experiment one needs the following…

  • A variable voltage source : Needs to be swept from Voltage A to  B (say from 0V to 5V)
  • Current Monitoring : Needs to be read for every value of Voltage
  • Plotting and analytics :  Tools to plot the parameters and save data

Schematic Circuit diagram:

diode IV

CH3 monitors the voltage drop across the diode. PV1 is varied in steps, and for each step the current is calculated from the difference between voltages at PV1 and CH3, and the known value of the resistor. For example for 1K resistor, current through the diode is given by

I = (PV1-CH3)/1K

Procedure :

Step 1. Connect Fossasia PSLab to the pc. Connect the components –  Diode from CH3 to Ground and  1k resistor from PV1 to CH3

Step 2. From the terminal Run

Experiments

The App-window will pop-up. Click on ‘Design your own Experiment’ button to get the experiment designer GUI.

experiment designer2

Step 3: Select channels

Sweep Channel PV1 – Sweep from 0.00V -5.00V in 200 steps

Read-back Channel CH3 – for monitoring voltage across the diode

Derived Channel – To measure Current. Type the equation to calculate the current,   (PV1()-CH3())/1000

Step 4. Click on Prepare Experiment‘ to get measurements screen. Click on ‘Evaluate All Rows‘ to make the measurements.

Experiment designer3

Step 5. Select the required columns and click on Plot Selected Columns‘, a message window will pop-up, here user can select the Axes for plotting the graph. On clicking  ‘Plot‘, view plots screen will be displayed.

plotsdiodeiv

One can repeat the experiment and plot multiple curves and save them in a spreadsheet. Acquired plots can be selectively displayed or deleted.

Step 6. The entire design ( Experiment Profile)  of the experiment can be saved for repeating the experiment in future. Saved profiles can be loaded from “Load Profile” tab.

experiment designer profile
This is a very important value add to PSLab Apps. It has enabled PSLab to reach out and help users, who do not have any background in programming. Now ‘designing your own experiments’ has become super easy 🙂 🙂 🙂

PSLab Communication Function Calls

Prerequisite reading:

Communicating with Pocket Science Lab via USB and capturing and plotting sine waves

Interfacing with the hardware of PSLab, fetching the data and plotting it is very simple and straight forward. Various sensors can be connected to PSLab and data can be fetched with a simple python code as shown in the following example…

>>> from PSL import sciencelab
>>> I = sciencelab.connect()     # Initializing: Returns None if device isn't found. The initialization process connects to tty device and loads calibration values.
# An example function that measures voltage present at the specified analog input
>>> print I.get_average_voltage('CH1')
# An example to capture and plot data
>>> I.set_gain('CH1', 3) # set input CH1 to +/-4V range 
>>> I.set_sine1(1000) # generate 1kHz sine wave on output W1 
>>> x,y = I.capture1('CH1', 1000, 10) # digitize CH1 1000 times, with 10 usec interval 
>>> plot(x,y) 
>>> show()
# An example function to get data from magnetometer sensor connected to PSLab
>>> from PSL.SENSORS import HMC5883L #A 3-axis magnetometer >>> M = HMC5883L.connect() >>> Gx,Gy,Gz = M.getRaw() 

The module sciencelab.py contains all the functions required for communicating with PSLab hardware. It also contains some utility functions. The class ScienceLab() contains methods that can be used to interact with the PSLab.

After initiating this class, all the features built into the device can be accessed  using various function calls.


Capture1 : for capturing one trace

capture1(ch, ns, tg)

Arguments

  • ch  : Channel to select as input. [‘CH1′..’CH3′,’SEN’]
  • ns  :  Number of samples to fetch. Maximum 10000
  • tg   :  Time gap between samples in microseconds
#Example >>> x,y = I.capture1('CH1', 1000, 10) # digitize CH1 1000 times, with 10 usec interval

Returns : Arrays X(timestamps),Y(Corresponding Voltage values)


Capture2 : for capturing two traces

capture2(ns, tg, TraceOneRemap='CH1')

Arguments

  • ns :  Number of samples to fetch. Maximum 5000
  • tg  :  Time gap between samples in microseconds
  • TraceOneRemap :   Choose the analogue input for channel 1 (Like MIC OR SEN). It is connected to CH1 by default. Channel 2 always reads CH2.
#Example 
>>> x,y1,y2 = I.capture2(1600,1.75,'CH1') # digitize CH1 and CH2, 1600 times, with 1.75 usec interval

Returns: Arrays X(timestamps),Y1(Voltage at CH1),Y2(Voltage at CH2)


Capture4 : for capturing four taces

capture4(ns, tg, TraceOneRemap='CH1')

Arguments

  • ns:   Number of samples to fetch. Maximum 2500
  • tg :   Time gap between samples in microseconds. Minimum 1.75uS
  • TraceOneRemap :   Choose the analogue input for channel 1 (Like MIC OR SEN). It is connected to CH1 by default. Channel 2 always reads CH2, channel 3 always reads CH3 and MIC is channel 4 (CH4)
#Example
>>> x,y1,y2,y3,y4 = I.capture4(800,1.75) # digitize CH1-CH4, 800 times, with 1.75 usec interval

Returns: Arrays X(timestamps),Y1(Voltage at CH1),Y2(Voltage at CH2),Y3(Voltage at CH3),Y4(Voltage at CH4)


Capture_multiple : for capturing multiple traces

capture_multiple(samples, tg, *args)

Arguments

  • samples:   Number of samples to fetch. Maximum 10000/(total specified channels)
  • tg :   Time gap between samples in microseconds.
  • *args :   channel names
# Example 
>>> from pylab import * 
>>> I=interface.Interface() 
>>> x,y1,y2,y3,y4 = I.capture_multiple(800,1.75,'CH1','CH2','MIC','SEN') 
>>> plot(x,y1) 
>>> plot(x,y2) 
>>> plot(x,y3) 
>>> plot(x,y4) 
>>> show()

Returns: Arrays X(timestamps),Y1,Y2 …


Capture_fullspeed : fetches oscilloscope traces from a single oscilloscope channel at a maximum speed of 2MSPS

capture_fullspeed(chan, amples, tg, *args)

Arguments

  • chan:   channel name ‘CH1’ / ‘CH2’ … ‘SEN’
  • tg :   Time gap between samples in microseconds. minimum 0.5uS
  • *args :   specify if SQR1 must be toggled right before capturing. ‘SET_LOW’ will set it to 0V, ‘SET_HIGH’ will set it to 5V. if no arguments are specified, a regular capture will be executed.
# Example
>>> from pylab import *
>>> I=interface.Interface()
>>> x,y = I.capture_fullspeed('CH1',2000,1)
>>> plot(x,y)               
>>> show()

Returns: timestamp array ,voltage_value array


Set_gain : Set the gain of selected PGA

set_gain(channel, gain)

Arguments

  • channel:   ‘CH1’ , ‘CH2’
  • gain :   (0-7) -> (1x,2x,4x,5x,8x,10x,16x,32x)

Note: The gain value applied to a channel will result in better resolution for small amplitude signals.

# Example
>>> I.set_gain('CH1',7)  #gain set to 32x on CH1


Get_average_voltage : Return the voltage on the selected channel
get_average_voltage(channel_name, **kwargs)
Arguments

  • channel_name:    ‘CH1’,’CH2’,’CH3’, ‘MIC’,’IN1’,’SEN’
  • **kwargs :   Samples to average can be specified. eg. samples=100 will average a hundred readings
# Example 
>>> print I.get_average_voltage('CH4')
1.002

Get_freq : Frequency measurement on IDx. Measures time taken for 16 rising edges of input signal. returns the frequency in Hertz

get_average_voltage(channel='Fin', timeout=0.1)
Arguments

  • channel :    The input to measure frequency from. ‘ID1’ , ‘ID2’, ‘ID3’, ‘ID4’, ‘Fin’
  • timeout :   This is a blocking call which will wait for one full wavelength before returning the calculated frequency. Use the timeout option if you’re unsure of the input signal. returns 0 if timed out
# Example
>>> I.sqr1(4000,25)
>>> print I.get_freq('ID1')
4000.0

Return float: frequency


Get_states : Gets the state of the digital inputs. returns dictionary with keys ‘ID1’,’ID2’,’ID3’,’ID4’
get_states()
#Example
>>> print get_states()
{'ID1': True, 'ID2': True, 'ID3': True, 'ID4': False}

Get_state : Returns the logic level on the specified input (ID1,ID2,ID3, or ID4)
get_state(input_id)
Arguments

  • input_id :    The input channel ‘ID1’ -> state of ID1 ‘ID4’ -> state of ID4
#Example
>>> print I.get_state(I.ID1)
False

Set_state : Set the logic level on digital outputs SQR1,SQR2,SQR3,SQR4
set_state(**kwargs)
Arguments

  • **kwargs :    SQR1,SQR2,SQR3,SQR4 states(0 or 1)
#Example
>>> I.set_state(SQR1=1, SQR2=0) #sets SQR1 HIGH, SQR2 LOw, but leave SQR3,SQR4 untouched.