Fix an Android sensor app sending no values to CODESYS

8 min read · Published November 5, 2026

The Android sensor app sends a UDP telegram with no reply, so any fault on the path looks like silence. Install the store example, download only the receiver, match the receive network variable list exactly, keep the phone and controller on one subnet, and point the list at the subnet broadcast such as 192.168.1.255 on Linux-based controllers; watch wCounter to confirm each hop.

The sensor app on your Android phone runs, the controller runs, and the visualization stays empty with no error anywhere. The fix is concrete: put the phone and controller on one subnet, and set the receive list's broadcast address to the subnet-directed broadcast. Use 192.168.1.255 on a 192.168.1.x network with mask 255.255.255.0, because some Linux-based controllers ignore the limited broadcast 255.255.255.255.

That silence is how UDP network variables fail. The sender transmits and never waits for an answer, so a build fault, a list mismatch, a routing problem and a discarded broadcast all look identical from the outside. This article walks the path in the order the signal travels: the store example and its build, the receive list the app expects, the shared subnet, the broadcast address a Linux-based controller accepts, and a capture that tells you which side drops the telegram. Check wCounter after every change; it is the pass mark for every hop after the build.

Why does the Android sensor app send no values to the CODESYS controller?

Four faults produce this silence, and you fix them in data-path order: a build or download failure, a receive network variable list that does not match the sender list, the phone and controller on different networks, and a broadcast address the target's network stack discards.

Work the symptom first, because each one names its own section:

  • A wall of compile or download errors. The example still carries the netvarupd 3.5.5.0 library, or the compiler and visualization profiles were not updated for your target. Fix it in the install section.
  • The application runs, no error, no values. The receive list layout, the subnet or the broadcast address. Work the middle sections in order.
  • Works against a runtime on your engineering PC, fails on the controller. The target's stack handles the limited broadcast differently. Go to the broadcast address section.
  • wCounter stays at 0 through every change. The telegram never reaches the application, and the capture at the end decides between network and runtime.

What path does a sensor value take from the phone to the PLC?

The app sends one UDP telegram carrying a fixed global variable list. The controller accepts it only when a receive list with an identical layout is running in the application. Nothing replies, so a mismatch produces silence instead of an error.

Every value crosses five points, and each one fails in its own way:

Hop What happens What breaks it
1. Phone The app packs the sensor values into its fixed list and sends one UDP telegram Mobile data active, phone on another SSID, VLAN or subnet
2. Access point or switch The datagram is delivered inside the local network Client isolation, a guest SSID, a router hop between the devices
3. Controller network stack The interface receives the datagram on the configured port A broadcast address the stack discards, wrong interface, firewall rule
4. Runtime receive list The layout matches and the values land in the globals Variables, order, types or list identifier differ; application stopped
5. Visualization and logic Your code reads the updated globals A stale element, a hidden frame, logic that overwrites the globals

Check: before you go on, write down the IP address and mask of the phone and of the controller, and name the interface each one uses.

How do you install the store example and which device do you download?

Install the SensorAppForAndroid package from the CODESYS Store, open AndroidSensorApp.project 1.4.0.0 from the CODESYS Examples folder in your user profile, run the project update for your controller, remove the netvarupd 3.5.5.0 library, and download only the second device, the receiver.

Start from the store project: a hand-built receive list has to match the list compiled into the app exactly, and the example already does.

  1. Install the SensorAppForAndroid package from the CODESYS Store.
  2. Open c:\Users\<yourwindowsusername>\CODESYS Examples\SensorAppForAndroid\1.4.0.0\AndroidSensorApp.project.
  3. Right-click the project in the tree, run the project update for your controller, then set the current compiler version and the current visualization profile.
  4. Open the library manager and delete the netvarupd 3.5.5.0 library; on the next build the compiler pulls in the current version. Leaving this old version in is what produces the pile of download errors.
  5. Download only the second device, the receiver. The DataGenerator application above it is a placeholder whose only job is to expose the sender list as a receive list.

Check: the build ends with zero errors in the message view and the receiver application is in run on the controller. If errors pile up at download, go back to steps 3 and 4.

Does the receive network variable list match the sender list exactly?

The receiver must declare the same variables, in the same order, with the same types as the list compiled into the app, down to STRING(70); a different order or string length changes the telegram layout, and the runtime reads shifted bytes or nothing.

The sender list in the example looks like this:

//This global variable list is received via the network.
//Sender: NVL [SensorDataGenerator: PLC Logic: DataGenerator]
//Protocol: UDP
VAR_GLOBAL
 wVersion : WORD := 16#00_01;
 wCounter : WORD;
 dwFeatures : DWORD;
 Data : SensorValues;
 strCommand : STRING(70);
END_VAR

The app serializes the list as a packed block, so a different variable order, a different SensorValues structure or any other string length changes the telegram layout. Compare four settings in the NVL properties of both sides: protocol (UDP), list identifier, port, and the setting that packs the variables. All four are fixed on the app side, so the receive list in your project is the side you align.

Check: go online with the receiver and watch wCounter. It increments while the app sends. At 0, the telegram is not being accepted, and the next two sections own the problem.

Do the phone and the PLC have to be in the same network?

Both devices need addresses in one shared subnet, because the app sends into its local network and UDP broadcasts do not cross a router; check the path with a ping in both directions before you change any list or address setting.

