This tutorial will show you how to modify the S5D9 Diagnostics Intelligence code to control an external servo from the board’s PMOD connector. With a few small modifications to the existing code, you’ll configure one of the S5D9 GPIO pins as a PWM output to control the servo. All of the Medium One workflows remain unchanged. This tutorial re-purposes the ‘blink’ widget to transmit servo position information to the board. The necessary changes are all made to the S5D9 application binary and must be made using e2 Studio.
-How to update an application binary on the S5D9 board
-S5D9 Diagnostics Intelligence Tutorial
-Familiarity with Renesas e2 Studio. This guide was written using the latest version 5.4.0.023
Required Software and Equipment:
-S5D9 IoT Fast Prototyping Kit
-Diagnostics Intelligence source code available here:
-Small 5V servo. This was written using an SM-S2309S which came with an old Arduino starter kit. Any 5V servo should be fine as long as the specifications are well known.
-1k resistor to connect between the servo control line and the S5D9 PWM output.
-Separate external 5V supply to power the servo. It should not be powered from the PMOD connector. This tutorial was created using an old HP variable DC supply. A 3 cell battery powerpack (1.6 V * 3 ~ 4.8V) should work fine as long as the batteries are new and the resulting voltage is within the servo specification. If your batteries are lower voltage, you could use a 4 cell pack, but make sure the voltage remains below the servo maximum spec.
Schematics for the fast prototyping board are available here:
In particular, here is the schematic for the PMOD connector:
PMOD pin 3 is connected to GPIO P2_2 on the S5D9. A little research in e2 Studio or in the S5D9 user’s manual (https://www.renesas.com/en-us/doc/products/renesas-synergy/doc/r01um0004eu0100-synergy-s5d9.pdf?key=c51808d9edd2b6b91e8f3264a809e472) reveals that this pin can be driven by GPT5 (General PWM Timer 5). Each GPT drives two pins, A and B. P2_2 is pin B which goes by the name GTIOCB. Because this pin is easy to access from the PMOD connector, you will configure it as a PWM output which controls the servo.
Every servo is different, but a quick survey of what’s available out there indicates that many servos require a square wave pulse every 20msec or less. The pulse width determines the servo position. Typically, a 1msec pulse is the minimum (zero degree) position, and a 2msec pulse is the maximum (180 degree) position. This servo has a more limited range of motion and a pulse of 1msec corresponds to zero degrees and 2msec corresponds to 90 degrees. There is a little room outside of this range, but the behavior gradually becomes erratic, so in this guide, we operate in the 0-90 degree range using pulses that vary in width from 1msec to 2msec. Your servo will be different, and a little experimentation will allow you to determine your usable range.
In this tutorial, you’ll configure the PWM output with a period of 10msec (100Hz) – well below the 20msec maximum requirement. We’ll configure the duty cycle in % so that a 10% duty cycle corresponds to a 1msec pulse (minimum servo position) and a 20% duty cycle corresponds to a 2msec pulse (maximum servo position). The code treats anything less than 10 as 10 and anything greater than 20 as 20. Of course these numbers can all be changed to suit your needs.
In order to transmit this information from the Medium One cloud to the board, you’ll use the ‘blink’ widget you already set up in the Intelligent Diagnostics tutorial. With that widget, you enter a number from 0 – 100 then press send. The red led then flashes the number of times you requested. That functionality remains, however you’ll increase the blink rate by a factor of 8 to make it obvious that you are running different code, and to speed up the time it takes to blink. That number also becomes the new PWM duty cycle in %, and when you press send, the servo position changes accordingly. From 0-10 the duty cycle is 10%. 14 results in a duty cycle of 14%, for example. Finally 20 or greater results in a 20% duty cycle. The LED blink count remains exactly the number you requested.
Below are some scope waveforms and the associated servo positions. Note the pulse widths and periods as measured on the scope. Disregard the Hz measurements in parentheses. Those are based on the time between markers (A) and (B) – not what we’re interested in here.
10% Duty Cycle
15% Duty Cycle
20% Duty Cycle
Build the Intelligent Diagnostics application binary from source.
Download the Intelligent Diagnostics source code here:
Unzip the download and put the resulting folder somewhere convenient. Note that there are two nested folders named diagnostics-intelligence-s5d9-1.2. Pull the inner one out and point to it from e2 Studio as shown below. First, you are going to build the Intelligent Diagnostics .srec binary file and test it to make sure e2 Studio is configured correctly.
After pointing to the Synergy license file (covered in other e2 Studio tutorials), the workbench should look as follows. Double click ‘configuration.xml’ to load all of the project information into the Synergy Perspective.
The ‘summary’ tab should look like this:
After clicking on the ‘Generate Project Content’ button in the upper right hand corner, build the project, and then locate the .srec file. The build will take a minute or two and will generate no errors or warnings.
Note the name of the file because it is different than the name of the .srec file that you download directly in the tutorial. It is the same file. It was just re-named. All that matters is that the name of the file match what you type into the update.txt file when you upload the application binary.
To finish this step, follow the Diagnostics Tutorial but use this newly created .srec file and confirm that everything works as expected. http://renesas-blog.mediumone.com/s5d9-diagnostic-intelligence-quick-start/
Configure the PWM timer driver
All of the LED blinking and response to cloud commands happens in the Net Thread, so that’s where you will add a gpt timer driver for the PWM output. Select the ‘Threads’ tab and then add a gpt timer driver.
Switch to the Synergy Perspective if you aren’t already there and highlight the new driver you just added which has the default name g_timer2. Don’t confuse this new driver with g_timer1 which was already in use by the project. After highlighting g_timer2, move to the ‘Properties’ tab in the lower left hand corner of the workbench and make the following changes:
Once you have entered those changes click on ‘Generate Project Content’ again to save everything. Now the driver you added will show up as ‘servo_timer.’
Configure GPIO Port 2, Pin 2 as PWM output controlled by timer gpt channel 5
First click on the ‘Pins’ tab and verify that the P202 configuration looks like this.
Next, click on the right arrow to change the Chip input/output, and disable SPI1 as shown.
Finally, enable GPT5 by making all of the following settings.
Now, ‘Generate Project Content’ and then build the project one more time to verify that there are no errors or warnings.
Modify the application code.
In the Intelligent Diagnostics application, all of the actions we care about in response to requests from the Medium One cloud happen in the net thread. Therefore, the code you will modify is in the file, net_thread_entry.c. Double click on the file to view the code.
This tutorial makes 3 small modifications to this code. Add the following code snippet (modification #1) after the line that reads, “int msglen;” in the void m1_callback(int type, char * topic, char * msg, int length) declaration.
//Begin DK Servo Tutorial Modification #1 //timer_size_t is a 32bit unsigned int typedef. It is the expected type //for the duty cycle parameter in the function dutyCycleSet used below timer_size_t servo_position = 10; //End DK Servo Tutorial Modification #1
Replace the entire " case ‘B’; " statement also in the void m1_callback(int type, char * topic, char * msg, int length) declaration with the following (modification #2)::
//Begin DK Servo Tutorial Modification #2 //The changes below leave the original blinking functionality alone, but the blink rate increases //The PWM functionality runs in parallel with the onboard LED blinking //GPT5 using Port2:Pin2 GTIOCB outputs the PWM signal. This is connected to //pin 3 on the PMOD connector //Inputting 10 blinks results in a pulse width of 1msec. Inputting 20 results in a pulse width of //2msec. This servo motor (SM-S2309S from Arduino starter kit) exhibits unpredictable behavior out of this //90 degree range. //This PWM could also be used to drive an LED if a servo is not available. In that case //the frequency should be increased from the 100Hz used here. case 'B': n_blinks = 0; sscanf(&p, "%d:%d", &temp, &n_blinks); servo_position = n_blinks; //Typecast of static volatile int n_blinks to unsigned 32 bit int //servo_position is OK here. There is no sign change for the small //numbers used. if (sscanf(&p, "%d:%d", &temp, &n_blinks) < 1) break; if (!temp) break; if (g_rtc0.p_api->open(g_rtc0.p_ctrl, g_rtc0.p_cfg) != SSP_SUCCESS) break; leds_to_toggle = (uint8_t)temp; // g_rtc0.p_api->periodicIrqRateSet(g_rtc0.p_ctrl, RTC_PERIODIC_IRQ_SELECT_1_SECOND); // Increase the blink frequency by a factor of 8 to indicate that this code is different // Commented out the line above and replaced it below. The enum is defined in r_rtc_api.h g_rtc0.p_api->periodicIrqRateSet(g_rtc0.p_ctrl, RTC_PERIODIC_IRQ_SELECT_1_DIV_BY_8_SECOND); g_rtc0.p_api->calendarCounterStart(g_rtc0.p_ctrl); g_rtc0.p_api->irqEnable(g_rtc0.p_ctrl, RTC_EVENT_PERIODIC_IRQ); //PWM duty cycle adjustment if (servo_position < 10) servo_position = 10; //Return to start position if < 10. 1msec pulse every 10 msec if (servo_position > 20) servo_position = 20; //Don't accept numbers larger than 20. 2msec pulse every 10msec servo_timer.p_api->dutyCycleSet(servo_timer.p_ctrl, servo_position, TIMER_PWM_UNIT_PERCENT, 1); break; //End DK Servo Tutorial Modification #2
Finally, paste this third snippet after the line “original_device.password = ‘\0’;” in the void net_thread_entry(void) declaration.
//Begin DK Servo Tutorial Modification #3 //The Default configuration is zero degrees with a 1msec pulse //The configurator starts the timer automatically //Open GPT5 below servo_timer.p_api->open(servo_timer.p_ctrl, servo_timer.p_cfg); //End DK Servo Tutorial Modification #3
When a number of blinks is received from the the Blink widget running on the Medium One cloud, the red LED blinks that number of times at 8 Hz. That number also becomes the new GPT5 PWM duty cycle. After pasting in the new code, build the project. There will now be 0 errors and 1 warning regarding a typecast which is not a problem in this application.
To verify that this step was completed correctly. Copy the new .srec file and upload it to the board following the procedure outlined in the application binary update tutorial here:
Everything should work as expected, but you’ll notice that the red LED blink rate is faster when you use the Blink widget. Verify this by sending instructions to blink 10 times.
Build the circuit.
Once everything is connected, you should be able to control the servo position from the cloud by entering 10-20 into the ‘Blink’ widget.
Next Steps: By changing a few workflows, we should be able to control the servo from a mobile phone. I’d also like to link the servo position to some sensor data.