I organized myself a measurement device and found out, that the tacho signal do only output very very small voltage levels - peek values were around 50mV. It is just as @herbschwarz said. Thank you for your advice! 
I just tested everything and it works great!
Here's my updated code:
#include <SAMD21turboPWM.h>
#include <WiFiNINA.h>
#include <PubSubClient.h>
#include "Credentials.h"
// define pins and timers
#define TACHO_PIN_A 9
#define TACHO_PIN_B 3
#define PWM_PIN_A 7
#define PWM_PIN_B 4
#define PWM_TIMER 1
// define variables to calculate RPM
unsigned long volatile lastTachoInterrupt_A = 0; // in ms
unsigned long volatile tachoInterruptDuration_A = 0; // In ms
unsigned long volatile rpm_A = 0;
unsigned long volatile lastTachoInterrupt_B = 0; // in ms
unsigned long volatile tachoInterruptDuration_B = 0; // In ms
unsigned long volatile rpm_B = 0;
int initializePwmValue = 500;
// define variables to connect with the mqtt server via WiFi
const char* ssid = networkSSID;
const char* password = networkPASSWORD;
const char* mqttServer = mqttSERVER;
const char* mqttUsername = mqttUSERNAME;
const char* mqttPassword = thingKEY;
const char* mqttDeviceId = thingID;
const int mqttPort = 1883;
const int publishingRate = 1000; // rate to publish in ms
// define mqtt pub/sub topics
char pwmSubTopic_A[] = "pwmDcControl_A";
char rpmPubTopic_A[] = "rpmState_A";
char pwmSubTopic_B[] = "pwmDcControl_B";
char rpmPubTopic_B[] = "rpmState_B";
// define global variables for mqtt calculations and/or operations
long lastMsg = 0;
TurboPWM pwm;
WiFiClient wifiClient;
PubSubClient client(wifiClient);
void setup_wifi()
{
delay(10);
Serial.println();
Serial.print("Connecting to wifi ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected.");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void reconnect()
{
while (!client.connected())
{
Serial.print("connecting to mqtt.tingg.io...");
if (client.connect(mqttDeviceId, mqttUsername, mqttPassword))
{
Serial.println("connected.");
client.subscribe(pwmSubTopic_A);
client.subscribe(pwmSubTopic_B);
}
else
{
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void callback(char* topic, byte* payload, unsigned int len)
{
Serial.print("topic: ");
Serial.println(topic);
Serial.print("message: ");
for (int i = 0; i < len; i++)
{
Serial.print((char)payload[i]);
}
Serial.println();
char tmpBuffer[128];
memcpy(tmpBuffer, payload, len);
tmpBuffer[len] = '\0';
// Convert it to integer
char *end = nullptr;
long value = strtol(tmpBuffer, &end, 10);
// Check for conversion errors
if (end == tmpBuffer)
{
Serial.println("Cannot convert payload to integer");
return; // Conversion error occurred
}
int pwmValue = (int)value;
// Clamp value between 0 and 1000
if (pwmValue > 1000) {
pwmValue = 1000;
}
else if (pwmValue < 0) {
pwmValue = 0;
}
const int start = (int)strlen(mqttDeviceId) + 1;
const int endIdx = (int)strlen(topic);
char normalizedTopic[128];
memcpy(normalizedTopic, &topic[start], endIdx);
// set pwms duty cycle to the input value
if (strcmp(normalizedTopic, pwmSubTopic_A) == 0) {
pwm.analogWrite(PWM_PIN_A, pwmValue);
}
else if (strcmp(normalizedTopic, pwmSubTopic_B) == 0) {
pwm.analogWrite(PWM_PIN_B, pwmValue);
}
}
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(PWM_PIN_A, OUTPUT);
pinMode(TACHO_PIN_A, INPUT_PULLUP);
pinMode(PWM_PIN_B, OUTPUT);
pinMode(TACHO_PIN_B, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(TACHO_PIN_A), tacho_A, FALLING);
attachInterrupt(digitalPinToInterrupt(TACHO_PIN_B), tacho_B, FALLING);
pwm.setClockDivider(1, false);
pwm.timer(PWM_TIMER, 1, 0x3c0, false);
pwm.enable(PWM_TIMER, true);
pwm.analogWrite(PWM_PIN_A, initializePwmValue);
pwm.analogWrite(PWM_PIN_B, initializePwmValue);
setup_wifi();
client.setServer(mqttServer, mqttPort);
client.setCallback(callback);
}
void loop() {
// put your main code here, to run repeatedly:
if (!client.connected())
{
reconnect();
}
client.loop();
long now = millis();
if (now - lastMsg > publishingRate)
{
lastMsg = now;
char payLoad_A[4];
itoa(rpm_A, payLoad_A, 10);
client.publish(rpmPubTopic_A, payLoad_A);
char payLoad_B[4];
itoa(rpm_B, payLoad_B, 10);
client.publish(rpmPubTopic_B, payLoad_B);
}
}
void tacho_A() {
unsigned long countMillis = millis();
tachoInterruptDuration_A = (countMillis - lastTachoInterrupt_A);
unsigned long freq = 1000 / tachoInterruptDuration_A; // Frequenz in Hz
rpm_A = (freq * 60) / 2;
lastTachoInterrupt_A = countMillis;
}
void tacho_B() {
unsigned long countMillis = millis();
tachoInterruptDuration_B = (countMillis - lastTachoInterrupt_B);
unsigned long freq = 1000 / tachoInterruptDuration_B; // Frequenz in Hz
rpm_B = (freq * 60) / 2;
lastTachoInterrupt_B = countMillis;
}
Also, I did not change anything in the circuit. But for the sake of completeness I will put the diagram in this answer, as well.
The pull up resistors are working fine with 1k ohm and I did not need any additional mosfets, level shifters or a resistor voltage divider.
I want to thank everyone that replied to this post and helped me improve my code and understanding the electronics around it more clearly! 