3D PRINTING (PART 15)


Part 123456789101112, 13, 14, 15

First serious failure…
After exactly 4 years of regular use, I experienced the first failure which is due to an aged component.

Although Peek is a very strong material, it did not sustain any longer the thermal strength which it endured for years. This critical part is responsible for guiding the “cold” filament down to the heated nozzle so that a gradient from ambient temperature up to 210 ° and more is observed next to its threads. It is easy to give advises once you know the consequences of some flaws, however, this is a well known principle that parts must be massive around the temperature dissipation points… In this case, the designers did the opposite and this is breakage is surely not a big surprise.

As a result of this breakage, a leak of thawed PLA occurred and finally clogged the extruding stage creating no dramatic further damage. The lesson learned from this unfortunate event that no extra stress should be applied to this part and consequently avoid over-tightening of the nozzle to the insulator.

PS: In the middle of the Covid-19 crisis, I ordered a spare part one month ago which is still “somewhere” at La Poste. I managed to get an other one from Okaphone in the Netherlands which was brought by the the PostNL and everything went well, right in time. The Covid-19 crisis cannot explain the disorganization at La Poste which seems to be endemic since a long time; check this tracking records which is a pure example of non sense:

HTH

HC-05 Bluetooth module (Part 1)

Many web pages, posts and topics can be found on the web, however it took me quite some time to gather enough information to have a clear picture about the HC-0x series Bluetooth modules. Although they are outdated by low power BT modules, these modules are still a product of choice for building amazing applications snappy and on the cheap.

Update: Some more work on this type of modules proved that the situation is messier than I thought! In fact the HC-0x modules have been assembled in various manners using various firmware versions which makes the hobbyst’s life a little more complicated.

Anyway, this new series of posts dedicated to these Bluetooth modules, which will explain the way to program them and to use them. This is going to be a progressive approach, so please be patient if you look for the ultimate configuration or code !

Let’s start with some basics. HC-0x modules are easy to use Bluetooth SPP (Serial Port Protocol) modules, designed for transparent wireless serial connection setup. The HC-Ox series consist in a variety of modules as per the description below:

  • Industrial level: HC-03 (Master/Slave), HC-04 (Slave)
  • Civil level: HC-05 (Master/Slave), HC-06 (Slave)

Unless specified, I will deal with the HC-05 module which is the most versatile. Next is an illustration of the module itself, as it can be soldered on a main PCB for its real use (datasheet):

Most of the available assemblies featuring HC-05 and HC-06 modules look like the illustration below. Once again, unless specified, I will deal with the ZS-040 version of these modules fitted with the version 3.0-20170601 for which I found no documentation…

The pinout of the assembly is as follows (and printed at the back of the PCB):

  • State (dir.: out) : module state (3 V digital level). The level of the state goes high when the module is paired. The controller may read this signal is order send data only if the module is paired. You may also wire a LED through a resistor of few hundred ohms. Warning: the pin is inactive on some modules!
  • RXD (dir.: in) : Receive data from the controller (3 V digital level)
  • TXD (dir.: out) : Transmit data to the controller (3 V digital level)
  • GND (dir.: in): Ground
  • VCC (dir.: in): DC voltage (3.6 to 6 V)
  • EN (dir.: in): AT enabling mode (3 V digital level). The enable pin is also known as the key pin. In the case of the ZS-040 module, a high level on this pin has the same effect than pressing the push-button.

The board itself features a push button which enabled the AT mode and a LED which blinks according the module state, as described below:

  • Slow blink (1 Hz): AT mode, or command mode
  • Fast blink (2 Hz): Trying to pair
  • Bursts of two blinks (1Hz): Paired module, ready for communication

Back to the connections: keep in mind that the module can be fed with a DC voltage ranging from 3.6 to 6 V, but the digital pins must comply to a 0-3 V range. This is a pretty well known situation in the world of prototyping as more and more components require less and less power and consequently most often lower supply voltages. Three options can be applied:

