Some values of digitalWrite on PWM-enabled pins break serial communication

Hi guys,

I have a simple setup where I try to control the duty cycle of an electromagnet via PWM. The circuit is essentially the one in the the schematic diagram attached (plus 4 hall sensors used only for reading). I am running the external power supply at 0.3A and 12V.

Now, when running the EM at duty cycles <=0.3 and >=0.8, everything works as expected. However, any other value immediately breaks serial communication, and basically makes the board unresponsive. If I try to re-upload the sketch, I then typically get a serial pipe broke or communication interrupted error.

I am not sure why this is the case. I have tried to use both pins 9 and 5, with identical results.

Has anyone suggestions on how to get the full duty cycle range to work? I am attaching my code, in case you can spot some obvious mistake. The code does also some basic serial command handling, so that the duty cycle can be set while running.

Many thanks in advance!

#include <stdarg.h>
#include <Arduino.h>
#include "RunningAverage.h"

const int transistorPin = 5;  // connected to the base of the transistor
float em_duty = 1.0;

int readline(int readch, char *buffer, int len)
{
 static int pos = 0;
 int rpos;

 if (readch > 0) {
   switch (readch) {
     case '\n': // Ignore new-lines
       break;
     case '\r': // Return on CR
       rpos = pos;
       pos = 0;  // Reset position index ready for next time
       return rpos;
     default:
       if (pos < len-1) {
         buffer[pos++] = readch;
         buffer[pos] = 0;
       }
   }
 }
 // No end of line has been found, so return -1.
 return -1;
}

void setup()
{
 Serial.begin(9600);
 // initialize the transistor pin as an output
 pinMode(transistorPin, OUTPUT);
 analogWrite(transistorPin, 255*em_duty);
}

void loop()
{

 static char buffer[20];
 if (readline(Serial.read(), buffer, 20) > 0) {
   char cmd_type = buffer[0];
   char* cmd_body_str = buffer;
   ++cmd_body_str; 
   ++cmd_body_str;
   if(cmd_type =='f')
   {
     // handle floating point messages
     float cmd_body = atof(cmd_body_str);
     Serial.println(cmd_body);
     if (cmd_body < 0)
       cmd_body = 0.0;
     else if(cmd_body > 1.0)
       cmd_body = 1.0;
     em_duty = cmd_body;
     analogWrite(transistorPin, 255*em_duty);
   }
   else if (cmd_type == 'c')
   {
     //handle directly char commands
     char* cmd_body = cmd_body_str;
   }
 }  
 delay(1);
}

schematics.png

Please use code tags (</> button on the toolbar) when you post code or warning/error messages. The reason is that the forum software can interpret parts of your code as markup, leading to confusion, wasted time, and a reduced chance for you to get help with your problem. This will also make it easier to read your code and to copy it to the IDE or editor. Using code tags and other important information is explained in the How to use this forum post. Please read it.

Wait, are you powering it through the 5v pin? With an electromagnet on the same power supply? Use separate supply for the inductive load, those will put a lot of noise on the power rails. You also need a diode across the terminals of the electromagnet, with the band towards the side that gets the positive voltage, to clamp the voltage generated when you turn it off.

Don't connect external 5v supply to 5v pin, you can damage the board by doing that while it's plugged into USB.

You may get better results just by separating the 5v for electromagnet from the Arduino 5v. Do keep ground connected.

@pert: Sorry, my bad. I have amended the code formatting.

@DrAzzy: I have the diode in already, as per schematic. However, disconnecting the 5V pin from the circuit and having only the external power supply did the job, thanks! Now I got the full dynamic range of the PWM to work. I am curious though: what is exactly happening with the 5V plugged in? Is the external supply adding noise on the power rails, which then causes the board to take some safety measures?

Now however I need a way to power my other sensors (4xhall sensors + 1 pressure sensors), as the external supply is directly attached to the coil. I have attached an image of my current setup, to clarify things. Previously, the sensors were all powered by the 5V Arduino pin (cable “A”, in figure). I understand you are suggesting to keep the two power supplies separated, but how could I effectively do that (pardon my ignorance :slight_smile: )? Or, do you know of a way to draw power from the external supply to power the whole setup?

Many thanks in advance!

Actually, I have figured out that I was plugging the cable (A) in prev. figure in the wrong Arduino pin-in. I plugged it in to the Vin pin, and I can now power everything (EM directly from external supply, 4 Hall Sensors and 1 force resistive sensor from the Vin pin).

I have noticed that for duty cycles bigger than 30% and smaller than 80%, the hall sensors readings become pretty noisy. Given the fact thgat the sensors are directly on top of the EM, I believe this has something o do with the PWM signal. Is this to be expected, or am I doing (again) something wrong :)?

Many thanks!