Monday, 19 October 2015

Communicate with Your Arduino Through Android

Want to send text from your Android phone to your Arduino? Here's how!

Requirements

  • ​Android Phone which supports USB Host Mode (i.e OTG Support) - Most devices running Android 3.1+ support this. Check if your phone does using the USB Host Diagnostics App from the Play Store.
  • Arduino - Any version will do. I will be using an Uno R3 . 
  • Arduino USB Cable
  • USB OTG Cable - You will need this to connect the USB cable of the Arduino to the micro-USB port of the Smartphone. It costs about $5 on Amazon.
  • Android Studio - You will need to have this installed and setup. It is pretty easy to do that.  Android Studio makes app development easier with its predictions and code generation. It's one of the best IDEs out there. You could also follow this article to set up Android Studio on your computer.

Main Components of an Android App

There are 3 major files in an Android app:
  • MainActivity.java
    This is where the Java code goes. It controls the way the app will function.
  • activity_main.xml
    This contains the layout of the app, i.e. the components or the widget-like buttons, TextViews etc.
  • AndroidManifest.xml
    This is where you define when the app must start, which permissions it needs, and which hardware it needs to access.  
There are a host of other files too but they are all linked together with the help of these three.
An activity can be described as a screen where the user interacts with the phone. Activities contain widgets like buttons, text fields, images, etc., which help in the transfer of information. This tutorial will use one activity, the Main Activity, which will take the user's input to send to the Arduino and also display the received text.

The Layout


We will be using the same layout for both the USB App and the Bluetooth App. It's a simple one with the minimum required widgets to test the connection between the devices.
As you can see, it has an EditText widget for getting input from the user, buttons to start the connection, transmit the data, end the connection and clear the TextView. The recieved data is displayed in the TextView (the empty part below the buttons).
Here's a part of the XML. Since the code for buttons is similar I've left them out here. Get the complete code at the end of this article.


                    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"

    android:layout_height="match_parent" 
    
    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@dimen/activity_vertical_margin"

    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <EditText

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:id="@+id/editText"

        android:layout_alignParentTop="true"

        android:layout_alignParentRight="true"

        android:layout_alignParentEnd="true"

        android:layout_alignParentLeft="true"

        android:layout_alignParentStart="true" />

    <Button

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:text="Begin"

        android:id="@+id/buttonStart"

        android:layout_below="@+id/editText"

        android:layout_alignParentLeft="true"

        android:layout_alignParentStart="true"

        android:onClick="onClickStart"/>

    <TextView

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:id="@+id/textView"

        android:layout_below="@+id/buttonSend"

        android:layout_alignParentLeft="true"

        android:layout_alignParentStart="true"

        android:layout_alignRight="@+id/editText"

        android:layout_alignEnd="@+id/editText"

        android:layout_alignParentBottom="true" />

</RelativeLayout>
                  

​I have used a RelativeLayout here, meaning that every widget is arranged with respect to the widgets around it. The layout can be easily recreated using the Design Tab where you can drag-and-drop the widgets wherever you want. When a button is clicked, we will have to describe what needs to happen. For this, an OnClick method is used. Specify the name of the method in the XML of the button. To do this add the line:
android:onClick="onClickMethod"
Now hover on this line and an alert will pop up on the left like this:
Click Create 'OnClick...'. This will automatically inject code for the onClick method in MainActivity.java. You will have to do this for each button.

The Usb Serial Library

​Setting up a serial connection in Android is quite a hassle because it will require you to manually configure a lot of stuff, so I had been looking at some libraries which do all this automatically. I tested out a few of them and finally settled on the UsbSerial library by Github user felHR85. Among all the relevant libraries I had found, this was the only one which is still being updated. It is pretty easy to set up and use. To add this library to your project, download the latest JAR file from Github. Move it to the 'libs' folder in your project's directory. Then, in the file explorer of Android Studio, right-click the JAR and select "Add as Library". That's it!

The Program Flow

This is the brief outline of how we will proceed. Every activity has a onCreate() method which is the run when the activity is created. Whatever code you want to run at the start must be placed inside it. Do notice that reading from the device is asynchronous, meaning it will keep running in the background. This is done so that the data is received as soon as possible .