The poor man translator using a voltage divider featuring a bridge of two resistors as shown below. This is a cheap solution. However, it draws a significant amount of power and should be use for prototyping only. Note that the TXD signal from the HC-05 is not boosted as a high signal (3.0 V) exceeds the trigger point of the input pin from a 5 V powered micro-controller. The enable pin shall be strapped on purpose to the 3.3 V from the Arduino platform. We will call this reference design the “basic platform” for later use.

The state of the art translator featuring a purpose built chip. Many chips cover the various needs which depend upon the type of communication. In the present case, a general purpose unidirectional translator will do the job, although the proposed TXB104D exceeds the needs as this is a bi-directional translator.

The in-between features popular discrete components. Each channel is fitted with a N-channel general purpose low signal MOSFET biased by two resistors. You may use some cheap of the shelves translator modules.

Next is an illustration of the poor-man’s design featuring a vintage Arduino Diecimila and an early Adafruit shield (Soon both collectors!).

Ultimately, one may want to build a fully versatile platform for programming and using the modules. Next is a suggestion of reference design that will be used in later posts and that we will recall as the “advanced platform”.

This version features a power supply control line which allows a full control of the module by the platform.

100 !

This picture illustrates my production of facial masks frames of the Easter week-end!
I never produced that many parts of the same sort using my brave old Vertex printer. So far, I experienced only 2 failures:
– 1 part was poorly printed showing gaps and lacks of filament. This problem did occur any more after a careful cleaning of the nozzle
– 1 part failed to stick properly to the bed. I readjusted the bed and this problem did not occur any more (although I do not use brim as it is not mandatory and the brim leaves sharp edges which may damage the gloves used my the medics and nurses).

After these 100 hours of printing, I checked the belts and adjusted on pulley, I cleaned the rods and applied clean grease again. That’s it.

HTH (Hope This Helps) has a double meaning this time: I really hope that theses mask help saving medics and nurses health.

By all means

By all means let’s stop the covid-19!

The heroes are those who stay home, in small flats, with nervous kids, noisy neighbors, low stocks of toilet paper and plenty kindness through the networks.

The action men and women keep the ball rolling, feed us, power our phones and care about us. They deserve as much help as we all can, if we can. Some bring them comfort in a noisy manner at 8:00 PM, some are sewing masks (that’s what my sister does!), some others print face shields for medics and professionals. A group of local makers set up an organisation in order to federate the good will of local owners of 3D printers. I volunteered immediately and here I am printing frames!

If you are living in Poitiers’s area France, you may contact this group through their Facebook account or by mail at [m a s q u e 3 d 8 6 @ g m a i l . c o m].

At a rate of 1 frame per hour, I expect to deliver at least a dozen units per day ;-). Next is a picture of one of the earliest product

Breaking news: Production line live !

https://meet.jit.si/let_s_stop_the_virus_by_all_means_3d_printing_of_face_masks

MicroHTR (Part 9)

Part 1, 2, 3, 4, 5, 6, 7, 8, 9

Here is an update of the MicroHTR (aka micro heater application) topic. Guy is a former marine pilot and his hobby is flying his touring-motor-glider wrote to me a very interesting message:
When flying close to cloudbase, the air becomes cold and the relative humidity becomes very high, this induces formation of ice in the carburetors; the so-called ” carburetor icing”.

In order to prevent carburetor icing and the resulting shut-down of the engine, i have installed electric heaters and a thermistor in each carburetor to heat up the carb’s body and prevent the icing. My intention is to install Brett Beaureguard’s PID control on an Arduino and control the power to the heaters via PWM for the two carburetors seperately ( so a PID loop running for each carburetor ). Interface is a 20×4 LCD with SPi and a rotary encoder KY-040. While reading and learning about the Arduino Atmega2560 programming , the LCD and rotary control I have come across your articles on the subject. ” … The following of the message contains some sort of a detailed description of the requirements.

This is typically the type of message that I like and that moves me forward to helping ;-). As a consequence, I reviewed my code (multiple libraries are involved in this project), and even reworked the PID library in order to take a interesting point into consideration.

The carburators may “start at a lower temperature than the setpoint and the PID kicks in right from the beginning to bring the carbs temp up to the setpoint. Without limiting the PWM they can both pull full Amperage until the setpoint is reached :Bad, this situation is to be avoided since power is limited. “