Test Pass means Fail points to
Ping the controller from a PC on the same LAN The controller's interface and addressing are sound Wrong IP or mask, a down interface, a cabling fault
Ping the phone from that PC The access point bridges Wi-Fi to the LAN in both directions Client isolation, a guest SSID, a separate VLAN
Mobile data off, Wi-Fi on, app in the foreground The app sends through the LAN interface The phone hands the telegram to the mobile interface

A phone hotspot can serve as that shared network for a bench test; a plain LAN is easier because a PC on it can ping each side while you work. If the controller itself will not answer on the network at all, work through the fix for a CODESYS scan that cannot find a runtime on the network first, because reachability comes before every list setting.

Check: ping succeeds from the PC to the phone and back before you touch any list setting.

Which broadcast address does a Linux-based PLC accept?

Enter the subnet-directed broadcast address, the highest address in your subnet, for example 192.168.1.255 for a 192.168.1.x network with mask 255.255.255.0, because some Linux-based controllers do not act on the limited broadcast 255.255.255.255.

Compute it instead of guessing:

subnet broadcast = host address OR (NOT subnet mask)
192.168.1.x with 255.255.255.0 gives 192.168.1.255

The limited broadcast and the directed broadcast explain the classic pattern: the same app and project work against a runtime on the engineering PC and stay silent on a Linux-based controller, because the two stacks treat 255.255.255.255 differently. Confirm while you are in the controller documentation that the runtime supports network variable lists at all; the manufacturer's feature list names that support. Treat the address change as one fault of four: if wCounter stays at 0 after it, continue with the capture in the last section.

Check: after the change, rebuild, download and watch wCounter again.

Worked example: which address do you enter on a 192.168.1.0 network?

A phone at 192.168.1.42 and a controller at 192.168.1.10 on mask 255.255.255.0 need the broadcast address 192.168.1.255 in the receive list, which you compute by ORing the address with the inverted mask 0.0.0.255.

Invert the mask byte by byte, then OR it with any address in the subnet:

Mask        255.255.255.  0
NOT mask      0.  0.  0.255
Host        192.168.  1. 42
Broadcast   192.168.  1.255

Every host in the subnet ORs to the same address, which is why one setting serves the whole network and why the phone's exact address is irrelevant here.

A smaller /28 subnet confirms the method with a different mask:

Mask        255.255.255.240
NOT mask      0.  0.  0. 15
Host        192.168.  1. 34      (34 = 00100010)
Broadcast   192.168.  1. 47      (00100010 OR 00001111 = 00101111)

Enter the result in the broadcast address setting of the receive list, rebuild, download, and watch wCounter.

Scenario: from a working feed to a screen the shift can read

Once wCounter increments and the values land, the same feed usually moves onto a status screen on the floor. Size the text for the distance people read it from. The planning figure is 30 ft of viewing distance per inch of letter height, with 1.7 x the capital height as line spacing; 20 ft per inch is the safer choice for fast reading.

Say a line of sensor values must be read from 20 ft. At the planning figure that is 20 ft / 30 ft per inch = 0.67 in of capital height. At the safer figure it is 20 ft / 20 ft per inch = 1.0 in. Set the text between 0.67 in and 1.0 in on the actual screen, and check the result from the real distance before you lock the layout.

What does a Wireshark capture show when wCounter stays at 0?

A capture on the controller's side of the network splits the fault in two: telegrams arriving point at the list or the application, and no telegrams point at the phone, the access point or the address.

Capture where the broadcast is visible: a mirror port on the switch the controller plugs into, or a PC on the same segment. Filter on UDP and the phone's IP address, run the app, and read the result against this table:

Capture shows Where the fault sits Next move
No UDP from the phone at all Phone, app or access point Ping both ways, mobile data off, isolation off
UDP present, destination is not the controller's subnet The address in the list Set the directed broadcast, rebuild, download
UDP present, destination correct, wCounter still at 0 Inside the controller Diff the two lists variable for variable and confirm the runtime supports network variables

When telegrams arrive but the values never appear, the fault sits inside the controller, and capturing logs on an embedded Linux device that freezes shows how to record what the Linux side actually does while you reproduce the fault. Once wCounter increments, the same feed can drive a bigger board than a phone: planning an offline sensor status display for your shop floor takes live values to a status screen the whole shift can read.

Recommendation: build from the SensorAppForAndroid example, download only the receiver, and treat wCounter as the pass mark after every change. Keep the phone and controller on one plain subnet for the bench test, and set the receive list to the subnet-directed broadcast such as 192.168.1.255 before the first download to a Linux-based controller. If a capture then shows telegrams arriving with wCounter still at 0, the list layout is the remaining fault, so compare the two lists line by line: same variables, same order, same types, same string length.

Questions

Why does nothing arrive even though the Wi-Fi works?

The phone can hold Wi-Fi and mobile data at the same time, and Android may hand the telegram to the mobile interface, which cannot reach the controller. Switch mobile data off, reopen the app, and check in your capture that the source address is the phone's Wi-Fi address, not a mobile one.

Can the app send my own variables instead of the phone's sensors?

No. The list compiled into the app is fixed, and the receive side has to match it, which is why the example project is the starting point. To move your own values, create a sending network variable list in your own application, then build a receive list in the controller that mirrors it variable for variable, in the same order and with the same types.

Can one phone feed two controllers at the same time?

Yes, on one subnet. The telegram is a broadcast, so every runtime on that subnet with a matching receive list listening on the same port receives the same values; give each controller its own receive list. The telegrams stop at a router, so a controller on another subnet needs its own sender on that subnet.

Planning information, not legal or engineering advice. Rules differ by place: check codes and permits with your local authority and your licensed trades.

Keep reading

Build your signAsk for a quote