1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-25 06:23:53 +01:00

Merge pull request #12523 from aabadie/pr/sys/arduino_pwm

sys/arduino: add implementation for analogWrite
This commit is contained in:
Gunar Schorcht 2019-11-21 15:08:10 +01:00 committed by GitHub
commit a05027cdba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 214 additions and 1 deletions

View File

@ -635,11 +635,16 @@ endif
ifneq (,$(filter arduino,$(USEMODULE)))
FEATURES_REQUIRED += arduino
FEATURES_OPTIONAL += arduino_pwm
FEATURES_OPTIONAL += periph_adc
FEATURES_REQUIRED += periph_gpio
USEMODULE += xtimer
endif
ifneq (,$(filter arduino_pwm,$(FEATURES_USED)))
FEATURES_REQUIRED += periph_pwm
endif
ifneq (,$(filter xtimer,$(USEMODULE)))
FEATURES_REQUIRED += periph_timer
USEMODULE += div

View File

@ -14,3 +14,4 @@ FEATURES_PROVIDED += periph_usbdev
# Various other features (if any)
FEATURES_PROVIDED += arduino
FEATURES_PROVIDED += arduino_pwm

View File

@ -22,6 +22,7 @@
#define ARDUINO_BOARD_H
#include "arduino_pinmap.h"
#include "periph/pwm.h"
#ifdef __cplusplus
extern "C" {
@ -70,6 +71,21 @@ static const adc_t arduino_analog_map[] = {
ARDUINO_A5,
};
/**
* @brief PWM frequency
*/
#define ARDUINO_PWM_FREQU (732U)
/**
* @brief List of PWM GPIO mappings
*/
static const arduino_pwm_t arduino_pwm_list[] = {
{ .pin = 3, .dev = PWM_DEV(0), .chan = 1 },
{ .pin = 4, .dev = PWM_DEV(0), .chan = 0 },
{ .pin = 8, .dev = PWM_DEV(1), .chan = 0 },
{ .pin = 9, .dev = PWM_DEV(1), .chan = 1 },
};
#ifdef __cplusplus
}
#endif

View File

@ -1,10 +1,11 @@
# Put defined MCU peripherals here (in alphabetical order)
FEATURES_PROVIDED += periph_adc
FEATURES_PROVIDED += periph_i2c
FEATURES_PROVIDED += periph_pwm
FEATURES_PROVIDED += periph_spi
FEATURES_PROVIDED += periph_timer
FEATURES_PROVIDED += periph_uart
# Various other features (if any)
FEATURES_PROVIDED += arduino
FEATURES_PROVIDED += periph_pwm
FEATURES_PROVIDED += arduino_pwm

View File

@ -23,6 +23,7 @@
#define ARDUINO_BOARD_H
#include "arduino_pinmap.h"
#include "periph/pwm.h"
#ifdef __cplusplus
extern "C" {
@ -141,6 +142,34 @@ static const adc_t arduino_analog_map[] = {
#endif
};
/**
* @brief PWM frequency
*/
#define ARDUINO_PWM_FREQU (490U)
/**
* @brief List of PWM GPIO mappings
*/
static const arduino_pwm_t arduino_pwm_list[] = {
#if defined(CPU_ATMEGA2560)
{ .pin = 13, .dev = PWM_DEV(0), .chan = 0 },
{ .pin = 4, .dev = PWM_DEV(0), .chan = 1 },
#elif defined(CPU_ATMEGA32U4)
{ .pin = 11, .dev = PWM_DEV(0), .chan = 0 },
{ .pin = 3, .dev = PWM_DEV(0), .chan = 1 },
#else /* CPU_ATMEGA328p */
{ .pin = 6, .dev = PWM_DEV(0), .chan = 0 },
{ .pin = 5, .dev = PWM_DEV(0), .chan = 1 },
#endif
#if defined(CPU_ATMEGA2560)
{ .pin = 10, .dev = PWM_DEV(1), .chan = 0 },
{ .pin = 9, .dev = PWM_DEV(1), .chan = 1 },
#else /* CPU_ATMEGA328p */
{ .pin = 11, .dev = PWM_DEV(1), .chan = 0 },
{ .pin = 3, .dev = PWM_DEV(1), .chan = 1 },
#endif
};
#ifdef __cplusplus
}
#endif

View File

@ -15,3 +15,4 @@ FEATURES_PROVIDED += periph_usbdev
# Various other features (if any)
FEATURES_PROVIDED += arduino
FEATURES_PROVIDED += arduino_pwm

View File

@ -22,6 +22,7 @@
#define ARDUINO_BOARD_H
#include "arduino_pinmap.h"
#include "periph/pwm.h"
#ifdef __cplusplus
extern "C" {
@ -68,6 +69,19 @@ static const adc_t arduino_analog_map[] = {
ARDUINO_A6,
};
/**
* @brief PWM frequency
*/
#define ARDUINO_PWM_FREQU (732U)
/**
* @brief List of PWM GPIO mappings
*/
static const arduino_pwm_t arduino_pwm_list[] = {
{ .pin = 2, .dev = PWM_DEV(0), .chan = 0 },
{ .pin = 3, .dev = PWM_DEV(0), .chan = 1 },
};
#ifdef __cplusplus
}
#endif

View File

