Here's what's happening:
The platform provides the following set of standard profiles in every organization:
• Read Only
• Standard User
• Marketing User
• Contract Manager
• Solution Manager
• System Administrator
Each of these standard profiles includes a default set of permissions for all of the standard objects available on the platform.
When a custom object is created, most profiles (except those with “Modify All Data”) don't
give access to the object. You can find more detailed descriptions of all the standard profiles
in the online help, but the important thing to know is that you can never edit the object
permissions on a standard profile.
In essence, none of your standard profile users can see the custom object with the exception of you or someone else who's a system admin. That's why the permission set is necessary to begin with. As for why a read only user who has the permission set enabled for them still can't see the pages/custom objects, I'd suggest you check to see if one of your controllers has the ability to call another controller that has DML capabilities. I'd also suggest you look at any sharing that's configured for them as well which might affect their access.
I just finished looking at Chapter 7 of the material I referred you to again myself. I'm confident that you need to at least enable read-only field level access in the user profile for the user to see the custom object and the particular fields you want them to see. There's also a separate read-only access checkbox for your VF pages that will also need to be enabled for that user profile as well. Its possible those pages require a higher level of access than the profile/permission set combo is currently giving your user.
SF works based on a combination of profiles, permission sets and record sharing with the latter done primarily through role hierarchies (plus preferably minimal manual sharing). SF is very Profile driven, but all 3 are required for it to operate as intended in an org of any size. I believe you'll encounter numerous problems should you attempt to only use Permission Sets and not leverage them with Profiles and Roles
Everything in SF, with the exception of the Read-only User Profile, builds on the Standard User Profile as the most restrictive profile, then expands permissions from there. The Custom User Profile you've created needs to expand on your Standard User Profile to have read-only access to this new custom object. If you've omitted anything from your Custom User Profile that's in your Standard User Profile, that could be part of the problem you're having. If all your users need access to this custom object and certain custom fields within it, it would be normal practice to grant that through a field level security in a custom version (clone) of your Standard User Profile; not through a permission set.