“The generator delivers 14 Amps at 12 Volts. The heaters are each 40 Watts, so 80 Watts pulls almost 7 Amps. This leaves only 7 Amps to recharge the battery ( 12 V -30 AH) and to power the avionics

Very important notice: This post describes an experimental setup, to be used at own risk and by no way approved for installation in Certified Aircraft

Starting with my earliest version of PlainPID , I tweaked this library so that the current version is now able to report the status of the controller: is it ramping to get to the set point or is it running under normal conditions ? In an application code, this feature translates as shown below:

 /* manage temperature */
float actualTemperature = TMP.getTemperature();
int16_t computedPwm = (int16_t)PID.getOutput(actualTemperature);
/* get stats from the PID */
stats_t stats;
PID.getStats(&stats);
/* manage output */
_pwm = computedPwm;
int16_t _currentMaxPwm = DEF_MAX_PWM;
if ((!stats.firstRampCompleted && (_maxPwmOnRamp == YES)) || (_maxPwmAlways == YES))
{
    _currentMaxPwm = _maxPwm;
}
if (_pwm > _currentMaxPwm)
{
    _pwm = _currentMaxPwm;
}		
/* set duty cycle to the driver */
PWM.dutyCycle(_pwm);

From the next plot (blue trace = set-point, red trace = actual temperature, green trace = PWM), we can clearly see the original ramp up using a limited power (half the full range in this case), then the PID controller uses as much power it needs. Then we have an illustration of how the PID controller behaves when the set-point is lowered and setback to the original set point. Once again, the power is limited during the ramp up. You may also recognize the efficient management of the overshoot.

Next is an illustration of the information displayed on a 16×2 LCD: the first line contains the actual temperature and the bracketed temperature set-points; the second line contains the actual PWM and the bracketed maximum allowed PWM which depends upon the choosen mode (Limited on ramps or limited always)

If necessary, the power may be limited always to the cost of broader temperature control as shown below .

Blog of the day

Thank you Guy for your very informative mail, the kind of request I love and pushes me hard to help. Part of the description of Guy’s project (Controlled heaters for deicing the carburetors from his touring-motor-glider) was a reference to Brett Beauregard’s blog.

Although I understand that nowadays Brett’s main preoccupation leads him to a lesser commitment to his blog, his great publications are still available and pleasured by those who play serious games. I had a quick glance at the PID subject that I incidentally covered at about (+/- 5 years!) the same time through the MicroHTR project.

Light sensor (Part 2)

Part 1, 2

In the previous part of this publication, I covered the subject of sensitivity. As for many sensor, the range is very broad and a simple configuration cannot help covering the whole range of light intensities.

As in the dated controllers, we might want to use a hand operated sensitivity selector. Although this option works, it is uncomfortable and we would prefer an auto-ranging device which will automatically select the best matching resistor, depending on the actual brightness.
The schematics below illustrate a simple and cheap design which will help covering light intensity from few Lux to hundreds of thousands Lux in four ranges.

The current Ipce flowing through the photo-transistor (U2) passes through the shunt resistor R5. The voltage generated across the resistor is buffered and amplified by U1 configured in non-inverting mode . The voltage divider is made of R4 and one of R1, R2 or R3 resistors which can be individually switched to ground thanks to the CD4066 quad analog switch. Each switch is controlled by a separate line which is wired to the pins from an arduino board. If none from the switches is closed, the amplifier is in unitary gain, so that this design features a 4 stages gain amplifier.
R5 is choosen so that the sensor will not saturate under strong lighting conditions. In my case, a resistor of 100 Ohm was appropriate for the TEPT5600 phototransistor. R1, R2 and R3 where choosen in order to obtain progressive gains of about x10, x100 and x1000. C1 filter the power supply from Arduino: 10 to 100 µF will do the job.

Next is an example of the code which drives this auto-ranging circuit. Starting from the highest sensitivity, the code reads the analog input. If the signal exceeds a predefined level, the code decrements the range counter, switches the next resistor and performs a new reading. The loop breaks when the analog reading lies in the allowed range or when the lowest sensitivity range is reached.

const uint16_t _autoGainTriggerLevel = 1008;
const uint8_t _stages = 4;
/* all switch driver pins must belong to the same port */
volatile uint8_t *_port = &PORTD;
const uint8_t _vStageCtrlMasks[] = {0, (1 << PIND2), (1 << PIND3), (1 << PIND4)};
const float _vGain[] = {1.0, 11.0, 101.0, 1001.0};
const float _responseFactor = 3.0;
const uint16_t _shuntResistor = 100;


void initSwitches(void)
{
    /* set swicthes driving pins */
	for (uint8_t i = 0; i < _stages; i++)
    {
        *(_port - 1) |= _vStageCtrlMasks[i]; 
    }
}


void setSwitch(uint8_t stage)
{
    /* clear swicthes */
 	for (uint8_t i = 0; i < _stages; i++)
    {
        *_port &= ~_vStageCtrlMasks[i]; 
    }
    /* set switch */
    *_port |= _vStageCtrlMasks[stage]; 
    delay(10);
}


void setup(void)
{
	/* initialize serial comm port */
	Serial.begin(38400); 
	/* initialize resistor switches */
    initSwitches();
}


void loop(void) 
{
    uint16_t adcCounts;
    /* find the best range starting for the most sensitive */
    uint8_t stage = _stages;
    do
    {
        stage -= 1;
        setSwitch(stage);
        adcCounts = analogRead(0);
        Serial.print(stage);
        Serial.print(" ; ");
        Serial.print(adcCounts);
        Serial.print(" ; ");
        Serial.print(_vGain[stage]);
        Serial.print(" ; ");
        Serial.print(adcCounts / _vGain[stage]);
        Serial.print(" ; ");
        float lightIntensity = _responseFactor * (float(adcCounts * 10e07) / float(_vGain[stage] * _shuntResistor * 1024 * 7));
        Serial.print(lightIntensity);
        Serial.println();      
    }
    while ((adcCounts > _autoGainTriggerLevel) && (stage > 0));
    Serial.println();      
    /* repeat after delay */
    delay(2000);
}

First we have a couple of declarations: global application related variables and hardware related variables. The response factor relates to the bin of the photo-transistor (as explained before). The _vGain vector contains the gains computed after R1, R2, R3 and R4 ( Gain=(1+(R4/Rx)) ). One function configures the pins wired to the switches and an other sets individual pins (after resetting all switches). The auto-ranging process lies in the loop function. It is almost self-explanatory. Data is printed so that it can be reconstructed as a scatter of x, y data points. Next is a plot of the brightness measured at my desk (on the side which is next to the window): today which is actually a cloudy day.

Light sensor (Part 1)

Part 1, 2

Sensing light is probably one of the most common sensing and probably one of the simplest measurement to start with.

Light sensors are used to detect light or brightness in a manner similar to the human eye. They are most commonly found in industrial lighting, consumer electronics, and automotive systems, where they allow settings to be adjusted automatically in response to changing ambient light conditions. By turning on, turning off, or adjusting features, ambient light sensors can conserve battery power and provide extra safety while eliminating the need for manual adjustments. (as per Vishay’s documentation)

Here is a list of various lighting conditions

ILLUMINANCE EXAMPLE
10-5 lux Light from Sirius star, the brightest star
10-4 lux Total starlight, overcast sky
0.002 lux Moonless clear night sky with airflow
0.01 lux Quarter moon
0.27 lux Full moon on a clear night
1 lux Full moon overhead at tropical latitudes
3.4 lux Dark limit of civil twilight under a clear sky
50 lux Family living room
80 lux Hallway / toilet
100 lux Very dark overcast day
320 to 500 lux Office lighting
400 lux Sunrise or sunset on a clear day
1000 luxOvercast day, typical TV studio lighting
10 000 to 25 000 lux Full daylight (not direct sun)
32000 to 130000 lux Direct sunlight

Sensing light is safe, simple and cheap. Many application notes describe the use of the dated LDR (Light Detecting Resistor), so that I will skip this sensor.

Some time ago I used the TEPT5600 ambient light sensor which is a photo-transistor. This versatile sensor can be used in various ways to address various applications exposed to variable brightness (Ev, in lux).

Photo-transistors are equivalent to photo-diodes used in conjunction with bipolar transistor amplifiers as shown below:

Typically, the current amplification, B factor, is between 100 and 1000. The active area of photo-transistor is usually about 0.5 x 0.5 mm2. The data of spectral responsiveness are equivalent to those of photo-diodes, but must be multiplied by the factor current amplification, B.
Next picture illustrates the linear luminescence to photo-current relationship:

Next is a cut view of the TEPT5600 sensor as per Vishay’s documentation

This image has an empty alt attribute; its file name is image-4.png

More about physicis and technolgy involved in phototransistors > here <

BINNING
…For a given irradiance, phototransistors may show lot-to-lot variability of the output current …. The lot-to-lot variability of photodiodes is significantly lower because it is caused only by the variability of the photosensitivity. Vishay offers its ambient light sensors with phototransistor output in binned groups. These groups cannot be ordered separately but each reel is marked with a label A, B, or C that will allow the user to select the appropriate load resistor to compensate for these wide tolerances. (as per Vishay’s documentation)

Next is a table showing the opto current flowing though the collector and the emitter (Ipce, in µA) biased with 5 V while exposed to a Ev of 20 lux.

Binned groupMin.Max.
TEPT5600 A2550.4
TEPT5600 B41.784
TEPT5600 C69.4140
TEPT5600 D113.4226.8

Next are a few exemples of use of the TEPT5600 sensor. For more information, read this publication.

Basic switch

The output goes high at Ev > 25 lux, Ipce: 10 μA, Vout: 2.0 V, Input Leakage Current: < 1 μA

Improved Switch featuring a level converter

Output Low at Ev > 10 lux, Ipce: 4 μA, Gate Threshold: 2.0 V, Input Leakage Current: < 1 μA

Basic Light Meter
As the photo-transistor acts as a current source directly proportional to the luminescence, a simple resistor in series with the sensor suffices.

EV: 10 lux to 1000 lux, Ipce: 4 μA to 400 μA, Vout: 16 mV to 1.6 V

Low Illuminance Light Meter

Ev: 0.1 to 10 lux, Ipce: 40 nA to 4 μA, Vout: 16 mV to 1.6 V . The output signal is amplified and buffered by an operational amplifier before the A/D converter

Next post on same topic

Power meter (Part 3)

Part 1, 2, 3

Once the hardware is ready, let’s have a look at the data and the software used to read these data.

The customer information can operate in two different modes:

  • historic: for compatibility reasons with older meters, this is the default mode.
  • standard: this new mode, available from the latest Linky meters. It is faster than the historic mode, and has more information, with a specific format. Just ask your provider for setting remotely this mode on your meter.

We will start with the historic mode which specifications are available from the technical documentation. The baud rate in this mode is 1200.
Each byte contains 1 start bit, 7 data bits, 1 parity bit and 1 stop bit.

Data is transferred as frames which are delimited by a STX character (0x02) and and a ETX character (0x03).

Each frame contains a set of data; each set of data is delimited by a LF character (0x10) and a CR character (0x0D). Each set of data contains one keyword (which length is variable and always less or equal 8 capital characters), one space, data (variable length of alpha numeric characters), one space and one checksum character as shown in the picture below

The checksum is computed with the keyword, a space and the data it self. It consists in adding all characters, applying a modulo 64 and adding the value 0x20. In this way, the checksum is printed in human readable character (from ‘space’ (0x20) to ‘_’ (0x5F)). Next is an example of code used to compute this checksum: (updated)

inline char computeChecksum(const char *aKeyword, const char *aData) 
{
	char sum = 0;
	while(*aKeyword) 
	{
		sum += *aKeyword;
		aKeyword += 1;
	}
	sum += 0x20;
	while(*aData) 
	{
		sum += *aData;
		aData += 1;
	}
	sum = ((sum & 0x3F) + 0x20);
	return (sum);
}

