-
1Get your AWS account set up
Amazon Web Services (or AWS) is a massive suite of services, including cloud servers, databases, DNS, machine learning, even quantum computing! Plus the service that is especially interesting to us -- IoT. Go poke around on their front page, and you'll see just how many services they offer. It's truly mind-boggling.
While you're there, you can either create a new account, or you should be able to log in with your existing Amazon account credentials. Don't worry about costs yet -- AWS has their Free Tier which gives very reasonable limits you can use to try out their products. Some of these are limited to 12 months, including IoT, but it includes 250 000 MQTT messages per month, 3 devices (or "things"), 50 device commands per month (this includes device creation and remote management, which we won't be using), as well as 2 500 events per month (events are automatic reactions to messages that are sent from your things) and access to their graphing service. Pretty neat! If you plan to use it after 12 months, the prices are quite low, and there are other services besides AWS that are free -- but often they don't support TLS, and having the integration with other AWS services is nice.
The downside of AWS, especially for first-time users, is its inherent complexity. Many of their services are tied together, and they often offer confusingly similarly named services that do different things. AWS really is targeted at enterprise users -- but that doesn't mean hobbyists can't use it too! You just need to be prepared to approach things in a methodical way.
Side note: if you are joining AWS for the first time, be sure to check out the other services offered, especially the 12 months of a cloud server for free.
-
2Create your AWS IoT Thing
Now that you are logged in, head over to the AWS Management Console. At the top, click Services, and scroll down until you see Internet of Things on the right hand side. Click on IoT Core.
On the left hand side, click Manage, and then click Create in the upper right. Choose "Create a Single Thing" and then give it a name. You can safely ignore everything else on this page for now. Scroll down and click Next.
The next page shows certificate creation options. AWS IoT is only accessible via TLS, meaning we have to deal with private keys and certificates. If you were starting from scratch, this would be quite the speed bump, but luckily mbed and Cypress have provided excellent example code and libraries. Choose the top option, One-click Certificate Creation.
Super important note! The next page that shows up will only ever be shown once, as a security measure. Make sure to download all three files: certificate, public key, and private key. After you have downloaded them, click the Activate button.
Next is a super-important step that I skipped when I first started working on this project, and it caused me hours of headaches thinking something completely different was wrong. Click Done, which should take you to the details page for your newly created Thing. Click the grey back arrow in the upper left hand corner.
Now we need to create a policy and attach it to the thing we just created (remember when I warned you about how AWS is targeted for enterprise usage? Now you can see I wasn't kidding!). On the main IoT Core page, click Secure in the left-hand menu. This will open a sub-menu where you can see the certificate we just created. Below Certificates, click on Policies, and then click on Create in the upper right. Give it a name like "Open". In the statements section below the name, enter iot:* as the action, and * as the resource ARN. Check off Allow, and then click Create at the bottom right.
Now go back to the Certificates sub-menu, and click the three dots in the certificate box. Choose Attach Policy, check off the policy we just created, and click Attach! Now we are finally ready to cloud surf.
-
3Getting set up with mbed
mbed is a service offered by ARM. It's essentially an online IDE with support for many different microcontrollers that use ARM cores. The Cypress boards I am using have landing pages at https://os.mbed.com/platforms/CY8CKIT-062-WiFi-BT/ and https://os.mbed.com/platforms/CY8CPROTO-062-4343W/ which give some info about the features of these boards, as well as links to schematics and other board data. Cypress also has a bunch of code examples on mbed, including the one that I based my code off of, which is located here: https://os.mbed.com/teams/Cypress/code/mbed-os-example-aws-iot-client/
If you click the Import into Compiler button in the top left, it will copy that code into your mbed workspace. This example contains two different programs, one for publishing and one for subscribing. For this example we will only be publishing, and the compiler seemed to get confused with both folders present, so I deleted the subscriber folder.
Note: If you end up using the mbed command-line tools instead, it's not necessary to delete the subscriber folder. Simply issue the command "mbed config root ." It's also helpful to set the board you are using, which you can do with "mbed target cy8cproto_062_4343w" or "mbed target cy8ckit_062_wifi_bt". Note these names use underscores, not hyphens!
The first and most critical step to getting this example working is to set up your AWS credentials in the aws_config.h header file. I will go through each item in this file, and explain exactly what you need to put in each.
- AWSIOT_ENDPOINT_ADDRESS: This is the actual address that your thing will communicate with. You can find it in the IoT panel by clicking on Manage, then clicking on your Thing. Select Interact from the left-hand menu, and then copy and paste the URL under the HTTPS heading. It will end in .amazonaws.com
- AWSIOT_THING_NAME: This is the human-readable name you gave your thing when creating it back in step 2. I just called mine "Cypress" but just make sure it matches whatever name you gave it in AWS.
- AWSIOT_TOPIC: This is the name of the topic it will publish to. This can be anything you like, as long as you remember it!
- const char SSL_CLIENTCERT_PEM: This is the certificate file that we downloaded earlier. It needs to be formatted in a particular manner, as shown in the example section. Copy and paste the entire file between the quotes, and then format it as shown. You will need to put quotes around each line, as well as add \n to the end of each line. You also need a backslash as the last character on the line. I will include a redacted screenshot of what mine look like.
- const char SSL_CLIENTKEY_PEM: This is the private key file that we downloaded. It needs to be formatted exactly as above.
- const char SSL_CA_PEM: This is the Amazon AWS root certificate, available at https://www.amazontrust.com/repository/AmazonRootCA1.pem. Make sure to copy and paste the entire thing, and format it the same was as the other two.
The last thing we need to do before launching the example code is adding our Wi-Fi credentials to the mbed_app.json file. Replace the SSID and password with your details, making sure to leave the escaped quotes in place. It should look like this:
{ "target_overrides": { "*": { "platform.stdio-convert-newlines": true, "target.network-default-interface-type": "WIFI", "nsapi.default-wifi-security": "WPA_WPA2", "nsapi.default-wifi-ssid": "\"MyNetwork\"", "nsapi.default-wifi-password": "\"password123\"", "platform.stdio-baud-rate": 115200 } } }
With all that inserted, you should be able to compile the example code. This will create a .hex file that will be automatically downloaded. Save it somewhere, and then plug your board in to your PC. If your board does not show up as a USB drive, read the instructions below on how to get your board's firmware updated. Otherwise, drag the downloaded .hex file into the USB drive that appears, and the firmware will self-program.
Cypress have released a tool to update the firmware on their boards. By default, these boards come with KitProg2 installed, but we need KitProg3. Download the latest release from their GitHub repository depending on which OS you run, and unzip it. Connect your board, and navigate to the bin/ folder inside the extracted folder. Run
fw-loader(.exe) --update-kp3 all
and allow it to finish. Once this is complete, you can either push the button on the programmer portion of the board labelled "MODE" to get it into DAPLINK mode. Or, you can simply run
fw-loader(.exe) --mode kp3-daplink
and it should appear as a USB drive. From now on, all you need to do to update the code running is simply drag and drop the downloaded .hex file into the USB drive. It will automatically self-program and then delete the .hex from the USB interface.
-
4Check to make sure MQTT is working
In your AWS IoT main menu, click on Test at the bottom of the left-hand menu. Under Subscribe to a Topic, enter the topic name you set in the aws_config.h file earlier. Then click on subscribe. If everything is running correctly, you will see the string HELLO published every 5 seconds. If it is not working, use a terminal program like minicom on Linux or RealTerm on Windows to connect to the serial port. Press the reset button and watch for the output.
Important note: If, after programming, the LED on your board blinks 4 times quickly, 4 times slowly in a loop, there was an issue with the file that was programmed. I had this happen with the downloaded hex files about 50% of the time and was never able to figure out why. In this case, you can use the mbed command-line compiler to do the work. In many ways I actually prefer using this. Getting it set up is beyond the scope of this example, but the instructions can be found here.
-
5Modify the code to send something more interesting!
Well, we got MQTT working, but now what? We want to send something more interesting than just HELLO. We want to send some actual data. Up to this point, you have been able to use either of the Cypress PSoC 6 dev boards (the CY8CPROTO-062-4343W or the CY8CKIT-062-WIFI-BT), but each board has different peripherals.
The Pioneer kit comes with the LCD shield, upon which is an ambient light sensor. This sensor is connected to an analog input pin on the PSoC, corresponding to A1. We will use the value from this light sensor as our data! I happened to have a breakout board with the exact same light sensor (the TEMT6000), which I connected to the CY8CPROTO. I ran into issues trying to use the on-board thermistor for temperature data on the CY8CPROTO, so I ended up using the external sensor for this example. You can easily connect any analog sensor to the same pins in this example, or connect an I2C sensor if you modify the code.
The mbed libraries will feel familiar to anyone who has used Arduino before. The abstraction layer between the peripherals and your code is very well-built, making it a snap to add new interfaces to sensors. For our example, the TEMT6000 outputs an analog signal. On the CY8CPROTO, I connected the analog out to P10_2 (after removing R37 on the back of the thermistor/mic board -- you could just snap it off, or find an unused analog input). On the CY8CKIT, the TEMT6000 is connected to P10_0, which has been defined as A0. For some reason the CY8CPROTO did not have these same "friendly" pin names. So, we simply modify publisher.c and add in our new AnalogIn:
AnalogIn analog(P10_2); // change to A0 or P10_0 on CY8CKIT float rawSensorValue = 0, scaledSensorValue = 0; float lux = 0; char *outputString = (char *)malloc(sizeof(char) * 15); while(1) { rawSensorValue = analog; // read the analog input, convert to volts APP_INFO(("raw input is %f\r\nscaled by VDD %f\r\n", rawSensorValue, rawSensorValue*VDD)); scaledSensorValue = (rawSensorValue * VDD) * 1000.0; // scaled to 3.3V, multiply by 1000 to get microamps lux = scaledSensorValue * 2.0; // convert to lux (2 * microamps) APP_INFO(("calculated luminance is %f lux\r\n", lux)); sprintf(outputString, "%02f", lux); // convert to a string, with leading 0 if necessary, and 2 digits after the decimal point. publish_params.QoS = AWS_QOS_ATMOST_ONCE; result = client->publish( AWSIOT_TOPIC, outputString, strlen(outputString), publish_params ); if ( result != CY_RSLT_SUCCESS ) { APP_INFO(( "publish to topic failed\r\n" )); if( client != NULL ) { delete client; client = NULL; } return 1; } APP_INFO(( "Published to topic successfully\r\n" )); wait_us( AWSIOT_TIMEOUT_IN_USEC * 60 ); // wait a minute between publishing }
The AnalogIn class we have used is very easy to work with. Simply read from it, and it automatically samples the ADC and returns a value between 0 and 1, where 0 is GND and 1 is VDD. In our case, VDD is 3.3V. I added a #define near the top of the file to make VDD equal to 3.3.
The voltage input we get needs to be scaled. First, we multiply by 3.3 to get the actual voltage input, and then we multiply by 1000, which gives us the microamps the sensor is allowing through (relative to the light input). Then we multiply this by 2, which the TEMT6000 datasheet tells us is the relationship between microamps and lux, and voila! We have our light value in lux.
To send this to the AWS server, we need to convert our floating point value into a string. So, we use malloc() to create a 15 byte long buffer, and sprintf() to convert the floating point into string form, using the normal printf() modifiers.
Then, we just need to modify the actual publish line by replacing AWSIOT_MESSAGE and strlen(AWSIOT_MESSAGE) with outputString and strlen(outputString) respectively. This code should build and generate a .hex file, which you can then copy into the DAPLINK drive.
Open a terminal at 115200 baud, pointing at /dev/ttyACM0 on Linux, and whichever COM port was assigned on Windows. You should see it connect to your Wi-Fi, connect to AWS, and then start printing the lux values every 5 seconds.
If you go to the AWS Test interface from the last step, you should now see your lux values being logged to the topic you chose! Awesome! We now have an IoT device logging data to the cloud!
If you get errors, double-check the formatting of your certificates and keys. The error codes printed to the terminal are often helpful. I had forgotten to attach the policy I created to my certificate, which ended up taking me awhile to figure out! I have also included my full copy of publisher.cpp in the files section of this project.
-
6Where to go from here?
Next steps you could take:
- Use another kit to subscribe to that same topic, and take some action based upon the lux value
- Connect a different sensor, and log different/more relevant data for your application
- Set up Bluetooth, and communicate with an Android phone to get GPS data (NMEA strings)
- Use the touch interface and LCD screen on the CY8KIT to create a cloud data display system
Basically, you can do just about any cloud-related thing with these boards. The PSoC 6 is absurdly flexible, with a huge number of peripherals, dual CPUs, and excellent low-power performance. The CY8KIT has a battery connector and charge circuitry on board to charge it, making wireless applications easier to develop and debug.
If you run into issues with this example, let me know in the comments below, or feel free to message me directly here on Hackaday! I also hang out on Freenode IRC, so you can catch me on there as MrAureliusR. I would love to hear about any projects you create with these boards!
I wanted to also quickly highlight the excellent quick start guide that comes with the CY8KIT-062-WIFI-BT. It has this awesome diagram showing every component on the board, and what it is! I wish more dev boards would come with diagrams like this in the box. Note that component 27, the ferroelectric RAM, actually is populated, at least on the version of the board I got. This is super awesome, because FRAM is a really neat technology, and you don't see it on many dev boards.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.