diff --git a/code-snippets/client/soil_sensor_sentec/main.cpp b/code-snippets/client/soil_sensor_sentec/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..aac6bac8b4d4084b3ead90eb19f85584560e25ce
--- /dev/null
+++ b/code-snippets/client/soil_sensor_sentec/main.cpp
@@ -0,0 +1,172 @@
+#include "Arduino.h"
+#include <SoftwareSerial.h>    // RS485 setup with ESP32
+
+// THIS SNIPPET APPLIES ONLY TO SOIL SENSORS!!!
+// Other RS485 sensors will have to use other commands as well
+
+/* 
+TODO It would be better to have one class for ALL RS485 sensors since they
+all send/receive data in the same way, and then specific classes for individual
+sensors (soil moisture, rain gauge, radiation) with sensor-specific commands.
+*/
+
+/* TODO The address of the sensor (first byte of the query frame) is
+hard-coded now - it should be passed as an argument instead since
+we have three sensors with different addresses now. 
+The last two values of the queryFrame don't matter, they will be changed
+later to confrom to the CRC check.
+The length of the sent message will always be 8 bytes.
+*/
+const byte bufferSize = 6;
+byte queryFrame[bufferSize + 2] = {0x05, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00};
+// 0: sensor address (differs per sensor)
+// 1: function code (03 = get data for all sensors) 
+// 2+3: register start (0x00 0x00 for all sensors)
+// 4+5: register length (0x01 for radiation+rain, 0x02 for soil)
+// 6+7: CRC check (calculated later per sensor and message)
+
+/*
+TODO the length of the answer frame should NOT be hard-coded, it's going to be either
+8 bytes (radiation, rain) or 9 bytes (soil)
+*/
+byte answerFrame[9];
+
+
+#define RXPin        4  // Serial Receive pin
+#define TXPin        5  // Serial Transmit pin
+ 
+// RS485 control
+// this will change once we get different hardware
+#define SERIAL_COMMUNICATION_CONTROL_PIN 6 // Transmission set pin
+#define RS485_TX_PIN_VALUE HIGH
+#define RS485_RX_PIN_VALUE LOW
+ 
+SoftwareSerial RS485Serial(RXPin, TXPin); // RX, TX
+ 
+
+unsigned int calculateCRC()
+// TODO pass the query/answer frame into this and return the changed frame
+//     to make things neater maybe? Apparently there are also libraries for this...
+
+// Change the last two bytes of the queryFrame to conform to a CRC check
+// Yes, this is necessary. No, I don't know exactly what it does.
+{
+  unsigned int tmp1, tmp2, flag;
+  tmp1 = 0xFFFF;
+  for (unsigned char i = 0; i < bufferSize; i++)
+  {
+    tmp1 = tmp1 ^ queryFrame[i];
+    for (unsigned char j = 1; j <= 8; j++)
+    {
+      flag = tmp1 & 0x0001;
+      tmp1 >>= 1;
+      if (flag)
+        tmp1 ^= 0xA001;
+    }
+  }
+
+  // Reverse byte order. 
+  tmp2 = tmp1 >> 8;
+  tmp1 = (tmp1 << 8) | tmp2;
+  tmp1 &= 0xFFFF;
+  queryFrame[bufferSize + 1] = tmp1;
+  queryFrame[bufferSize] = tmp1 >> 8;
+
+    return tmp1; // the returned value is already swapped - CRC_L byte is first & CRC_H byte is last
+}
+
+
+void setup()  {
+  // configure the pin to be output only
+  pinMode(SERIAL_COMMUNICATION_CONTROL_PIN, OUTPUT);
+  
+  // Set data rates: Serial baud rate has to be WAY HIGHER than RS485Serial!
+  Serial.begin(115200);
+  RS485Serial.begin(4800);
+ 
+  // Calculate the check bytes: changes the last two bytes of queryFrame
+  calculateCRC(); 
+
+  // Print the message that's sent to the sensor
+  Serial.println("Query bytes:");
+  for (int i = 0; i < sizeof(queryFrame); i++){
+    Serial.print(queryFrame[i], HEX);
+    Serial.print(" ");
+  } 
+  Serial.println();
+  Serial.println();
+}
+
+
+void loop() {
+  // Index for the readout while loop
+  int idx = 0;
+  int byteReceived;
+
+  float vwc;  // volumetric waetr content, i.e. soil moisture
+  float temp;  // soil temperature
+
+ 
+  // Initialize the transmitter
+  Serial.println("Sending data");
+  digitalWrite(SERIAL_COMMUNICATION_CONTROL_PIN, RS485_TX_PIN_VALUE); 
+  // Send message: request a reading from the sensor
+  RS485Serial.write(queryFrame, sizeof(queryFrame)); 
+
+  // Initialize the receiver
+  digitalWrite(SERIAL_COMMUNICATION_CONTROL_PIN, RS485_RX_PIN_VALUE); 
+
+  // Read out data: this works ONLY when the Serial baud rate >> RS485Serial baud rate
+  // TODO add some logic for when there's no data and we get a timeout
+  while (idx < sizeof(answerFrame)) { 
+    if(RS485Serial.available()) {
+        byteReceived = RS485Serial.read();
+        // Serial.println(byteReceived, HEX);
+        answerFrame[idx] = byteReceived;
+        idx++;
+    }
+  }
+    
+  // Print out answer bytes
+  /*
+  Byte 0: sensor address
+  Byte 1: Function code
+  Byte 2: valid bytes (2 valid bytes per read variable)
+  Byte 3+4: 1st read variable
+  Byte 5+6: 2nd read variable
+  Byte n-1 + n: CRC checks
+  */
+  Serial.println(" ");
+  Serial.println("Answer bytes:");
+  for(int i = 0; i < sizeof(answerFrame); i++){
+    Serial.print(answerFrame[i], HEX);
+    Serial.print(" ");
+  }
+
+  Serial.println();
+  Serial.println();
+
+  Serial.print("Sensor number: "); 
+  Serial.println(answerFrame[0], HEX);
+
+  Serial.print("Number of read variables: ");
+  Serial.println(answerFrame[2] / 2, DEC);
+
+  vwc = word(answerFrame[3], answerFrame[4]);  // word = 2 bytes, high byte first
+  Serial.print("vwc: ");
+  Serial.println(vwc / 10 , DEC);
+
+  temp = word(answerFrame[5], answerFrame[6]);
+  Serial.print("soil T: ");
+  Serial.println(temp / 10, DEC);
+
+  Serial.println(" ");
+  
+  // Get reading every 5 seconds
+  delay(5000);
+
+  /* TODO add a CRC check for the received data, i.e. take n-2 bytes of the answer,
+  calculate CRC, and then compare if it fist with the CRC bytes that were received.
+  */
+  
+}
diff --git a/code-snippets/client/soil_sensor_sentec/platformio.ini b/code-snippets/client/soil_sensor_sentec/platformio.ini
new file mode 100644
index 0000000000000000000000000000000000000000..0b77e00dd063100148dec39a48144938f45d1373
--- /dev/null
+++ b/code-snippets/client/soil_sensor_sentec/platformio.ini
@@ -0,0 +1,19 @@
+; PlatformIO Project Configuration File
+;
+;   Build options: build flags, source filter
+;   Upload options: custom upload port, speed and extra flags
+;   Library options: dependencies, extra library storages
+;   Advanced options: extra scripting
+;
+; Please visit documentation for the other options and examples
+; https://docs.platformio.org/page/projectconf.html
+
+[env:esp32-c3-devkitm-1]
+platform = espressif32
+board = esp32-c3-devkitm-1
+framework = arduino
+monitor_speed = 115000
+lib_deps = EspSoftwareSerial
+
+
+