Opening a Connection

First off, let us define the onClick method for the Begin button. When clicked, it should search for all connected devices and then check if the vendor ID of the Arduino matches that of a connected device. If found, permission must be requested from the user. Each USB slave device has a vendor and product ID which can be used to identify what drivers should be used for it. The vendor ID for any Arduino is 0x2341 or 9025.
                    public void onClickStart(View view) {

        HashMap usbDevices = usbManager.getDeviceList();
        if (!usbDevices.isEmpty()) {
            boolean keep = true;
            for (Map.Entry entry : usbDevices.entrySet()) {
                device = entry.getValue();
                int deviceVID = device.getVendorId();
                if (deviceVID == 0x2341)//Arduino Vendor ID
                {
                    PendingIntent pi = PendingIntent.getBroadcast(this, 0, 
                     new Intent(ACTION_USB_PERMISSION), 0);
                    usbManager.requestPermission(device, pi);
                    keep = false;
                } else {
                    connection = null;
                    device = null;
                }

                if (!keep)
                    break;
            }
        }
    }
                  

​Now let us define the BroadcastReceiver to receive the broadcast to ask for user permission and also to start the connection automatically when a device is connected and to close the connection when it is disconnected.
                    private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { //Broadcast Receiver to automatically start and stop the Serial connection.
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(ACTION_USB_PERMISSION)) {
                boolean granted = 
                intent.getExtras().getBoolean(UsbManager.EXTRA_PERMISSION_GRANTED);
                if (granted) {
                    connection = usbManager.openDevice(device);
                    serialPort = UsbSerialDevice.createUsbSerialDevice(device, connection);
                    if (serialPort != null) {
                        if (serialPort.open()) { //Set Serial Connection Parameters.
                            setUiEnabled(true); //Enable Buttons in UI
                            serialPort.setBaudRate(9600);
                            serialPort.setDataBits(UsbSerialInterface.DATA_BITS_8);
                            serialPort.setStopBits(UsbSerialInterface.STOP_BITS_1);
                            serialPort.setParity(UsbSerialInterface.PARITY_NONE);
                            serialPort.setFlowControl(UsbSerialInterface.FLOW_CONTROL_OFF);
                            serialPort.read(mCallback); //
                            tvAppend(textView,"Serial Connection Opened!\n");

                        } else {
                            Log.d("SERIAL", "PORT NOT OPEN");
                        }
                    } else {
                        Log.d("SERIAL", "PORT IS NULL");
                    }
                } else {
                    Log.d("SERIAL", "PERM NOT GRANTED");
                }
            } else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_ATTACHED)) {
                onClickStart(startButton);
            } else if (intent.getAction().equals(UsbManager.ACTION_USB_DEVICE_DETACHED)) {
                onClickStop(stopButton);
            }
        };
    };
                  

If the first IF condition is satisfied, and if the user has granted permission, initiate a connection for the device whose vendor ID matched our required vendor ID. Also, if a broadcast for a device attach or detach is received, manually call the onClick methods for the Start and Stop buttons. A SerialPort is defined using the device as the connection as the arguments. If this is successful, open the SerialPort and set the parameters accordingly. For an Uno, the default parameters are 8 Data bits, 1 Stop bit, no parity bit and Flow Control is Off. The baud rate can be 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, or 115200, but let us go with the standard 9600.

Receiving data from the Device

In the code fragment above, notice the line that says serialPort.read(mCallback). Here a reference of a Callback is passed to the read function so that it will automatically trigger when any incoming data is detected.
                    UsbSerialInterface.UsbReadCallback mCallback = new UsbSerialInterface.UsbReadCallback() { 
     //Defining a Callback which triggers whenever data is read.
        @Override
        public void onReceivedData(byte[] arg0) {
            String data = null;
            try {
                data = new String(arg0, "UTF-8");
                data.concat("/n");
                tvAppend(textView, data);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
    };
                  

The data received will be in the form of raw bytes. We will have to re-encode it into a readable format like UTF-8. Then it is appended to the TextView using a custom method named tvAppend(). This is done because any change to the UI can only happen on the UI thread. Since this Callback will be running as a background thread, it can't affect the UI directly.
 private void tvAppend(TextView tv, CharSequence text) { final TextView ftv = tv; final CharSequence ftext = text; runOnUiThread(new Runnable() { @Override public void run() { ftv.append(ftext); } }); }  

Sending Data to the Device

Sending data is relatively easy when compared to reading data from the device. It is a simple function call with bytes of data which needs to be sent as the argument. This will be defined in the OnClick method of the Send Button.
serialPort.write(string.getBytes()); 

Closing the connection

To close the connection, just close the SerialPort.
serialPort.close();

The Application Manifest

​ In the manifest, state what extra permissions the app might require. The only one needed is the permission to make the phone a USB host. Add the following to the manifest:
<uses-feature android:name="android.hardware.usb.host" />The app can be made to start automatically by adding an IntentFilter to the MainActivity. This IntentFilter will be triggered when any new device is attached. The kind of device can be explicitly specified by providing the vendor ID and/or product ID in an XML file.
                    <?xml version="1.0" encoding="utf-8"?> 
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" />
            </intent-filter>

            <meta-data
                android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
                android:resource="@xml/device_filter" />
        </activity>
                  

​Notice the line "android:resource="@xml/device_filter". This tells the compiler that it can find the device properties in a file named device_filter in src/main/res/xml, so make a folder named "xml" in src/main/res and put the following in it:
                    <resources>
    <usb-device vendor-id="9025" />
    <!-- Vendor ID of Arduino -->
</resources>
                  

Testing the App

Build and run the app on your smartphone. Now fire up the Arduino IDE and set up the Arduino to simply echo whatever it receives on the serial port. Here's a very simple code to do that.
                    void setup()  
 {  
  Serial.begin(9600);  
 }  
 void loop()  
 {  
  char c;
  if(Serial.available())  
  {  
   c = Serial.read();  
   Serial.print(c);  
  }  
 }  
                  

​Now connect the Arduino to the microUSB port using the OTG Cable. The app must auto-start. Try sending some text and the same data will be echoed back!


Conclusion

​ This article has helped to show how an Arduino can talk to your Smartphone. The uses for this are endless! In case data from any sensor is needed and if that isn't available on board a smartphone, any microcontroller can be used to read from that sensor and transmit the data to the phone. The next part of the article will show how to connect using the popular Bluetooth HC05 Module.

 

Sunday, 18 October 2015

An Introduction to Freescale’s Kinetis Design Studio

In the last year, Freescale has revamped their ARM Cortex-M development platform. Previously just an Eclipse plugin, it has been upgraded into its own standalone platform, dubbed "Kinetis Design Studio," that comes with a whole slew of sweet features for embedded development. In addition to the Design Studio, Freescale has also created a handy software development kit to make it even easier to get your ideas rolling on hardware. It's compatible with every Kinetis board Freescale makes, and can get your hardware protoype up and running within an afternoon!

What You'll Need

  • An account here - You'll need it to download both of the software packages we'll be using here. It's totally free to register!
  • A download of Kinetis Design Studio - Once you've created your Freescale account, you need to download and install Kinetis Design Studio. I'll be showing some screenshots from KDS on my personal machine, which happens to be a Mac, but the Windows distribution isn't terribly different. This article uses KDS v3.0.0, which you can download here. (Note: you'll need to be logged into Freescale's webpage for this to work.)
  • A download of Kinetis Software Development Kit - While you're still logged into your Freescale account, you'll need to download the Kinetis SDK as well. You can find that at this link (also only works if you're logged into Freescale's page).
  • A Freescale Kinetis Development Board - I'm using the Freescale FRDM-K22F, but just about any of the Freescale Kinetis boards will work with this example - you just have to remember to swap out the build files shown in later sections for the appropriate board/processor. I'll do my best to make it abundantly clear when you need to pay attention to this!
  • A Segger J-Link EDU Debugger (Mac OS only) - OpenSDA, the embedded bootloader software that Freescale includes with their dev boards, does not currently have drivers available for Mac OS X. Not to worry, however! All you'll need is a Segger J-Link EDU debugger, which is available online for about $60. It's a very nice piece of debug hardware, and has a ton of uses besides programming boards, but we'll get into those later!
The goal of this piece is to show you how to get Kinetis Design Studio and Kinetis SDK playing nicely together. By the end of the article, you should have a working toolchain, and a simple program running on a Kinetis board!

At Your Local Library...

Before we start writing any code, we'll need to get the Kinetis Design Studio toolchain up, running, and playing nicely with the SDK. The first thing you'll need to do is build you platform specific linker library. The guide to do this is included with Kinetis SDK: navigate to your install directory to the path `/<install_dir>/KSDK_1.2.0/doc/`, and look for the file "Getting Started With Kinetis SDK". Follow the instructions from section 5.3, entitled "Build the Platform Library". This will build the linker library - we'll need it later in this article!

Total Eclipse from the Start

As I mentioned earlier, Kinetis Design Studio is really just Freescale's version of the Eclipse IDE. To get it playing nicely with Freescale's SDK, we have to install a patch to let KDS know that we have the kit installed on our machine. That patch is stored in the bowels of the SDK filesystem, in `/tools/eclipse_update/`. There will be a .zip file titled "KSDK_1.2.0_Eclipse_Update.zip". You will need to feed this to Kinetis Studio through the "Install New Software" utility, which is located under the "Help" dropdown menu.


Once the "Install New Software" window is open, click the "Add" button, then the "Archive" button on the resulting popup. Navigate to the correct zip file, select it, and click "OK". You'll be back at the "Install New Software" pane at this point, and "KSDK 1.2.0 Eclipse Update" should be in the "Available Software" box.


Click the checkbox next to it, and then select "Next". Click "Next" through the following screens, and then click "Finish" to start the patching process. Once the patch is complete, you will get a prompt asking you to restart the Kinetis Suite. Click "yes", and the software will bring you back to the main Kinetis Studio window.

The Setup

Alright! Now that we're back on the main tab, or "Workbench", we can start getting our build environment ready! Click on the "File" dropdown menu, and select "New > Kinetis Project". Name it whatever you like (I'm calling mine "blink"), and click the "Next" button. This will bring you to the Device selection pane. Select the board you're using from the list or using the search bar, and then click "Next".


Double check the board you are using. I'm using the FRDM-K22F board, but if yours is different, make sure you select the correct one from the dropdown!
The next menu allows you to specify what rapid development environment you are using. Since we installed Kinetis SDK, and patched Kinetis Studio to recognize that, Kinetis SDK should be the default option. (If you don't see Kinetis SDK as the default option, try rerunning the patch from the "Help > Install New Software" menu.) Double check that the absolute path to the "Freescale/KSDK_1.2.0" folder is correct, and then click "Finish". This will build up a nice project directory for you, with links to all of the proper toolchain utilites, header files, and startup code for your target processor.

Use Your Head(ers)!

Now that we've got a project folder rolling, we can set up the local project headers needed to link code to our target Freescale board. Right click on the "Sources" folder in the "Project Explorer" pane, and select "New > Folder". This is where we'll store Kinetis SDK's board-specific headers in our project. You can find these headers in `/KSDK_1.2.0/examples/`. For me, `board_id` is `frdmk22f`. Remember - if you are using a different board, choose the folder that corresponds to your board! Be sure to grab all of the files with a .c or .h extension in this folder. Once you've copied these into your project, you should have a folder in the "Project Explorer" pane of Kinetis Studio with the following files in it:
  • pin_mux.c
  • pin_mux.h
  • gpio_pins.c
  • gpio_pins.h
  • board.c
  • board.h

In addition to our `brd` folder, we want to create another folder, titled `util`. This is where we'll store a software defined UART connection used for debug purposes. Create the `util` folder the same way you created the `brd` folder, and then navigate to `//KSDK_1.2.0/platform/utilities/inc`. From this folder, copy the file `fsl_debug_console.h` into your new `util` file. After this is done, navigate to `//KSDK_1.2.0/platform/utilities/src`, and repeat the process of copying `fsl_debug_console.c` to your local `util` folder.

Never Break The (Tool)Chain

We're nearly ready to rock and roll! The last thing we need to do is to show Kinetis Studio what folders to look in when compiling. From the "Project" dropdown menu, select "Properties > C/C++ Build > Settings > Cross ARM C Compiler > Includes". You'll need to add a few paths to this window:
/KSDK_1.2.0/platform/drivers/inc
/KSDK_1.2.0/platform/hal/inc
/KSDK_1.2.0/platform/osa/inc
/KSDK_1.2.0/platform/system/inc
So that it ends up displaying the following:


Alright, one last thing to include! Head to the "Cross ARM C++ Linker > Libraries" window, and add "ksdk_platform" to the Libraries pane, and the path to your debug library in the "Library Search path" pane. Your debug library will be named "libsdk_platform.a", and should be located in a path similar to `/KSDK_1.2.0/lib/ksdk_platform_lib/kds/K22F51212/debug`. Don't see that file in the path you selected? That's because you haven't built the driver library yet! Make sure to head back to the beginning of this article and do that, or else your compiled code won't link!


Big Warning Here: you will need to select the folder that corresponds to your processor. Since I'm using the FRDM-K22F, I chose the K22F51212 folder, as that's the onboard processor.

The "Hello World" of Hardware

Phew! We made it through all of that setup. Now it's on to the big dance! We're going to build a simple program here just to show that the toolchain is working. I'm referring to that good old standby of embedded engineers - blinking an LED!

                    #include "fsl_device_registers.h"
#include "board.h"
#include "pin_mux.h"
#include "fsl_clock_manager.h"
#include "fsl_debug_console.h"
#include <stdio.h>


#define DELAY() do     \
     {     \
      int32_t i;   \
      for (i = 0; i < 0x1FFFFF; i++) \
      {    \
       __asm("nop");  \
      }    \
     } while (0);    \

int main(void)
{
 // enable clocks for GPIO ports
 CLOCK_SYS_EnablePortClock(PORTA_IDX);
 CLOCK_SYS_EnablePortClock(PORTD_IDX);

 // initialize GPIO
 GPIO_DRV_Init(switchPins, ledPins);

 while(1)
 {
  GPIO_DRV_TogglePinOutput(BOARD_GPIO_LED_BLUE);
                DELAY();
 }

 // Never return; loop forever!
 return 0;
}

                  

The first time we compile this guy, we'll need to set some default configurations. Click "Run > Debug Configurations" from the toolbar menu. I'll be running this as a Segger J-Link application, but it's really no different if you're running as a P&E Micro OpenSDA application. You just need to run through the debug configurations once, then click "Debug". This will take you to the "Debug" Perspective of Kinetis Design Studio. Click the "Start" button on the tool tray, and you should see your LED blinking happily away!

Wrapping Up/More Resources

Freescale has put a ton of good work into making development platforms like this available. Kinetis Design Suite and Kinetis SDK make a powerful combination for quick protoyping. Want to learn more? I'd highly recommend Erich Styger's site for more info on the Kinetis platform. Erich's tutorials are very thorough, and very useful!

Saturday, 17 October 2015

Build Your Own Time-Domain Reflectometer

What's a TDR?

Time Domain Reflectometry is a powerful technique in which a pulse is generated to propagate down a cable, after which the reflected signal returns to the generator and is then interpreted based on its shape, phase, and delay. The results can be used to determine the length of a cable, if and where there is an open circuit, what kind of load a cable is terminated with, and even the relative permittivity and permeability of a dielectric. TDRs are used in a wide range of applications including aviation and naval craft troubleshooting where there are often miles of cable and a technician can accurately pinpoint a malfunction. They are also used in devices measuring soil moisture content in which a cable is placed in the soil and the relative permittivity (dielectric constant) of the soil can be calculated. Because water has a very high relative permittivity and dry soil does not, the permittivity that is detected will correlate to the amount of moisture present. TDRs are used in this same way as a level indicator for liquids, where a thin probe is submerged and detects lower permittivity as the level drops. Most circuit board verification jigs will implement this technique as a method of determining if a chip on a ball-grid-array solder pad has any open pins.

How It Works

The physics behind this method can be pretty complex (single equations that take up half a page), but we will work with a few assumptions that will make life easier and still get us a very close answer; in engineering it is important to not let perfection be the enemy of good-enough. Firstly, we will assume we are working with a lossless dielectric, meaning the vector describing this dielectric contains no real component ‘R’ and the loss tangent is 0°. Secondly, we will assume that our cable material (copper) is a perfect conductor and the vector describing it contains no imaginary component “ωj”. The basic principal is that we want to send a short pulse into a cable and use a visualization tool to examine the reflection. When a signal is incident to a cable, the signal does not travel to the end of the cable instantaneously. For starters, the finite speed of light (299,792,458 m/s) is the upper boundary, but as we will soon see, we will not even achieve these speeds; the reason is that the constants of relative permittivity and permeability for our cable's dielectric will slow down transmission speed or phase velocity, Vp. The signal will still be traveling at a significant fraction of the speed of light but keeping this value precise is key to the math coming out right. Phase velocity with our assumptions is defined as
Thus the time it will take for our incident signal to travel to the load can be calculated as
We will then expect to see a delay in our reflected signal corresponding to the results of these equations. We will get into more detailed calculations in a moment, for now let’s get building

Implementation

TDRs are expensive, but fortunately a rudimentary version can be easily assembled using a signal generator and an oscilloscope. In addition to these items you will need a set of BNC connectors and of course, a cable (can be to test it; you may also use a set of precision matched loads as seen in the image below, or you can use a potentiometer connected to the end of the cable, though this method introduces a bit of noise. The matched set I will be using consists of a 50, 75, and 93 Ohm loads.

 

One of the most readily available cable available is a piece of coaxial cable. Coaxial cable has been around for a very long time, but it has improved in construction significant over the years. Any coaxial cable will have a characteristic impedance partly determined by the diameter of the core cable that corresponds to its intended usage; they will range between 30 Ohms to 93 Ohms, with 30 ohms having the highest power handling capacity, and 77 ohms having the least signal attenuation. 50 Ohms is a common coaxial cable impedance as it is a compromise between power handling and signal loss. For this test I will use a long piece of coax cable, but I won’t say just yet how long it is or what its characteristic impedance is yet- that’s what we are here to find out! I will tell you that the manufacturer lists its relative permittivity as 1.2. For all coaxial dielectrics, the relative permeability is so close to 1 that we can just assume it is for our purposes ( accurate to within 0.00000001%). Substituting these values into our first equation we get
Vp = 273,671,819.7 m/s
or 10.7745 in/nS
which means our signal will propagate at about 91.29% of the speed of light, this percentage is known as the velocity factor or VF. Now we will hook up our gear and see what we get. Connect the signal generator to your scope with a T connector and the shortest cable you can find, this will help minimize error and the T will give you a place to connect the coaxial mystery cable- seen in the image as a white cable.

Open Circuit Configuration

After connecting one end of the coaxial cable to the T connector, leave the other end open; this first test will be an open circuit test. The open circuit test will give a very good representation of delay time and reflection coefficient. The frequency that you the the signal generator to is arbitrary, but it works best if you have a really fast rise time. In my case I am connecting to the 'Pulse Out' terminal that can be seen in the image below.
With the signal generator hooked up, trigger the scope and you should see an image like the one below:

Here we see our incident wave as the bottom step with the reflected wave as the top step. Because there is a finite transit time (calculated earlier) in the line, its input impedance will look like the characteristic impedance of the line for   so the line appears to be infinitely long until the pulse has had a chance to traverse the cable and reflect back to the input. the pulse begins as V0/2 because it is expecting the input impedance and load to be matched, creating a voltage divider. In the open circuit case the entire signal is reflected back towards the generator as can be seen using the equation for the reflection coefficient

giving us a coefficient of 1 for the load being infinite. After reflecting back, the signal jumps back up to V0, in this case about 4.5-5 volts. Let's take a closer look at what is going on: