PIDv1 and H-Bridge

I use this Library to get a steady compass course for a H-bridge 2 motor controled robot. I use FreeIMU the get the compas course stable, tiltcompnsated and calibrated.

The course 187 degrees is made as Setpoint and every 66ms Input of the current compass heding is Computed.
When the current heading is 181 degrees ( 181 – wanted 187 = -7 degrees ) the output is a value like 2.3

When the current heading is 194 degrees ( 194 – wanted 187 = +7 degrees ) the output is always o.00. I was supposed to get a negative value like -2.3

Is there somthing that I have misunderstod in the Setpoint/Input value and the whole use of PID??

// Before test, point the FreeIMU at a direction like 187 degrees.
// Pointing at 355 degrees can give result like 358….359….0…1
// Opps .. the compass has a 359.9 overflow
// Pointing at 187 degrees will give me the possibility to set 187 as
// wanted SetPoint and adjust the current heading +- 10 degrees
// without hiting the 359 overflow

#include <PID_v1.h>

#include <ADXL345.h>
#include <bma180.h>
#include <HMC58X3.h>
#include <ITG3200.h>
#include <MS561101BA.h>
#include <I2Cdev.h>
#include <MPU60X0.h>
#include <EEPROM.h>

//#define DEBUG
#include "DebugUtils.h"
#include "FreeIMU.h"
#include <Wire.h>
#include <SPI.h>

//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,1,1,1, DIRECT);

float ypr[3];

int sensVal;           // for raw sensor values 
float filterVal;       // this determines smoothness  - .0001 is max  1 is off (no smoothing)
float smoothedVal;     // this holds the last loop value just use a unique variable for every different sensor that needs smoothing

float setpoint;

// Set the default object
FreeIMU my3IMU = FreeIMU();

void setup() { 
  my3IMU.init(false); // the parameter enable or disable fast mode
  // Do 100 meassurement just to get a stable reading
  for (int i=0; i<100; i++) {
  float degree = ypr[0];
  if (degree < 0) degree += 360.0;
  smoothedVal =  smooth(degree, 0.5, smoothedVal);
  setpoint = smoothedVal; // Save the setpoint to a variable just to have it in the Serial.print
  Setpoint = smoothedVal; // Set the wanted direction to myPID

  //turn the PID on

void loop() {
  float degree = ypr[0];
  if (degree < 0) degree += 360.0;
  smoothedVal =  smooth(degree, 0.5, smoothedVal);
  Input = smoothedVal;
  Serial.print(smoothedVal - setpoint);
  delay (66); // Make one meassurement / 66ms. Could be smaller because the Serial takes alot of time

int smooth(int data, float filterVal, float smoothedVal){

  if (filterVal > 1){      // check to make sure param's are within range
    filterVal = .99;
  else if (filterVal <= 0){
    filterVal = 0;

  smoothedVal = (data * (1 - filterVal)) + (smoothedVal  *  filterVal);

  return (int)smoothedVal;

It sounds like you need to set the output limit to use negative numbers. By default it is 0 to 255 but can be changed using the SetOutputLimits method
See Arduino Playground - HomePage


SetOutpuLimit to -255 - 255 solves the problem.