While talking about general purpose functions, let’s deal a bit with the parity check. The Linky power meter uses 7 bits data and a parity bit. This bit is set so that the ultimate parity of the data and the parity bits are even (even number of bits set to ‘1’). Although, faster algorithms exist, as we have kind of plenty of time (1200 baud) the classic method shall be used, as shown below

inline bool getParity(uint8_t byteValue) 
{ 
	bool parity = false; 
	while (byteValue) 
	{ 
		parity = !parity; 
		byteValue &= (byteValue - 1); 
	}      
	return (parity); 
} 

Reading a frame consists in listening to the incoming STX character, collecting consecutive bytes, checking their parity, extracting the 7 data bits, storing the byte in a vector and do that until the ETX occurs. An extra feature prevents the function from running for ever in case of lack of data for a certain amount of time (timeout).

bool readFrame
(
char *aFrame,
const uint16_t frameSize, 
const uint16_t timeOut,
const bool checkParity
)
{
	/* reset the content of the array */
	*aFrame = '\0';	
	bool waitForEtx = true;
	bool waitForStx = true;
	uint16_t bytesCount = 0;
	uint32_t startTime = millis();
	while (waitForStx) 
	{
		if (((millis() - startTime) > timeOut) || (bytesCount == frameSize))
		/* timeout and overflow protect */
		{
			return false;
		}
		/* if data is available in the incoming buffer */
		if (PwrMtrSerial.available())
		{			
			/* read the incoming data */
			char dataIn = PwrMtrSerial.read();
			if (checkParity && getParity(dataIn))
			/* check partity: true if odd, even (false) is expected */
			{
				return false;
			}
			/* mask the parity bit */
			dataIn &= 0x7F;
			/* parse incoming data */
			if (waitForEtx)
			{
				if (dataIn == 0x02)
				/* start of text */
				{
					/* change state */
					waitForEtx = false;
				}

			}
			else
			{
				if (dataIn == 0x03)
				/* end of text */
				{
					/* append termination character */
					*(aFrame + bytesCount) = '\0';	
					/* change state of readiness */
					waitForStx = false;
				}
				else 
				{
					/* record incoming character and increment pointer */
					*(aFrame + bytesCount) = dataIn;
					bytesCount += 1;
				}			
			}
		}
		else
		{
			delay(1);
		}
	}
	return (true);
}

Power meter (Part 2)

Part 1, 2, 3

I have been tumbling through the net, looking for interfaces to the TIC. So far, I found two types of reference designs:

  • The quick, dirty, safe but questionable design
  • The academic design

Most of the interfaces described on the web are very basic. They feature a single optocoupler and a biasing resistor.
The other option is much sophisticated and features a signal shaping stage. The design is far better, but requires TTL components and their power supply.

Credit

Once again, I decided to design one of mine, with my own constants: state of the art, compact, cheap and safe. This one features features a few cheap analog components arranged in these sections: power supply, demodulator and opto-switch.

Power supply: here we use a simple half wave rectifier (D1 and D3) biased through R2. The rectified signal is dampened by C1 and optionally regulated by D5. The output is a stable DC voltage.

Demodulator: once again we use a simple half wave rectifier (D4 and D2) biased through R1. The rectified signal is moderately dampened by C2 and applied through R3 to the base of Q1 acting as a switch. R3 discharges C2 in order to prevent tailing pulses.

Opto-switch: this is the easy part of the schematics ! The internal LED is biased through R5 and switched by Q1. Tx is switched to ground when a wave hits the input of the demodulator.

Warning: As you can see on the schematics, the interface has a separate ground from the Arduino, which is probably connected to your PC and thus to the mains ground. At all times the interface GND (labelled GNDA) must be floating versus GROUND.

Note: During the development satge, is used a reference signal generated with my RIGOL DG1022U DDS function generator, using the burst mode applied to a 50 kHz, 6 Vpp, 0V offset signal.

And the plots are screen shots from my good’ol RIGOL DS1052E tweeked to 100 Mhz

Both are electronic’s enthusiasts best friends ! Affordable, compact, reliable (except the encoders from the scope), accurate and pretty powerful.