Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KiCad schematics #2

Open
binomaiheu opened this issue Apr 5, 2024 · 9 comments
Open

KiCad schematics #2

binomaiheu opened this issue Apr 5, 2024 · 9 comments

Comments

@binomaiheu
Copy link

Dear Jolon,

Many thanks for this repository and for your elaborate bachelor thesis on developing an SDI-12 enabled IoT system. I'm currently on a similar quest actually ;). I am aware of the Arduino SDI12 library, which I'm currently testing, but I'm a little worried that it will interfere with the interrupts I'm using in my logger firmware, so i wanted to explore the hardware option for interfacing the UART with the SDI-12 bus as well. I did find the schematic on https://www.daycounter.com/Circuits/SDI-12/SDI-12-Interface.phtml which is also mentioned in your thesis, so i ordered some parts to test that, but I really like the way you are using the SN74LVC2G241 dual buffer to switch between TX & RX and wasn't aware of the need for the additional NAND gate on the TX line.

My electronics/KiCad skills are not the best, so I was wondering whether you would consider sharing the KiCad files for your SDI-12 interface ? I noticed the files under hardware/config_1 are fairly empty if I'm not mistaken. In any case a big thanks for your work !

Regards,
Bino (from Belgium)

@JolonB
Copy link
Owner

JolonB commented Apr 6, 2024

Hi Bino,

Thanks for getting in touch. It's great to hear that you had a look at my thesis and are interested in working with SDI-12. I'm more than happy to help!

I did probably get a bit ambitious with this repository and ended up not actually doing much work outside of the README, meaning config_1 (and all the other non-existent configurations) are pretty empty... whoops :/ This will just have to be motivation to update this repo.


Anyway, you mentioned the additional NAND gate on the Tx line. Are you referring to the one I've circled here?

image

This was added to implement the break condition (12ms high voltage (logic 0)) in the SDI-12 specification. Some UART buses might be able to do this, however, we were working with an ESP32 running MicroPython, which seemed to prevent us from doing this. This NAND gate exists as a workaround for the inability to implement a break. The FOut pin allows us to send the break by setting that pin for 12ms instead.

If you are using a microcontroller that can send a 12ms break on the Tx pin, you won't need to include this NAND gate; you'll be able to simplify it down to use just 3 pins (Tx, Rx, and direction).
If you don't know if your microcontroller's UART bus can send a 12ms break, it may even be possible to manually set the output register for the Tx pin to 5V for 12ms.

I believe the design at https://www.daycounter.com/Circuits/SDI-12/SDI-12-Interface.phtml should work. The only issue is that all of your Tx data will also be received by Rx, so you need to filter that out. That's why I used the dual buffer


I'll try to update some schematics tomorrow and I'll let you know when I've done it. If you want to, you could let me know what microcontroller you are using and I can give you some advice on how I would design the SDI-12 circuit or—if I have the time—I could upload a new design to this repo that will work for your microcontroller :)
The designs I show in my thesis and on this repo have been specifically made for ESP32 devices. I want to make designs for other devices, but haven't had the motivation to do so (until now!)

@JolonB
Copy link
Owner

JolonB commented Apr 7, 2024

Hey @binomaiheu

Since you mentioned Arduino, I've made a design that should work for an Arduino with 5V GPIO. This probably won't work with 3.3V GPIO, at least not reliably. You can find it here. Bear in mind, I haven't tested this

This design uses two components:

  • 74LVC1G04: 1-channel logic inverter. Needed to make the Rx and Tx lines operate exclusively of eachother.
  • 74LVC2G240: Inverting tri-state buffer.

There is also a large pull-down resistor. I'm not sure if it is needed. I never used one there; maybe some sensors have one built in?? I'll leave that up to you to test because I no longer have any SDI-12 sensors.

output.pdf

As you can see, this design does not need the NAND gate with the FOut input. As I mentioned in my previous comment, this is only needed if your UART bus cannot send the break signal. There are two ways this can be achieved: hardware support for break signals, or the ability to close and reopen a UART bus. It seems that Arduinos support the latter.

I'm basing the following code on this code from the RS485 library. You should be able to implement a break like so:

void sendSDI12Break() {
  Serial.flush();
  Serial.end();
  pinMode(txPin, OUTPUT);
  digitalWrite(txPin, LOW);  // remember, this will be inverted
  delay(12);  // minimum 12, could do slightly longer
  Serial.begin(1200, 7E1);  // 1200 baud; 1 start, 7 data, 1 even parity, and 1 stop bits
}

You'd also need to manage switching the direction yourself. I believe my code spent most of the time in the receive state and only switched to the transmit state when it was needed. (This is why I think the pull-down resistor (R1) could be needed. It just means Rx has a defined input)

