PWM ou Pulse Width Modulation tem uma gama enorme de aplicações, usamos para controlar servos, definir o brilho de LEDs, potência de motores, regular tenção, efeitos sonoros e por ai vai.
Como de costume poderíamos ter chamado diretamente as funções da MRAA, mas daí o código fica muito mais confuso, uma pratica melhor é dividir o programa em múltiplos arquivos.
Primeiro o cabeçalho pwm.h que vai ser usado para incluir as funções C no código Go.
#ifndef __PWM_H__
#define __PWM_H__
void config(void);
void writePWM(float duty);
void stopPWM(void);
#endif
Em seguida o arquivo pwm.c que vai conter as funções em C para acessar o hardware. Nesse exemplo o LED esta conectado na porta digital 5.
#include <mraa.h>
#include "pwm.h"
#define PWM_PIN 5
mraa_pwm_context pwmPin; // guarda o contexto do terminal
void config(void) {
// 1: Inicia a biblioteca MRAA
mraa_init();
// 2: Inicia o terminal D5 para PWM
pwmPin = mraa_pwm_init(PWM_PIN);
// 3: Ajusta o período do PWM para 5000us ou 5ms
mraa_pwm_period_us(pwmPin, 5000);
// 4: Ativa PWM
mraa_pwm_enable(pwmPin, 1);
}
void writePWM(float duty) {
// 5: ajusta o ciclo de trabalho
mraa_pwm_write(pwmPin, duty);
}
void stopPWM(void) {
// 6: Para o PWM
mraa_pwm_enable(pwmPin, 0);
}
O fonte Golang pwm.go controla os tempos e faz o PWM funcionar. Para ficar um pouco mais elegante também interceptamos ^C. Como nesse post sobre Tratando sinais com Go.
package main
/*
#cgo LDFLAGS: -lmraa pwm.a
#include "pwm.h"
*/
import "C"
import (
"fmt"
"os"
"os/signal"
"time"
)
var duty float32 = 0.5 // guarda o ciclo de trabalho
var delta float32 = 1.0 // variação do ciclo de trabalho
func main() {
keeprunning := true
go func() {
sc := make(chan os.Signal, 1)
signal.Notify(sc, os.Interrupt)
// espera pelo sinal
<-sc
keeprunning = false
}()
C.config()
for keeprunning {
if duty >= 1 {
duty = 1 // Intencidade do LED
delta = -0.05 // Diminui a variação do ciclo de trabalho
} else if duty <= 0 {
duty = 0 // Intencidade do LED
delta = +0.05 // Aumenta a variação do ciclo de trabalho
}
// Ajusta o ciclo de trabalho
C.writePWM(C.float(duty))
time.Sleep(50000 * time.Microsecond)
duty = duty + delta
fmt.Printf("ciclo de trabalho: %f\r\n", duty)
}
C.writePWM(0)
C.stopPWM()
}
Por fim o Makefile para compilar tanto o código C quanto o programa em Go.
all:
gcc -c -Wall -O2 -lmraa pwm.c
ar rvs pwm.a pwm.o
go build pwm.go
clean:
rm -f pwm.o pwm.a pwm