From f54e537d6494866a9261835427ec42081e5313ee Mon Sep 17 00:00:00 2001 From: Thomas Ingleby Date: Mon, 14 Apr 2014 11:05:52 +0100 Subject: [PATCH 1/5] pwm: Added API for PWM. * Added include line on main maa header to include PWM definitions. Signed-off-by: Thomas Ingleby --- api/maa.h | 1 + api/pwm.h | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 api/pwm.h diff --git a/api/maa.h b/api/maa.h index 824841e..f5ef581 100644 --- a/api/maa.h +++ b/api/maa.h @@ -27,6 +27,7 @@ #include "i2c.h" #include "i2cslave.h" #include "gpio.h" +#include "pwm.h" #define MAA_LIBRARY_VERSION 1 diff --git a/api/pwm.h b/api/pwm.h new file mode 100644 index 0000000..8262a1d --- /dev/null +++ b/api/pwm.h @@ -0,0 +1,128 @@ +/* + * Author: Thomas Ingleby + * + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include +#include + +namespace maa { + +/** A PWM object, used for interacting with PWM output. + * + * Example: + * @code + * // Set up PWM object then cycle percentage 0-100. + * + * #include "maa.h" + * + * PWM pwm(3); + * + * int main() { + * pwm.period_us(7968750i); //Max Galileo Rev D + * pwm.enable(1); + * + * float value = 0; + * while(1) { + * pwm.write(value); + * sleep(0.5); + * if(value == 1.0) { + * value = 0; + * } else { + * value = value +0.1; + * } + * } + * } + * @endcode + */ +class PWM { + +public: + + /** Create an PWM object + * + * @param pin The PWM pin to operate on. + */ + PWM(int pin); + + /** Set the ouput duty-cycle percentage, as a float + * + * @param percentage A floating-point value representing percentage of output. + * The value should lie between 0.0f (representing on 0%) and 1.0f + * Values above or below this range will be set at either 0.0f or 1.0f. + */ + void write(float percentage); + + /** Read the ouput duty-cycle percentage, as a float + * + * @return percentage A floating-point value representing percentage of output. + * The value should lie between 0.0f (representing on 0%) and 1.0f + * Values above or below this range will be set at either 0.0f or 1.0f. + */ + float read(); + + /** Set the PWM period as seconds represented in a float + * + * @param seconds Peroid represented as a float in seconds. + */ + void period(float seconds); + + /** Set period. Microseconds. + * @param ms microseconds for period. + */ + void period_ms(int ms); + + /** Set period. Nanoseconds + * @param ns nanoseconds as period. + */ + void perod_us(int us); + + /** Set pulsewidth, As represnted by seconds in a (float). + * @param seconds The duration of a pulse + */ + void pulsewidth(float seconds); + + /** Set pulsewidth. Microseconds + * @param ms microseconds for pulsewidth. + */ + void pulsewidth_ms(int ms); + + /** Set pulsewidth, nanoseconds. + * @param us nanoseconds for pulsewidth. + */ + void pulsewidth_us(int us); + + /** Set the enable status of the PWM pin. None zero will assume on with output being driven. + * and 0 will disable the output. + * @param enable enable status of pin + */ + void enable(int enable); + + /** Close and unexport the PWM pin. + */ + void close(); + +}; +} From cb92c892cf2d4d70f010f444641d4f518916b69e Mon Sep 17 00:00:00 2001 From: Thomas Ingleby Date: Mon, 14 Apr 2014 13:10:53 +0100 Subject: [PATCH 2/5] pwm: Refined API. Work towards functionality * Private functions added * Added to CMakeLists Signed-off-by: Thomas Ingleby --- api/pwm.h | 13 ++++- src/CMakeLists.txt | 1 + src/pwm/pwm.cxx | 136 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 src/pwm/pwm.cxx diff --git a/api/pwm.h b/api/pwm.h index 8262a1d..670809b 100644 --- a/api/pwm.h +++ b/api/pwm.h @@ -59,13 +59,22 @@ namespace maa { */ class PWM { +private: + int chipid, pin; + FILE *duty_fp; + + void write_period(int period); + void write_duty(int duty); + int setup_duty_fp(); + public: /** Create an PWM object * - * @param pin The PWM pin to operate on. + * @param chipid The chip in which the following pin is on. + * @param pin The PWM channel to operate on */ - PWM(int pin); + PWM(int chipid, int pin); /** Set the ouput duty-cycle percentage, as a float * diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f2babf1..c77b504 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,6 +9,7 @@ set (maa_LIB_SRCS ${PROJECT_SOURCE_DIR}/src/i2c/i2cslave.cxx ${PROJECT_SOURCE_DIR}/src/i2c/smbus.c ${PROJECT_SOURCE_DIR}/src/gpio/gpio.c + ${PROJECT_SOURCE_DIR}/src/pwm/pwm.cxx ) add_library (maa STATIC ${maa_LIB_SRCS}) diff --git a/src/pwm/pwm.cxx b/src/pwm/pwm.cxx new file mode 100644 index 0000000..a653d05 --- /dev/null +++ b/src/pwm/pwm.cxx @@ -0,0 +1,136 @@ +/* + * Author: Thomas Ingleby + * + * Copyright © 2014 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "pwm.h" + +using namespace maa; + +PWM::PWM(int chipin, int pinin) +{ + chipid = chipin; + pin = pinin; + + FILE *export_f; + char buffer[64]; + snprintf(buffer, 64, "/sys/class/pwm/pwmchip%d/export", chipid); + + if((export_f = fopen(buffer, "w")) == NULL) { + fprintf(stderr, "Failed to open export for writing!\n"); + } else { + fprintf(export_f, "%d", pin); + fclose(export_f); + } +} + +void +PWM::write(float percentage) +{ + //DO some writting +} + +float +PWM::read() +{ + //Do Something +} + +void +PWM::period(float seconds) +{ + //Do Something +} + +void +PWM::period_ms(int ms) +{ + //Do Something +} + +void +PWM::perod_us(int us) +{ + //Do Something +} + +void +PWM::pulsewidth(float seconds) +{ + //Do Something +} + +void +PWM::pulsewidth_ms(int ms) +{ + //Do Something +} + +void +PWM::pulsewidth_us(int us) +{ + //Do Something +} + +void +PWM::enable(int enable) +{ + //Do Something +} + +void +PWM::close() +{ + //Do Something +} + +void +PWM::write_period(int period) +{ + //Impossible +} + +void +PWM::write_duty(int duty) +{ + if(duty_fp == NULL) { + setup_duty_fp(); + } + fseek(duty_fp, SEEK_SET, 0); + fprintf(duty_fp, "%d", duty); + fseek(duty_fp, SEEK_SET, 0); +} + +int +PWM::setup_duty_fp() +{ + char bu[64]; + sprintf(bu, "/sys/class/pwm/pwmchip%d/pwm%d/duty_cycle", chipid, pin); + + if((duty_fp = fopen(bu, "r+b")) == NULL) { + return 1; + } else { + return 0; + } + return 1; +} From 5c2235dc0cfcb549881b62af468e82066a1c9b35 Mon Sep 17 00:00:00 2001 From: Thomas Ingleby Date: Mon, 14 Apr 2014 14:40:40 +0100 Subject: [PATCH 3/5] pwm: Completed functions: Signed-off-by: Thomas Ingleby --- api/pwm.h | 20 ++++++----- src/pwm/pwm.cxx | 90 +++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 90 insertions(+), 20 deletions(-) diff --git a/api/pwm.h b/api/pwm.h index 670809b..d57fc7a 100644 --- a/api/pwm.h +++ b/api/pwm.h @@ -66,6 +66,8 @@ private: void write_period(int period); void write_duty(int duty); int setup_duty_fp(); + int get_period(); + int get_duty(); public: @@ -98,28 +100,28 @@ public: */ void period(float seconds); - /** Set period. Microseconds. - * @param ms microseconds for period. + /** Set period. milli-oseconds. + * @param ms milli-seconds for period. */ void period_ms(int ms); - /** Set period. Nanoseconds - * @param ns nanoseconds as period. + /** Set period. microseconds + * @param ns microseconds as period. */ - void perod_us(int us); + void period_us(int us); /** Set pulsewidth, As represnted by seconds in a (float). * @param seconds The duration of a pulse */ void pulsewidth(float seconds); - /** Set pulsewidth. Microseconds - * @param ms microseconds for pulsewidth. + /** Set pulsewidth. Milliseconds + * @param ms milliseconds for pulsewidth. */ void pulsewidth_ms(int ms); - /** Set pulsewidth, nanoseconds. - * @param us nanoseconds for pulsewidth. + /** Set pulsewidth, microseconds. + * @param us microseconds for pulsewidth. */ void pulsewidth_us(int us); diff --git a/src/pwm/pwm.cxx b/src/pwm/pwm.cxx index a653d05..ff0c700 100644 --- a/src/pwm/pwm.cxx +++ b/src/pwm/pwm.cxx @@ -23,6 +23,8 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include + #include "pwm.h" using namespace maa; @@ -47,67 +49,102 @@ PWM::PWM(int chipin, int pinin) void PWM::write(float percentage) { - //DO some writting + write_duty(percentage*get_period()); } float PWM::read() { - //Do Something + return get_duty() / get_period(); } void PWM::period(float seconds) { - //Do Something + period_ms(seconds*1000); } void PWM::period_ms(int ms) { - //Do Something + period_us(ms*1000); } void -PWM::perod_us(int us) +PWM::period_us(int us) { - //Do Something + write_period(us*1000); } void PWM::pulsewidth(float seconds) { - //Do Something + pulsewidth_ms(seconds*1000); } void PWM::pulsewidth_ms(int ms) { - //Do Something + pulsewidth_us(ms*1000); } void PWM::pulsewidth_us(int us) { - //Do Something + write_duty(us*1000); } void PWM::enable(int enable) { + int status; + if(enable != 0) { + status = 1; + } else { + status = enable; + } + FILE *enable_f; + char bu[64]; + sprintf(bu, "/sys/class/pwm/pwmchip%d/pwm%d/enable", chipid, pin); + + if((enable_f = fopen(bu, "w")) == NULL) { + fprintf(stderr, "Failed to open export for writing!\n"); + } else { + fprintf(enable_f, "%d", status); + fclose(enable_f); + } //Do Something } void PWM::close() { - //Do Something + enable(0); + FILE *unexport_f; + char buffer[64]; + snprintf(buffer, 64, "/sys/class/pwm/pwmchip%d/unexport", chipid); + + if((unexport_f = fopen(buffer, "w")) == NULL) { + fprintf(stderr, "Failed to open unexport for writing!\n"); + } else { + fprintf(unexport_f, "%d", pin); + fclose(unexport_f); + } } void PWM::write_period(int period) { - //Impossible + FILE *period_f; + char bu[64]; + sprintf(bu, "/sys/class/pwm/pwmchip%d/pwm%d/period", chipid, pin); + + if((period_f = fopen(bu, "r+b")) == NULL) { + fprintf(stderr, "Failed to open period for writing!\n"); + } else { + fprintf(period_f, "%d", period); + fclose(period_f); + } } void @@ -134,3 +171,34 @@ PWM::setup_duty_fp() } return 1; } + +int +PWM::get_period() +{ + FILE *period_f; + char bu[64]; + char output[16]; + sprintf(bu, "/sys/class/pwm/pwmchip%d/pwm%d/period", chipid, pin); + + if((period_f = fopen(bu, "rb")) == NULL) { + fprintf(stderr, "Failed to open period for reading!\n"); + return 0; + } else { + fgets(output, 16, period_f); + fclose(period_f); + return atoi(output); + } +} + +int +PWM::get_duty() +{ + if(duty_fp == NULL) { + setup_duty_fp(); + } + char output[16]; + fseek(duty_fp, SEEK_SET, 0); + fgets(output, 16, duty_fp); + fseek(duty_fp, SEEK_SET, 0); + return atoi(output); +} From fbd863ca39fb8be294d65c6521774a4737ec5d29 Mon Sep 17 00:00:00 2001 From: Thomas Ingleby Date: Mon, 14 Apr 2014 16:55:19 +0100 Subject: [PATCH 4/5] pwm: Fully Functional. * C++ example included Signed-off-by: Thomas Ingleby --- examples/CMakeLists.txt | 2 ++ examples/cycle-pwm3.cpp | 24 ++++++++++++++++++++++++ src/pwm/pwm.cxx | 11 ++++++----- 3 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 examples/cycle-pwm3.cpp diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index a0db23a..430c18e 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,7 +1,9 @@ add_executable (readi2c readi2c.cpp) add_executable (hellomaa hellomaa.cpp) +add_executable (cycle-pwm3 cycle-pwm3.cpp) include_directories(${PROJECT_SOURCE_DIR}/api ${PROJECT_SOURCE_DIR}/include) target_link_libraries (hellomaa maa) target_link_libraries (readi2c maa) +target_link_libraries (cycle-pwm3 maa) diff --git a/examples/cycle-pwm3.cpp b/examples/cycle-pwm3.cpp new file mode 100644 index 0000000..a24dce9 --- /dev/null +++ b/examples/cycle-pwm3.cpp @@ -0,0 +1,24 @@ +#include + +#include "maa.h" + +int +main () +{ + maa::PWM pwm(0, 3); + pwm.period_us(200); + pwm.enable(1); + + float value = 0.0f; + + while(1) { + value = value + 0.01f; + pwm.write(value); + usleep(50000); + if (value >= 1.0f) { + value = 0.0f; + } + float output = pwm.read(); + } + return 0; +} diff --git a/src/pwm/pwm.cxx b/src/pwm/pwm.cxx index ff0c700..bd1fecd 100644 --- a/src/pwm/pwm.cxx +++ b/src/pwm/pwm.cxx @@ -43,6 +43,7 @@ PWM::PWM(int chipin, int pinin) } else { fprintf(export_f, "%d", pin); fclose(export_f); + setup_duty_fp(); } } @@ -55,7 +56,8 @@ PWM::write(float percentage) float PWM::read() { - return get_duty() / get_period(); + float output = get_duty() / (float) get_period(); + return output; } void @@ -153,9 +155,9 @@ PWM::write_duty(int duty) if(duty_fp == NULL) { setup_duty_fp(); } - fseek(duty_fp, SEEK_SET, 0); fprintf(duty_fp, "%d", duty); - fseek(duty_fp, SEEK_SET, 0); + rewind(duty_fp); + fflush(duty_fp); } int @@ -178,8 +180,8 @@ PWM::get_period() FILE *period_f; char bu[64]; char output[16]; - sprintf(bu, "/sys/class/pwm/pwmchip%d/pwm%d/period", chipid, pin); + sprintf(bu, "/sys/class/pwm/pwmchip%d/pwm%d/period", chipid, pin); if((period_f = fopen(bu, "rb")) == NULL) { fprintf(stderr, "Failed to open period for reading!\n"); return 0; @@ -197,7 +199,6 @@ PWM::get_duty() setup_duty_fp(); } char output[16]; - fseek(duty_fp, SEEK_SET, 0); fgets(output, 16, duty_fp); fseek(duty_fp, SEEK_SET, 0); return atoi(output); From 2d074c2ca38c1985eef68f15769e7f08ee772558 Mon Sep 17 00:00:00 2001 From: Thomas Ingleby Date: Mon, 14 Apr 2014 17:07:24 +0100 Subject: [PATCH 5/5] pwm: Added python example script Signed-off-by: Thomas Ingleby --- examples/python/cycle-pwm3.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 examples/python/cycle-pwm3.py diff --git a/examples/python/cycle-pwm3.py b/examples/python/cycle-pwm3.py new file mode 100644 index 0000000..e5f7a3b --- /dev/null +++ b/examples/python/cycle-pwm3.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 + +import pymaa as maa +import time + +x = maa.PWM(0,3) +x.enable(1); +x.period_us(20) +value= 0.0 + +while True: + x.write(value) + time.sleep(0.2) + value = value +0.01 + if value >= 1: + value = 0.0