@ -2,4 +2,7 @@ CPU_MODEL = samd21j18a
FEATURES_PROVIDED += periph_pwm
# Various other features (if any)
FEATURES_PROVIDED += arduino_pwm
include $(RIOTBOARD)/common/sodaq/Makefile.features

View File

@ -21,6 +21,7 @@
#include "periph/gpio.h"
#include "periph/adc.h"
#include "periph/pwm.h"
#ifdef __cplusplus
extern "C" {
@ -145,6 +146,22 @@ static const adc_t arduino_analog_map[] = {
ADC_LINE(14),
};
/**
* @brief PWM frequency
*/
#define ARDUINO_PWM_FREQU (732U)
/**
* @brief List of PWM GPIO mappings
*/
static const arduino_pwm_t arduino_pwm_list[] = {
{ .pin = 20, .dev = PWM_DEV(0), .chan = 0 },
{ .pin = 29, .dev = PWM_DEV(0), .chan = 1 },
{ .pin = 11, .dev = PWM_DEV(1), .chan = 0 },
{ .pin = 13, .dev = PWM_DEV(1), .chan = 1 },
{ .pin = 14, .dev = PWM_DEV(1), .chan = 2 },
};
#ifdef __cplusplus
}
#endif

View File

@ -103,6 +103,17 @@ typedef enum {
} pwm_mode_t;
#endif
#ifdef MODULE_ARDUINO
/**
* @brief RIOT GPIO mapping between Arduino pin, PWM device and channel
*/
typedef struct {
int pin; /**< Arduino pin number */
int dev; /**< PWM device index of pin */
int chan; /**< PWM channel index */
} arduino_pwm_t;
#endif
/**
* @brief Initialize a PWM device
*

View File

@ -22,6 +22,7 @@ extern "C" {
#include "xtimer.h"
#include "periph/gpio.h"
#include "periph/adc.h"
#include "periph/pwm.h"
}
#include "arduino.hpp"
@ -106,3 +107,55 @@ int analogRead(int arduino_pin)
return adc_value;
}
#endif
#if MODULE_PERIPH_PWM
static int _get_pwm_pin_idx(int pin)
{
for (uint8_t i = 0; i < ARRAY_SIZE(arduino_pwm_list); ++i) {
if (arduino_pwm_list[i].pin == pin) {
return i;
}
}
return -1;
}
void analogWrite(int pin, int value)
{
/*
* Bitfield for the state of the PWM devices.
* 0: Not initialized
* 1: Successfully initialized
*/
static uint8_t pwm_dev_state;
/* Clamp given value within bounds */
if (value < 0) {
value = 0;
}
if ((unsigned)value >= ARDUINO_PWM_STEPS) {
value = ARDUINO_PWM_STEPS - 1;
}
/* Check if the PWM pin is valid */
int pin_idx = _get_pwm_pin_idx(pin);
if (pin_idx == -1) {
/* Set to digital write if not a PWM pin */
pinMode(pin, OUTPUT);
return;
}
/* Initialization of given PWM pin */
if (!(pwm_dev_state & (1 << arduino_pwm_list[pin_idx].dev))) {
if (pwm_init(arduino_pwm_list[pin_idx].dev,
ARDUINO_PWM_MODE, ARDUINO_PWM_FREQU, ARDUINO_PWM_STEPS) == 0) {
return;
}
/* The PWM channel is initialized */
pwm_dev_state |= (1 << arduino_pwm_list[pin_idx].dev);
}
/* Write analog value */
pwm_set(arduino_pwm_list[pin_idx].dev, arduino_pwm_list[pin_idx].chan, value);
}
#endif /* MODULE_PERIPH_PWM */

View File

@ -122,5 +122,37 @@ unsigned long millis();
int analogRead(int pin);
#endif
#if MODULE_PERIPH_PWM || DOXYGEN
/**
* @brief PWM default frequency
*
* Can be overridden at board level in arduino_board.h.
*
* See table from https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/
* for reference values.
*/
#ifndef ARDUINO_PWM_FREQU
#define ARDUINO_PWM_FREQU (1000U)
#endif
/**
* @brief PWM mode
*/
#define ARDUINO_PWM_MODE PWM_LEFT
/**
* @brief PWM steps
*/
#define ARDUINO_PWM_STEPS (256U)
/**
* @brief Write an analog value to a pin
*
* @param[in] pin pin to write
* @param[in] value duty cycle value, between 0 and 255
*/
void analogWrite(int pin, int value);
#endif
#endif /* ARDUINO_HPP */
/** @} */

View File

@ -0,0 +1,15 @@
BOARD ?= arduino-zero
include ../Makefile.tests_common
LED_PIN ?= 3
USEMODULE += arduino
# Features used by Arduino analogRead/analogWrite functions are required
FEATURES_REQUIRED += arduino_pwm
FEATURES_REQUIRED += periph_adc
CFLAGS += -DLED_PIN=$(LED_PIN)
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,15 @@
// Example sketch given in analogWrite documentation
// https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/
int ledPin = LED_PIN; // LED connected to digital pin 3 by default
int analogPin = 1; // potentiometer connected to analog pin 1
int val = 0; // variable to store the read value
void setup() {
pinMode(ledPin, OUTPUT); // sets the pin as output
}
void loop() {
val = analogRead(analogPin); // read the input pin
analogWrite(ledPin, val / 4); // analogRead values go from 0 to 1023, analogWrite values from 0 to 255
}