@binomaiheu
Copy link
Author

Hi @JolonB !

Thanks a lot for taking the time for such an the elaborate response! We had the first proper spring weekend here in Belgium so haven't had the change to test much further, but as usual nice weather doesn't last very long here, so I'll get back to it tomorrow :). Normally the components i ordered to try the schematic on that daycounter website should arrive then as well.

I'm currently using both the Atmel1284p (as found on the Sodaq Mbili boards) and the SAMD21G (as on the Arduino MKR boards). Both using 3.3V level logic, so the original schematics should be ok. The final logger will be using a SAMD.

Good tip about the UART being able to send the break signal itself, I wouldn't know by heart, but I'll try that tomorrow, that would indeed save one GPIO line, thanks ! And thanks for uploading the schematic, great to get me going (have only done small things in kicad, but pretty sure i'll get the hang of it).

I'll keep you updated on my progress !

Cheers,
bino

@JolonB
Copy link
Owner

JolonB commented Apr 8, 2024

Hey @binomaiheu

There is something to be aware of when using the original designs with a 3.3V microcontroller. When I did the environmental monitoring project, I used NAND gates with TTL logic levels, which meant that 3.3V signals would be detected as a HIGH signal.

image

If you use a CMOS chip instead of TTL, the 3.3V signals will be undefined, so you have to be careful not to do that.

However, instead of using a TTL logic gate, I recommend using the new circuit I made but with a logic level shifter connected to the microcontroller to convert the 3.3V signal to 5V and vice versa. With the logic level shifter, it doesn't matter if you use a TTL or CMOS chip—they'll both work.

Keep me updated. I'm keen to hear how it goes.

Jolon

@binomaiheu
Copy link
Author

Hi Jolon,

I did some more testing with sending a break via the UART line. On the Arduino MKR (SAMD21 MCU), it didn't seem to work with the standard UART pins for Serial1 (13 & 14). For some reason the bus stopped working and the entire device froze after a few iterations (i setup a small firmware to print a character every 2 seconds, alternately preceeded by the 12 ms break and not. So I dug a little deeper and created an own hardware UART following https://docs.arduino.cc/tutorials/communication/SamdSercom/. That seemed to work, also defining the correct number of bits (7) and parity etc..

Source is below :

#include <Arduino.h>
#include <wiring_private.h>

int32_t n = 0;

Uart mySerial(&sercom3, 1, 0, SERCOM_RX_PAD_1, UART_TX_PAD_0); // Create the new UART instance assigning it to pin 1 and 0

// Attach the interrupt handler to the SERCOM
void SERCOM3_Handler()
{
  mySerial.IrqHandler();
}

void setup()
{
  Serial.begin(9600);
//  Serial1.begin(1200,  SERIAL_7E1);

  mySerial.begin(1200, SERIAL_7E1);

  pinPeripheral(1, PIO_SERCOM); //Assign RX function to pin 1
  pinPeripheral(0, PIO_SERCOM); //Assign TX function to pin 0
}

void sendSDI1Break()
{
  mySerial.flush();
  mySerial.end();

  pinPeripheral(0, PIO_OUTPUT);
  pinPeripheral(1, PIO_OUTPUT);

  digitalWrite(0, LOW);  // remember, this will be inverted
  delay(12);  // minimum 12, could do slightly longer

  pinPeripheral(1, PIO_SERCOM); //Assign RX function to pin 1
  pinPeripheral(0, PIO_SERCOM); //Assign TX function to pin 0

  mySerial.begin(1200, SERIAL_7E1);  // 1200 baud; 1 start, 7 data, 1 even parity, and 1 stop bits
}

void loop()
{
  
  Serial.println("--");
  if ( n % 2 ) sendSDI1Break();
  
  mySerial.print("g");

  n++;
  delay(2000);
}

So not entirely trivial, but at least this seems to work in adding the 12 ms break in software. However, on the scope I did notice that when I re-enable the UART in the sendSDI12break() routine, the TX line briefly goes back to it's (default) HIGH state for about 52 µs, which I suppose makes sense from a UART initialisation point of view, but I'm a little worried that it will mess up the SDI-12 communication. See traces below :

TEK00008

and with cursor :

TEK00009

So perhaps having the NAND gate around isn't such a bad idea for safety anyway.

My test-parts have arrived, but I was stupid enough to order them in packages which are completely beyond my soldering capabilities. So I'll have to revisit my component search. I'm thinking of just trying to layout the schematic on a pcb first (with the optional NAND gate via a jumper or so).

Regarding the logic level shifter, thanks for the tip. For the software implementation using the official arduino SDI-12 library, I was actually trying to use the TXB0108 (https://www.ti.com/product/TXB0108), but it did not seem to work, I assume for the reasons mentioned on https://e2e.ti.com/support/logic-group/logic/f/logic-forum/887817/txb0104-trying-to-adapt-voltage-levels-for-an-sdi-12-bus-with-a-3-3v-mcu

Cheers,
Bino

@binomaiheu
Copy link
Author

Hi Jolon,

I spent an afternoon & evening working my way through KicCad and component footprints. This is what I have made so far. Both the Electrical Rules and Design checkers are happy with the design. I'll re-check the schematic tomorrow thoroughly, as this was a first attempt of me getting to know KiCad a bit better.

Screenshot from 2024-04-10 21-00-34

and the PCB:

sdi12-breakout

@binomaiheu
Copy link
Author

Few minor updates:

  • I have added a jumper for which one end is connected to the 3.3V (logic HIGH at the input side of the NAND gate, so will always return the inverted output of TX), effectively bypassing the Fout to be able to play around with it.

  • Also, after some searching, I believe the following chip (https://www.ti.com/product/SN74AHCT1G00) could also be used for the NAND gate,that seems to be compatible with TTL logic (input > 2V for logic high, irrespective of Vcc), correct ? I could only find quad-input SN74LS00, and that seemd a bit overkill for our purposes :).

Cheers,
b.

@JolonB
Copy link
Owner

JolonB commented Apr 11, 2024

Hi @binomaiheu

  • That's a shame that disabling and re-enabling the UART bus didn't work. I had a similar issue when using ESP32, but I assume it must work on some hardware so it's always worth a try. It's good to see you found a software solution though. That little 52us pulse could be an issue in some situations, but I don't think it will be for SDI-12. See the image below for my understanding. The letter g sent as a 7-bit message is transmitted as 1110011 (the actual binary representation is 1100111, but it gets sent in reverse order). Before the payload, you have the start bit, and afterwards there is the stop bit (which is just 3.3V).
    image
    However, the thing to remember is that after sending the break for 12ms, the SDI-12 spec requires you to send "marking" for at least 8.33ms. Marking is 0V, which is the default state of the SDI-12 bus. This is the equivalent of 3.3V when uninverted, which is the default state of the UART bus (see where I'm going with this?). Basically, when the break finishes, re-enabling the UART bus forces it to transition from 0 to 3.3V. However, you want to send marking immediately afterwards, which is also 3.3V, so there is no 52us pulse. I hope I'm making sense here.
    All you need to do is adjust your code to include a >8.33ms marking (e.g. delay(10);) after the break. Then it'll look like this. I've drawn an orange line to indicate where the 52us pulse would be. As you can see, it is only an issue because you tried to send data too soon after the break. The marking essentially extends the 52us pulse to 8.33ms so you shouldn't see the pulse at all on your oscilloscope anymore. (Remember, this image has the logic inverted so it is flipped compared to the one above)
    image

  • The schematic looks right to me. But it's still a good idea to check it again :)

  • Yep! The SN74AHCT1G00 should work well. In fact, the datasheet even explicitly mentions that it can be used for it..
    image
    I did notice, however, that the chip is technically a CMOS chip and it mentions that there is higher current draw when using TTL levels, which might be a problem since the input from Tx will be 3.3V by default
    image
    It might be worth testing if that'll be an issue for you.
    The 74LS00 also mentions that it'll work.
    image
    I suppose it is up to you which one you choose. If you choose to continue with the 74LS00, apparently it's a good idea to connect the unused inputs to Vcc.

I won't say whether I think that sending the break with the UART pins or with the NAND gate is the better option, because I don't want to give you incorrect advice on something I haven't tested. The downsides of the UART solution is there could be issues that aren't obvious now (for example, the interrupt might affect something else). The downsides of the NAND gate is that there could be higher current draw, and there is the cost of an extra component.


I was stupid enough to order them in packages which are completely beyond my soldering capabilities

I did the same thing when working on SDI-12 4 years ago. I think it happens to everyone at least once 😅️

@binomaiheu
Copy link
Author

Hi Jolon,

To keep you updated, I checked the schematics & PCB with a colleague who has more experience with electronics than I do and integrated the 12V/5V and 3.3V onto the PCB as well along with the stuff we discussed above. I believe indeed you are right concerning the 8.33 ms marking, so it should be possible to use the UART and leave out the "FOut" via the NAND gate. But I included both options for testing.

I just ordered the PCB ... with the correct footprints ! (I hope), so I'm looking forward to the result. Will get back here when I receive my toys & have tested them !

Cheers,
b.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants