Go com Intel Edison controlando saída PWM

Como usar PWM no Intel Edison com Go

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.

PWM - Pulse Width Modulation

PWD com MRAA

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 Go 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()
}

Makefile

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

comments powered by Disqus